コード例 #1
0
 /**
  * returns the product aggregate for a given accountable
  * 
  * @param Sales_Model_Accountable_Interface $record
  */
 public function findProductAggregate(Sales_Model_Accountable_Interface $record)
 {
     $accountableClassName = get_class($record);
     $filter = new Sales_Model_ProductFilter(array());
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'accountable', 'operator' => 'equals', 'value' => $accountableClassName)));
     $products = Sales_Controller_Product::getInstance()->search($filter);
     $filter = new Sales_Model_ProductAggregateFilter(array());
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'product_id', 'operator' => 'in', 'value' => $products->getId())));
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'equals', 'value' => $this->getId())));
     $pas = Sales_Controller_ProductAggregate::getInstance()->search($filter);
     if ($pas->count() < 1) {
         throw new Tinebase_Exception_Data('A contract aggregate could not be found!');
     } elseif ($pas->count() > 1) {
         throw new Tinebase_Exception_Data('At the moment a contract may have only one product aggregate for the same product, not more!');
     }
     return $pas->getFirstRecord();
 }
 /**
  * add body rows
  * 
  * @alternate, kind of POC or VIP, overwrites the default one
  *
  * @param Tinebase_Record_RecordSet $records
  */
 public function processIteration($_records)
 {
     $json = new Tinebase_Convert_Json();
     $productAggregateIds = $_records->accountable_id;
     $paFilter = new Sales_Model_ProductAggregateFilter();
     $paFilter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'id', 'operator' => 'in', 'value' => $productAggregateIds)));
     $productAggregates = Sales_Controller_ProductAggregate::getInstance()->search($paFilter);
     $pFilter = new Sales_Model_ProductFilter();
     $pFilter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'id', 'operator' => 'in', 'value' => array_unique($productAggregates->product_id))));
     $products = Sales_Controller_Product::getInstance()->search($pFilter);
     $resolved = $json->fromTine20RecordSet($_records);
     foreach ($resolved as $record) {
         $record['accountable_id'] = $productAggregates->getById($record['accountable_id'])->toArray();
         $record['product_id'] = $products->getById($record['accountable_id']['product_id'])->toArray();
         $row = $this->_activeTable->appendRow();
         $i18n = $this->_translate->getAdapter();
         foreach ($this->_config->columns->column as $field) {
             $identifier = $field->identifier;
             // TODO: use ModelConfig here to get the POC
             // get type and value for cell
             $cellType = $this->_getCellType($field->type);
             switch ($identifier) {
                 case 'quantity':
                     $value = intval($record[$identifier]) * intval($record['accountable_id']['quantity']);
                     break;
                 case 'month':
                     $value = $record[$identifier];
                     break;
                 default:
                     $value = $record['product_id'][$identifier];
             }
             // create cell with type and value and add style
             $cell = $row->appendCell($value, $cellType);
             if ($field->customStyle) {
                 $cell->setStyle((string) $field->customStyle);
             }
         }
     }
 }
 /**
  * tests adding and removing of products to a contract
  */
 public function testAddDeleteProducts()
 {
     $prodTest = new Sales_ProductControllerTest();
     $productOne = $prodTest->testCreateProduct();
     $productTwo = $prodTest->testCreateProduct();
     $contractData = $this->_getContract();
     $contractData->products = array(array('product_id' => $productOne->getId(), 'quantity' => 1, 'interval' => 1, 'billing_point' => 1), array('product_id' => $productTwo->getId(), 'quantity' => 1, 'interval' => 1, 'billing_point' => 1));
     $this->_backend->create($contractData);
     $contract = $this->_backend->get($contractData->getId());
     // checks
     $this->assertEquals($contractData->getId(), $contract->getId());
     $this->assertGreaterThan(0, $contract->number);
     $this->assertEquals(Tinebase_Core::getUser()->getId(), $contract->created_by);
     // check count of product aggregates
     $filter = new Sales_Model_ProductAggregateFilter(array());
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'equals', 'value' => $contract->getId())));
     $productAggregates = Sales_Controller_ProductAggregate::getInstance()->search($filter);
     $this->assertEquals(2, count($productAggregates));
     $contractData->products = array(array('product_id' => $productOne->getId(), 'quantity' => 1, 'interval' => 1, 'billing_point' => 1));
     $this->_backend->update($contractData);
     $contract = $this->_backend->get($contractData->getId());
     // check count of product aggregates
     $filter = new Sales_Model_ProductAggregateFilter(array());
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'equals', 'value' => $contract->getId())));
     $productAggregates = Sales_Controller_ProductAggregate::getInstance()->search($filter);
     $this->assertEquals(1, count($productAggregates));
     // cleanup
     $this->_backend->delete($contract->getId());
     $this->_decreaseNumber();
     $prodTest->getUit()->delete(array($productOne->getId(), $productTwo->getId()));
 }
 public function testInvoiceRecreation()
 {
     $result = $this->_createInvoiceUpdateRecreationFixtures();
     $oldInvoiceId0 = $result['created'][0];
     $ipc = Sales_Controller_InvoicePosition::getInstance();
     $f = new Sales_Model_InvoicePositionFilter(array(array('field' => 'invoice_id', 'operator' => 'AND', 'value' => array(array('field' => 'id', 'operator' => 'equals', 'value' => $oldInvoiceId0)))));
     $positions = $ipc->search($f);
     $this->assertEquals(9, $positions->count());
     $oldInvoiceId1 = $result['created'][1];
     $ipc = Sales_Controller_InvoicePosition::getInstance();
     $f = new Sales_Model_InvoicePositionFilter(array(array('field' => 'invoice_id', 'operator' => 'AND', 'value' => array(array('field' => 'id', 'operator' => 'equals', 'value' => $oldInvoiceId1)))));
     $positions = $ipc->search($f);
     $this->assertEquals(4, $positions->count());
     $contract4 = $this->_contractRecords->getByIndex(3);
     $filter = new Sales_Model_ProductAggregateFilter(array(array('field' => 'interval', 'operator' => 'equals', 'value' => 3)), 'AND');
     $filter->addFilter(new Tinebase_Model_Filter_ForeignId(array('field' => 'contract_id', 'operator' => 'AND', 'value' => array(array('field' => ':id', 'operator' => 'equals', 'value' => $contract4->getId())), 'options' => array('controller' => 'Sales_Controller_Contract', 'filtergroup' => 'Sales_Model_ContractFilter', 'modelName' => 'Sales_Model_Contract'))));
     $pA = Sales_Controller_ProductAggregate::getInstance()->search($filter);
     $this->assertEquals(1, $pA->count());
     $pA = $pA->getFirstRecord();
     $pA->interval = 4;
     Sales_Controller_ProductAggregate::getInstance()->update($pA);
     $contract4->title = $contract4->getTitle() . ' changed';
     sleep(1);
     $this->_contractController->update($contract4);
     $this->sharedTimesheet->id = NULL;
     $this->_timesheetController->create($this->sharedTimesheet);
     $result = $this->_invoiceController->checkForContractOrInvoiceUpdates();
     $this->assertEquals(true, count($result) === 2 || count($result) === 3);
     $mapping = $this->_invoiceController->getAutoInvoiceRecreationResults();
     $this->assertEquals(true, isset($mapping[$oldInvoiceId0]));
     $this->assertEquals(true, isset($mapping[$oldInvoiceId1]));
     $newInvoiceId0 = $mapping[$oldInvoiceId0];
     $newInvoiceId1 = $mapping[$oldInvoiceId1];
     $this->assertNotEquals($oldInvoiceId0, $newInvoiceId0);
     $this->assertNotEquals($oldInvoiceId1, $newInvoiceId1);
     $this->_checkInvoiceUpdateExistingTimeaccount($newInvoiceId1);
     $f = new Sales_Model_InvoicePositionFilter(array(array('field' => 'invoice_id', 'operator' => 'AND', 'value' => array(array('field' => 'id', 'operator' => 'equals', 'value' => $newInvoiceId0)))));
     $positions = $ipc->search($f);
     $this->assertEquals(10, $positions->count());
     $f = new Sales_Model_InvoicePositionFilter(array(array('field' => 'invoice_id', 'operator' => 'AND', 'value' => array(array('field' => 'id', 'operator' => 'equals', 'value' => $newInvoiceId1)))));
     $positions = $ipc->search($f);
     $this->assertEquals(1, $positions->count());
 }
