public function checkForRecreation(array $ids, $contract)
 {
     //we should delete from recent to old
     //we should create from old to recent
     //then compare correctly...
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         $forTrace = $contract->id . ' ' . print_r($ids, true);
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' for: ' . $forTrace);
     }
     $this->_autoInvoiceIterationDetailResults = array();
     $this->_autoInvoiceIterationResults = array();
     $this->_autoInvoiceRecreationResults = array();
     $oldInvoices = array();
     $oldPositions = array();
     $somethingChanged = false;
     $failed = false;
     $transactionId = Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
     $invoicePositionController = Sales_Controller_InvoicePosition::getInstance();
     foreach ($ids as $id) {
         $invoice = $this->get($id);
         if (!$invoice) {
             Tinebase_Core::getLogger()->err(__METHOD__ . '::' . __LINE__ . ' can not ::get invoice with id: ' . $id);
             continue;
         }
         $invoice->setTimezone(Tinebase_Core::getUserTimezone());
         $oldInvoices[] = $invoice;
         $filter = new Sales_Model_InvoicePositionFilter(array());
         $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'invoice_id', 'operator' => 'equals', 'value' => $invoice->getId())));
         $oldPositions[$invoice->getId()] = $invoicePositionController->search($filter);
         try {
             $this->delete(array($invoice));
         } catch (Sales_Exception_DeletePreviousInvoice $sedpi) {
             $failed = true;
             Tinebase_Core::getLogger()->err(__METHOD__ . '::' . __LINE__ . ' could not delete invoice with id: ' . $id);
             break;
         }
         //is $invoice still valid?!?!?
     }
     if (true === $failed) {
         Tinebase_TransactionManager::getInstance()->rollBack();
         return;
     }
     // reload relations as they may have changed as we deleted the invoices above
     // TODO: could be made more efficient as we just need to reload releationsa actually and not the whole contract.
     $contract = Sales_Controller_Contract::getInstance()->get($contract->getId());
     $this->_currentBillingContract = $contract;
     $this->_currentBillingContract->setTimezone(Tinebase_Core::getUserTimezone());
     // the newest invoice!
     $date = clone $oldInvoices[0]->date;
     // date seems not to have a tz, so after the clone, the tz is UTC!! we need to reset it
     $date->setTimezone(Tinebase_Core::getUserTimezone());
     $this->_createAutoInvoicesForContract($this->_currentBillingContract, $date);
     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' deleted ' . count($oldInvoices) . ' and recreated ' . count($this->_autoInvoiceIterationDetailResults) . ' invoices for: ' . $forTrace);
     }
     if (count($oldInvoices) !== count($this->_autoInvoiceIterationDetailResults)) {
         // something changed for sure. fine, commit => done
         $somethingChanged = true;
     } else {
         // WE NEED TO DIFF POSITIONS TOO! diff on invoice does not do a diff on the positions!
         // if diff on invoice is negative, then check the positions
         foreach ($this->_autoInvoiceIterationDetailResults as $newInvoice) {
             $diff = null;
             foreach ($oldInvoices as $oldInvoice) {
                 if ($newInvoice->date->equals($oldInvoice->date)) {
                     $diff = $newInvoice->diff($oldInvoice, array('description', 'id', 'relations', 'contract', 'customer', 'created_by', 'creation_time', 'last_modified_by', 'last_modified_time'));
                     //if nothing changed, check the invoice positions
                     if ($diff->isEmpty()) {
                         $filter = new Sales_Model_InvoicePositionFilter(array());
                         $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'invoice_id', 'operator' => 'equals', 'value' => $newInvoice->getId())));
                         $newPositions = $invoicePositionController->search($filter);
                         $i = 0;
                         foreach ($oldPositions[$invoice->getId()] as $oldPosition) {
                             if ($i + 1 > $newPositions->count()) {
                                 $diff = null;
                                 break;
                             }
                             $newPosition = $newPositions->getByIndex($i++);
                             $diff = $newPosition->diff($oldPosition, array('id', 'invoice_id'));
                             if (!$diff->isEmpty()) {
                                 break;
                             }
                         }
                     }
                     break;
                 }
             }
             // null === $diff means that we could not match the new Invoice to the old one, though the count of invoices seems not to have changed
             if (null === $diff || !$diff->isEmpty()) {
                 if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
                     Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' something changed with $diff = ' . (null === $diff ? 'null' : print_r($diff->toArray(), true)) . ' for: ' . $forTrace);
                 }
                 $somethingChanged = true;
                 break;
             }
         }
     }
     if (true === $somethingChanged) {
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' something changed for: ' . $forTrace);
         }
         Tinebase_TransactionManager::getInstance()->commitTransaction($transactionId);
         //create mapping of old to new invoices
         foreach ($this->_autoInvoiceIterationDetailResults as $newInvoice) {
             foreach ($oldInvoices as $oldInvoice) {
                 if ($newInvoice->date->equals($oldInvoice->date)) {
                     $this->_autoInvoiceRecreationResults[$oldInvoice->getId()] = $newInvoice->getId();
                 }
             }
         }
     } else {
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' nothing changed for: ' . $forTrace);
         }
         Tinebase_TransactionManager::getInstance()->rollBack();
     }
 }
 /**
  * create contracts, auto add timeaccounts if there are any
  * 
  * @param array $contractData
  * @return Tinebase_Record_RecordSet
  */
 protected function _createContracts($contractData = NULL)
 {
     // 1.1.20xx
     $startDate = clone $this->_referenceDate;
     $endDate = clone $startDate;
     // 1.8.20xx
     $endDate->addMonth(7);
     $this->_contractController = Sales_Controller_Contract::getInstance();
     $container = $this->_contractController->getSharedContractsContainer();
     $this->_sharedContractsContainerId = $container->getId();
     if (!$contractData) {
         if (!$this->_costcenterRecords) {
             $this->_createCostCenters();
         }
         if (!$this->_productRecords) {
             $this->_createProducts();
         }
         if (!$this->_customerRecords) {
             $this->_createCustomers();
         }
         if (!$this->_timesheetRecords) {
             $this->_createTimesheets();
         }
         $contractData = array(array('number' => 1, 'title' => Tinebase_Record_Abstract::generateUID(), 'description' => '1 unittest begin', 'container_id' => $this->_sharedContractsContainerId, 'billing_address_id' => $this->_addressRecords->filter('customer_id', $this->_customerRecords->filter('name', 'Customer1')->getFirstRecord()->getId())->filter('type', 'billing')->getFirstRecord()->getId(), 'start_date' => clone $startDate, 'end_date' => NULL, 'products' => array(array('start_date' => $startDate, 'end_date' => NULL, 'quantity' => 1, 'interval' => 1, 'billing_point' => 'begin', 'product_id' => $this->_productRecords->filter('name', 'Hours')->getFirstRecord()->getId()))), array('number' => 2, 'title' => Tinebase_Record_Abstract::generateUID(), 'description' => '2 unittest end', 'container_id' => $this->_sharedContractsContainerId, 'billing_address_id' => $this->_addressRecords->filter('customer_id', $this->_customerRecords->filter('name', 'Customer2')->getFirstRecord()->getId())->filter('type', 'billing')->getFirstRecord()->getId(), 'start_date' => clone $startDate, 'end_date' => clone $endDate, 'products' => array(array('start_date' => clone $startDate, 'end_date' => clone $endDate, 'quantity' => 1, 'interval' => 4, 'billing_point' => 'end', 'product_id' => $this->_productRecords->filter('name', 'Hours')->getFirstRecord()->getId()))), array('number' => 3, 'title' => Tinebase_Record_Abstract::generateUID(), 'description' => '3 unittest end', 'container_id' => $this->_sharedContractsContainerId, 'billing_address_id' => $this->_addressRecords->filter('customer_id', $this->_customerRecords->filter('name', 'Customer3')->getFirstRecord()->getId())->filter('type', 'billing')->getFirstRecord()->getId(), 'start_date' => clone $startDate, 'end_date' => NULL, 'products' => array(array('start_date' => clone $startDate, 'end_date' => NULL, 'quantity' => 1, 'interval' => 3, 'billing_point' => 'end', 'product_id' => $this->_productRecords->filter('name', 'Hours')->getFirstRecord()->getId()))), array('number' => 4, 'title' => Tinebase_Record_Abstract::generateUID(), 'description' => '4 unittest products', 'container_id' => $this->_sharedContractsContainerId, 'billing_address_id' => $this->_addressRecords->filter('customer_id', $this->_customerRecords->filter('name', 'Customer4')->getFirstRecord()->getId())->filter('type', 'billing')->getFirstRecord()->getId(), 'start_date' => clone $startDate, 'end_date' => NULL, 'products' => array(array('start_date' => clone $startDate, 'end_date' => NULL, 'quantity' => 1, 'interval' => 6, 'billing_point' => 'begin', 'product_id' => $this->_productRecords->filter('name', 'billhalfyearly')->getFirstRecord()->getId()), array('start_date' => clone $startDate, 'end_date' => NULL, 'quantity' => 1, 'interval' => 3, 'billing_point' => 'begin', 'product_id' => $this->_productRecords->filter('name', 'billeachquarter')->getFirstRecord()->getId()))));
     }
     $this->_contractRecords = new Tinebase_Record_RecordSet('Sales_Model_Contract');
     $i = 0;
     foreach ($contractData as $cd) {
         $costcenter = $this->_costcenterRecords->getByIndex($i);
         $customer = $this->_customerRecords->getByIndex($i);
         if ($this->_timeaccountRecords) {
             $timeaccount = $this->_timeaccountRecords->getByIndex($i);
         }
         $i++;
         $contract = new Sales_Model_Contract($cd);
         $contract->setTimezone('UTC');
         $contract->relations = array(array('own_model' => 'Sales_Model_Contract', 'own_backend' => Tasks_Backend_Factory::SQL, 'own_id' => NULL, 'related_degree' => Tinebase_Model_Relation::DEGREE_SIBLING, 'related_model' => 'Sales_Model_CostCenter', 'related_backend' => Tasks_Backend_Factory::SQL, 'related_id' => $costcenter->getId(), 'type' => 'LEAD_COST_CENTER'), array('own_model' => 'Sales_Model_Contract', 'own_backend' => Tasks_Backend_Factory::SQL, 'own_id' => NULL, 'related_degree' => Tinebase_Model_Relation::DEGREE_SIBLING, 'related_model' => 'Sales_Model_Customer', 'related_backend' => Tasks_Backend_Factory::SQL, 'related_id' => $customer->getId(), 'type' => 'CUSTOMER'));
         if ($this->_timeaccountRecords) {
             $contract->relations = array_merge($contract->relations, array(array('own_model' => 'Sales_Model_Contract', 'own_backend' => Tasks_Backend_Factory::SQL, 'own_id' => NULL, 'related_degree' => Tinebase_Model_Relation::DEGREE_SIBLING, 'related_model' => 'Timetracker_Model_Timeaccount', 'related_backend' => Tasks_Backend_Factory::SQL, 'related_id' => $timeaccount->getId(), 'type' => 'TIME_ACCOUNT')));
         }
         $this->_contractRecords->addRecord($this->_contractController->create($contract));
     }
     return $this->_contractRecords;
 }