/**
  * creates invoice positions by the billables per each month
  * 
  * @param array $billables
  * @param Sales_Model_Accountable_Interface $accountable
  * @return Tinebase_Record_RecordSet
  */
 protected function _getInvoicePositionsFromBillables(array $billables, Sales_Model_Accountable_Interface $accountable)
 {
     $invoicePositions = new Tinebase_Record_RecordSet('Sales_Model_InvoicePosition');
     foreach ($billables as $month => $billablesPerMonth) {
         if ($accountable->sumBillables()) {
             $sumQuantity = 0.0;
             foreach ($billablesPerMonth as $billable) {
                 $qty = $billable->getQuantity();
                 $sumQuantity = $sumQuantity + $qty;
             }
             $pos = array('month' => $month, 'model' => get_class($accountable), 'accountable_id' => $accountable->getId(), 'title' => $accountable->getTitle(), 'quantity' => $sumQuantity, 'unit' => $billable->getUnit());
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->log(__METHOD__ . '::' . __LINE__ . ' Create invoice position ' . print_r($pos, 1) . ' for contract: ' . $this->_currentBillingContract->getId(), Zend_Log::DEBUG);
             }
             $invoicePositions->addRecord(new Sales_Model_InvoicePosition($pos));
         } else {
             foreach ($billablesPerMonth as $billable) {
                 $pos = array('month' => $month, 'model' => get_class($accountable), 'accountable_id' => $accountable->getId(), 'title' => $accountable->getTitle(), 'quantity' => $billable->getQuantity(), 'unit' => $billable->getUnit());
                 if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                     Tinebase_Core::getLogger()->log(__METHOD__ . '::' . __LINE__ . ' Create invoice position ' . print_r($pos, 1), Zend_Log::DEBUG);
                 }
                 $invoicePositions->addRecord(new Sales_Model_InvoicePosition($pos));
             }
         }
     }
     return $invoicePositions;
 }
 /**
  * returns timeaccount-contract relation
  * @param Sales_Model_Contract $contract
  * @param Timetracker_Model_Timeaccount $timeaccount
  */
 protected function _getRelation($contract, $timeaccount)
 {
     $r = new Tinebase_Model_Relation();
     $ra = array('own_model' => 'Timetracker_Model_Timeaccount', 'own_backend' => 'Sql', 'own_id' => $timeaccount->getId(), 'related_degree' => 'sibling', 'remark' => 'phpunit test', 'related_model' => 'Sales_Model_Contract', 'related_backend' => 'Sql', 'related_id' => $contract->getId(), 'type' => 'CONTRACT');
     $r->setFromArray($ra);
     return $r;
 }
 /**
  * merges source contracts into the target contract (relations and products)
  * 
  * @param Sales_Model_Contract $targetContract
  * @param Tinebase_Record_RecordSet $sourceContracts
  */
 public function mergeContracts(Sales_Model_Contract $targetContract, Tinebase_Record_RecordSet $sourceContracts)
 {
     // handle relations (duplicates get skipped)
     foreach ($sourceContracts as $sourceContract) {
         Tinebase_Relations::getInstance()->transferRelations($sourceContract->getId(), $targetContract->getId(), 'Sales_Model_Contract');
     }
     // handle products
     $filter = new Sales_Model_ProductAggregateFilter(array());
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'in', 'value' => $sourceContracts->getId())));
     $products = Sales_Controller_ProductAggregate::getInstance()->search($filter);
     foreach ($products as $product) {
         $product->contract_id = $targetContract->getId();
         Sales_Controller_ProductAggregate::getInstance()->update($product);
     }
     return true;
 }
 /**
  * removes unbilled auto invoices
  * 
  * @param Sales_Model_Contract $contract
  */
 public function removeUnbilledAutoInvoices(Sales_Model_Contract $contract = NULL)
 {
     if (!Sales_Config::getInstance()->featureEnabled(Sales_Config::FEATURE_INVOICES_MODULE)) {
         Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' removeUnbilledAutoInvoices ran allthoug feature ' . Sales_Config::FEATURE_INVOICES_MODULE . ' is disabled');
         return false;
     }
     $c = Sales_Controller_Invoice::getInstance();
     $f = new Sales_Model_InvoiceFilter(array(array('field' => 'is_auto', 'operator' => 'equals', 'value' => TRUE), array('field' => 'cleared', 'operator' => 'not', 'value' => 'CLEARED')), 'AND');
     if ($contract) {
         $subf = new Tinebase_Model_Filter_ExplicitRelatedRecord(array('field' => 'contract', 'operator' => 'AND', 'value' => array(array('field' => ':id', 'operator' => 'equals', 'value' => $contract->getId())), 'options' => array('controller' => 'Sales_Controller_Contract', 'filtergroup' => 'Sales_Model_ContractFilter', 'own_filtergroup' => 'Sales_Model_InvoiceFilter', 'own_controller' => 'Sales_Controller_Invoice', 'related_model' => 'Sales_Model_Contract')));
         $f->addFilter($subf);
     }
     $p = new Tinebase_Model_Pagination(array('sort' => 'start_date', 'dir' => 'DESC'));
     $invoiceIds = $c->search($f, $p, false, true);
     if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' About to delete ' . count($invoiceIds) . ' uncleared invoices ...');
     }
     foreach ($invoiceIds as $invoiceId) {
         try {
             $c->delete(array($invoiceId));
         } catch (Sales_Exception_DeletePreviousInvoice $sedpi) {
             Tinebase_Exception::log($sedpi);
         }
     }
 }
 /**
  * set relations for contract
  * 
  * @param array|Sales_Model_Contract $contract
  * @param array $contacts
  * @param string $type
  */
 protected function _setContractRelations($contract, $contacts, $type = 'PARTNER')
 {
     $relationData = array();
     foreach ($contacts as $contact) {
         $relationData[] = array('own_degree' => 'sibling', 'related_degree' => 'sibling', 'related_model' => 'Addressbook_Model_Contact', 'related_backend' => 'Sql', 'related_id' => $contact->getId(), 'type' => $type);
     }
     $contractId = $contract instanceof Sales_Model_Contract ? $contract->getId() : $contract['id'];
     Tinebase_Relations::getInstance()->setRelations('Sales_Model_Contract', 'Sql', $contractId, $relationData);
 }
 /**
  * returns a temporarily productaggregate which contains the
  * default billing information of this accountable
  * 
  * @param Sales_Model_Contract $contract
  * @return Sales_Model_ProductAggregate
  */
 public function getDefaultProductAggregate(Sales_Model_Contract $contract)
 {
     $startDate = clone $contract->start_date;
     if ($contract->start_date->format('d') !== 1) {
         $startDate->setDate($startDate->format('Y'), $startDate->format('m'), 1);
     }
     $accountable = get_class($this);
     $filter = new Sales_Model_ProductFilter(array(array('field' => 'accountable', 'operator' => 'equals', 'value' => $accountable)));
     $product = Sales_Controller_Product::getInstance()->search($filter)->getFirstRecord();
     // create product, if no product is found
     if (!$product) {
         if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' . ' Create Product for ' . $accountable);
         }
         $product = Sales_Controller_Product::getInstance()->create(new Sales_Model_Product(array('name' => $accountable, 'accountable' => $accountable, 'description' => 'auto generated on invoicing')));
     }
     if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' . ' Create ProductAggregate for ' . $accountable . ' contract: ' . $contract->getId());
     }
     $endDate = clone $startDate;
     $endDate->addMonth($this->_defaultInterval);
     $pa = new Sales_Model_ProductAggregate(array('interval' => $this->_defaultInterval, 'billing_point' => $this->_defaultBillingPoint, 'contract_id' => $contract->getId(), 'start_date' => $startDate, 'end_date' => NULL, 'last_autobill' => NULL, 'product_id' => $product->getId(), 'quantity' => $product->accountable ? NULL : 1));
     return $pa;
 }
 /**
  * creates the auto invoices, gets called by cli
  * 
  * @param Tinebase_DateTime $currentDate
  * @param Sales_Model_Contract $contract
  */
 public function createAutoInvoices(Tinebase_DateTime $currentDate, Sales_Model_Contract $contract = NULL)
 {
     $this->_autoInvoiceIterationResults = array();
     $this->_autoInvoiceIterationFailures = array();
     $contractBackend = new Sales_Backend_Contract();
     $ids = $contract ? array($contract->getId()) : $contractBackend->getBillableContractIds($currentDate);
     $filter = new Sales_Model_ContractFilter(array());
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'id', 'operator' => 'in', 'value' => $ids)));
     $iterator = new Tinebase_Record_Iterator(array('iteratable' => $this, 'controller' => Sales_Controller_Contract::getInstance(), 'filter' => $filter, 'options' => array('getRelations' => TRUE, 'limit' => $this->_autoInvoiceIterationLimit), 'function' => 'processAutoInvoiceIteration'));
     $iterator->iterate($currentDate);
     $result = array('failures' => $this->_autoInvoiceIterationFailures, 'failures_count' => count($this->_autoInvoiceIterationFailures), 'created' => $this->_autoInvoiceIterationResults, 'created_count' => count($this->_autoInvoiceIterationResults));
     return $result;
 }