コード例 #5
0
 /**
  * finds product aggregates for $this->_currentBillingContract
  * 
  * @return Tinebase_Record_RecordSet
  */
 protected function _findProductAggregates()
 {
     $filter = new Sales_Model_ProductAggregateFilter(array());
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'equals', 'value' => $this->_currentBillingContract->getId())));
     $productAggregates = Sales_Controller_ProductAggregate::getInstance()->search($filter);
     $productAggregates->setTimezone(Tinebase_Core::getUserTimezone());
     return $productAggregates;
 }
コード例 #6
0
 /**
  * processUpdateBillingInformation
  * 
  * @param Tinebase_Record_RecordSet $contracts
  */
 public function processUpdateLastAutobillOfProductAggregates(Tinebase_Record_RecordSet $contracts)
 {
     $now = Tinebase_DateTime::now();
     $billingPoints = array('Timetracker_Model_Timeaccount' => 'end', 'Sales_Model_Product' => 'end', 'WebAccounting_Model_BackupPath' => 'end', 'WebAccounting_Model_StoragePath' => 'end', 'WebAccounting_Model_MailAccount' => 'end', 'WebAccounting_Model_DReg' => 'begin', 'WebAccounting_Model_CertificateDomain' => 'begin', 'WebAccounting_Model_IPNet' => 'end', '' => 'end', 'Sales_Model_ProductAgregate' => 'end');
     foreach ($contracts as $contract) {
         if ($contract->end_date && $contract->end_date < $now) {
             continue;
         }
         // find product aggregates for this contract
         $filter = new Sales_Model_ProductAggregateFilter(array());
         $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'equals', 'value' => $contract->getId())));
         $productAggregates = Sales_Controller_ProductAggregate::getInstance()->search($filter);
         foreach ($productAggregates as $pa) {
             // find all invoices for the contract
             $filter = new Sales_Model_InvoiceFilter(array(array('field' => 'contract', 'operator' => 'AND', 'value' => array(array('field' => ':id', 'operator' => 'equals', 'value' => $contract->getId())))));
             $invoices = Sales_Controller_Invoice::getInstance()->search($filter);
             // find last invoice position for this aggregate
             $filter = new Sales_Model_InvoicePositionFilter();
             $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'invoice_id', 'operator' => 'in', 'value' => $invoices->getArrayOfIds())));
             $pagination = new Tinebase_Model_Pagination(array('limit' => 1, 'sort' => 'month', 'dir' => 'DESC'));
             $lastInvoicePosition = Sales_Controller_InvoicePosition::getInstance()->search($filter, $pagination)->getFirstRecord();
             // set billing_point, if none given
             if (!$pa->billing_point) {
                 $pa->billing_point = $billingPoints[$lastInvoicePosition->model];
             }
             if (!$lastInvoicePosition) {
                 // if no invoice position has been found, this is a new contract, so set start_date to the first day of the month of the contracts start_date
                 $date = clone $contract->start_date;
                 $date->setTimezone(Tinebase_Core::getUserTimezone());
                 $date->setTime(0, 0, 0);
                 $date->setDate($date->format('Y'), $date->format('m'), 1);
                 $date->setTimezone('UTC');
                 $startDate = clone $date;
                 $labDate = NULL;
             } else {
                 $split = explode('-', $lastInvoicePosition->month);
                 $date = Tinebase_DateTime::now();
                 $date->setTimezone(Tinebase_Core::getUserTimezone());
                 $date->setTime(0, 0, 0);
                 $date->setDate($split[0], $split[1], 1);
                 // set to next billing date
                 $date->addMonth(1);
                 // if the billing point is at the begin of the interval, set date back one interval
                 if ($pa->billing_point == 'begin') {
                     $date->subMonth($pa->interval);
                 }
                 $date->setTimezone('UTC');
                 $labDate = clone $date;
                 // find first invoice position to calculate start_date
                 $pagination = new Tinebase_Model_Pagination(array('limit' => 1, 'sort' => 'month', 'dir' => 'ASC'));
                 $firstInvoicePosition = Sales_Controller_InvoicePosition::getInstance()->search($filter, $pagination)->getFirstRecord();
                 $split = explode('-', $firstInvoicePosition->month);
                 $startDate = Tinebase_DateTime::now()->setTimezone(Tinebase_Core::getUserTimezone());
                 $startDate->setTime(0, 0, 0);
                 $startDate->setDate($split[0], $split[1], 1);
                 $startDate->setTimezone('UTC');
             }
             $pa->start_date = $startDate;
             $pa->last_autobill = $labDate;
             Sales_Controller_ProductAggregate::getInstance()->update($pa);
         }
     }
 }
コード例 #7
0
 public function setLastAutobill()
 {
     if (!Sales_Config::getInstance()->featureEnabled(Sales_Config::FEATURE_INVOICES_MODULE)) {
         Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' setLastAutobill ran allthoug feature ' . Sales_Config::FEATURE_INVOICES_MODULE . ' is disabled');
         return false;
     }
     $cc = Sales_Controller_Contract::getInstance();
     $pc = Sales_Controller_ProductAggregate::getInstance();
     $date = Tinebase_DateTime::now()->setTimezone(Tinebase_Core::getUserTimezone());
     $date->setDate($date->format('Y'), 1, 1)->setTime(0, 0, 0);
     $date->setTimezone('UTC');
     $filter = new Sales_Model_ContractFilter(array(array('field' => 'start_date', 'operator' => 'after_or_equals', 'value' => $date)));
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'end_date', 'operator' => 'isnull', 'value' => NULL)));
     $contracts = $cc->search($filter);
     foreach ($contracts as $contract) {
         $filter = new Sales_Model_ProductAggregateFilter(array());
         $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'equals', 'value' => $contract->getId())));
         echo 'Updating last_autobill of ' . $contract->title . PHP_EOL;
         $contract->last_autobill = clone $contract->start_date;
         $contract->last_autobill->subMonth($contract->interval);
         foreach ($pc->search($filter) as $pagg) {
             echo 'Updating last_autobill of product assigned to ' . $contract->title . PHP_EOL;
             $pagg->last_autobill = clone $contract->start_date;
             $pagg->last_autobill->subMonth($pagg->interval);
             $pc->update($pagg);
         }
         $cc->update($contract);
     }
 }
コード例 #8
0
 public function setLastAutobill()
 {
     $cc = Sales_Controller_Contract::getInstance();
     $pc = Sales_Controller_ProductAggregate::getInstance();
     $date = Tinebase_DateTime::now()->setTimezone(Tinebase_Core::getUserTimezone());
     $date->setDate($date->format('Y'), 1, 1)->setTime(0, 0, 0);
     $date->setTimezone('UTC');
     $filter = new Sales_Model_ContractFilter(array(array('field' => 'start_date', 'operator' => 'after_or_equals', 'value' => $date)));
     $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'end_date', 'operator' => 'isnull', 'value' => NULL)));
     $contracts = $cc->search($filter);
     foreach ($contracts as $contract) {
         $filter = new Sales_Model_ProductAggregateFilter(array());
         $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'equals', 'value' => $contract->getId())));
         echo 'Updating last_autobill of ' . $contract->title . PHP_EOL;
         $contract->last_autobill = clone $contract->start_date;
         $contract->last_autobill->subMonth($contract->interval);
         foreach ($pc->search($filter) as $pagg) {
             echo 'Updating last_autobill of product assigned to ' . $contract->title . PHP_EOL;
             $pagg->last_autobill = clone $contract->start_date;
             $pagg->last_autobill->subMonth($pagg->interval);
             $pc->update($pagg);
         }
         $cc->update($contract);
     }
 }
 /**
  * inspects delete action
  *
  * @param array $_ids
  * @return array of ids to actually delete
  */
 protected function _inspectDelete(array $_ids)
 {
     $records = $this->_backend->getMultiple($_ids);
     $records->setTimezone(Tinebase_Core::getUserTimezone());
     $invoicePositionController = Sales_Controller_InvoicePosition::getInstance();
     $contractController = Sales_Controller_Contract::getInstance();
     foreach ($records as $record) {
         if (!$record->is_auto) {
             continue;
         }
         if ($record->cleared == 'CLEARED') {
             // cleared invoices must not be deleted
             throw new Sales_Exception_InvoiceAlreadyClearedDelete();
         } else {
             // try to find a invoice after this one
             // there should be a contract
             $contractRelation = Tinebase_Relations::getInstance()->getRelations('Sales_Model_Invoice', 'Sql', $record->getId(), NULL, array(), TRUE, array('Sales_Model_Contract'))->getFirstRecord();
             if ($contractRelation) {
                 $contract = $contractRelation->related_record;
                 $contract->setTimezone(Tinebase_Core::getUserTimezone());
                 // get all invoices related to this contract. throw exception if a follwing invoice has been found
                 $invoiceRelations = Tinebase_Relations::getInstance()->getRelations('Sales_Model_Contract', 'Sql', $contract->getId(), NULL, array(), TRUE, array('Sales_Model_Invoice'));
                 foreach ($invoiceRelations as $invoiceRelation) {
                     $invoiceRelation->related_record->setTimezone(Tinebase_Core::getUserTimezone());
                     if ($record->getId() !== $invoiceRelation->related_record->getId() && $record->creation_time < $invoiceRelation->related_record->creation_time) {
                         throw new Sales_Exception_DeletePreviousInvoice();
                     }
                 }
             } else {
                 if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) {
                     Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Could not find contract relation -> skip contract handling');
                 }
                 $contract = null;
             }
             // remove invoice_id from billables
             $filter = new Sales_Model_InvoicePositionFilter(array());
             $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'invoice_id', 'operator' => 'equals', 'value' => $record->getId())));
             $invoicePositions = $invoicePositionController->search($filter);
             $allModels = array_unique($invoicePositions->model);
             foreach ($allModels as $model) {
                 if ($model == 'Sales_Model_ProductAggregate') {
                     continue;
                 }
                 $filteredInvoicePositions = $invoicePositions->filter('model', $model);
                 $billableControllerName = $model::getBillableControllerName();
                 $billableFilterName = $model::getBillableFilterName();
                 $filterInstance = new $billableFilterName(array());
                 $filterInstance->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'invoice_id', 'operator' => 'equals', 'value' => $record->getId())));
                 $billableControllerName::getInstance()->updateMultiple($filterInstance, array('invoice_id' => NULL));
                 // set invoice ids of the timeaccounts
                 if ($model == 'Timetracker_Model_Timeaccount') {
                     $filterInstance = new Timetracker_Model_TimeaccountFilter(array());
                     $filterInstance->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'invoice_id', 'operator' => 'equals', 'value' => $record->getId())));
                     Timetracker_Controller_Timeaccount::getInstance()->updateMultiple($filterInstance, array('invoice_id' => NULL));
                 }
             }
             // delete invoice positions
             $invoicePositionController->delete($invoicePositions->getId());
             // set last_autobill a period back
             if ($contract) {
                 // check product aggregates
                 $filter = new Sales_Model_ProductAggregateFilter(array());
                 $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'contract_id', 'operator' => 'equals', 'value' => $contract->getId())));
                 $paController = Sales_Controller_ProductAggregate::getInstance();
                 $productAggregates = $paController->search($filter);
                 $productAggregates->setTimezone(Tinebase_Core::getUserTimezone());
                 foreach ($productAggregates as $productAggregate) {
                     if ($productAggregate->last_autobill) {
                         $lab = clone $productAggregate->last_autobill;
                         $add = 0 - (int) $productAggregate->interval;
                         $productAggregate->last_autobill = $lab->addMonth($add);
                         $productAggregate->last_autobill->setTime(0, 0, 0);
                         // last_autobill may not be before aggregate starts (may run into this case if interval has been resized)
                         if (!$productAggregate->start_date || $productAggregate->last_autobill < $productAggregate->start_date) {
                             $productAggregate->last_autobill = NULL;
                         }
                     }
                     $productAggregate->setTimezone('UTC');
                     $paController->update($productAggregate);
                 }
             }
         }
     }
     return $_ids;
 }