/** * appends sql to given select statement * * @param Zend_Db_Select $_select * @param Tinebase_Backend_Sql_Abstract $_backend */ public function appendFilterSql($_select, $_backend) { if (empty($this->_value)) { // nothing to filter return; } $filterData = array(array('field' => 'lead_name', 'operator' => 'contains', 'value' => $this->_value), array('field' => 'description', 'operator' => 'contains', 'value' => $this->_value), array('field' => 'showClosed', 'operator' => 'equals', 'value' => TRUE)); $filter = new Crm_Model_LeadFilter($filterData, 'OR'); /*** also filter for related contacts ***/ $contactFilter = new Addressbook_Model_ContactFilter(array(array('field' => 'query', 'operator' => 'contains', 'value' => $this->_value))); $contactIds = Addressbook_Controller_Contact::getInstance()->search($contactFilter, NULL, FALSE, TRUE); $relationFilter = new Tinebase_Model_RelationFilter(array(array('field' => 'own_model', 'operator' => 'equals', 'value' => 'Crm_Model_Lead'), array('field' => 'related_model', 'operator' => 'equals', 'value' => 'Addressbook_Model_Contact'), array('field' => 'related_id', 'operator' => 'in', 'value' => $contactIds))); $leadIds = Tinebase_Relations::getInstance()->search($relationFilter, NULL)->own_id; $filter->addFilter(new Tinebase_Model_Filter_Id('id', 'in', $leadIds)); Tinebase_Backend_Sql_Filter_FilterGroup::appendFilters($_select, $filter, $_backend); }
/** * append relation filter * * @param Crm_Model_LeadFilter $filter */ protected function _appendRelationFilter($filter) { if (!Tinebase_Core::getPreference()->getValue(Tinebase_Preference::ADVANCED_SEARCH, false)) { return; } $relationsToSearchIn = array('Addressbook_Model_Contact', 'Sales_Model_Product', 'Tasks_Model_Task'); $leadIds = array(); foreach ($relationsToSearchIn as $relatedModel) { $filterModel = $relatedModel . 'Filter'; $relatedFilter = new $filterModel(array(array('field' => 'query', 'operator' => 'contains', 'value' => $this->_value))); $relatedIds = Tinebase_Core::getApplicationInstance($relatedModel)->search($relatedFilter, NULL, FALSE, TRUE); $relationFilter = new Tinebase_Model_RelationFilter(array(array('field' => 'own_model', 'operator' => 'equals', 'value' => 'Crm_Model_Lead'), array('field' => 'related_model', 'operator' => 'equals', 'value' => $relatedModel), array('field' => 'related_id', 'operator' => 'in', 'value' => $relatedIds))); $leadIds = array_merge($leadIds, Tinebase_Relations::getInstance()->search($relationFilter, NULL)->own_id); } $filter->addFilter(new Tinebase_Model_Filter_Id('id', 'in', $leadIds)); }
/** * returns own ids defined by relation filter * * @param string $_modelName * @return array */ protected function _getOwnIds($_modelName) { if (!$this->_options['own_filtergroup']) { throw new Tinebase_Exception_InvalidArgument('own filter group has to be defined!'); } if (!$this->_options['own_controller']) { throw new Tinebase_Exception_InvalidArgument('own controller has to be defined!'); } $idProperty = 'id'; $filtergroup = $this->_options['own_filtergroup']; $controller = $this->_options['own_controller']; if (!$this->_value[0]['value']) { $relationFilter = new Tinebase_Model_RelationFilter(array(array('field' => 'own_model', 'operator' => 'equals', 'value' => $_modelName), array('field' => 'related_model', 'operator' => 'equals', 'value' => $this->_options['related_model']))); $notInIds = Tinebase_Relations::getInstance()->search($relationFilter, NULL)->own_id; $filter = new $filtergroup(array(), 'AND'); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => $idProperty, 'operator' => 'notin', 'value' => $notInIds))); return $controller::getInstance()->search($filter, null, false, true); } return parent::_getOwnIds($_modelName); }
/** * rebills an invoice * * @param string $id */ public function rebillInvoice($id) { $invoice = Sales_Controller_Invoice::getInstance()->get($id); $relation = Tinebase_Relations::getInstance()->getRelations('Sales_Model_Invoice', 'Sql', $id, 'sibling', array('CONTRACT'), 'Sales_Model_Contract')->getFirstRecord(); $contract = Sales_Controller_Contract::getInstance()->get($relation->related_id); $date = clone $invoice->creation_time; $date->setTimezone(Tinebase_Core::getUserTimezone()); Sales_Controller_Invoice::getInstance()->delete(array($id)); return Sales_Controller_Invoice::getInstance()->createAutoInvoices($date, $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; }
/** * transfer relations * * @param Zend_Console_Getopt $opts */ public function transferRelations($opts) { if (!$this->_checkAdminRight()) { return FALSE; } $this->_addOutputLogWriter(); try { $args = $this->_parseArgs($opts, array('oldId', 'newId', 'model')); } catch (Tinebase_Exception_InvalidArgument $e) { if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Parameters "oldId", "newId" and "model" are required!'); } exit(1); } $skippedEntries = Tinebase_Relations::getInstance()->transferRelations($args['oldId'], $args['newId'], $args['model']); if (!empty($skippedEntries) && Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' ' . count($skippedEntries) . ' entries has been skipped:'); } if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' The operation has been terminated successfully.'); } return 0; }
/** * tests auto invoice creation */ public function testFullAutoInvoice() { $this->markTestSkipped('0010492: fix failing invoices and timetracker tests'); $this->_createFullFixtures(); $this->_createFailingContracts(); $this->assertEquals(7, $this->_contractRecords->count()); $date = clone $this->_referenceDate; $i = 0; // the whole year, 12 months while ($i < 12) { $result = $this->_invoiceController->createAutoInvoices($date); $date->addMonth(1); $i++; } $this->assertEquals(6, count($result['failures'])); $failures = ''; foreach ($result['failures'] as $failure) { $failures .= $failure; } $this->assertTrue(strstr($failures, 'no customer') !== FALSE); $this->assertTrue(strstr($failures, 'no billing') !== FALSE); $this->assertTrue(strstr($failures, 'no costcenter') !== FALSE); // also add an hour to get the last end $date->addHour(1); $this->_invoiceController->createAutoInvoices($date); $date->addHour(1); $this->_invoiceController->createAutoInvoices($date); $all = $this->_invoiceController->getAll(); $cc1 = $this->_costcenterRecords->filter('remark', 'unittest1')->getFirstRecord(); $cc2 = $this->_costcenterRecords->filter('remark', 'unittest2')->getFirstRecord(); $cc3 = $this->_costcenterRecords->filter('remark', 'unittest3')->getFirstRecord(); $cc4 = $this->_costcenterRecords->filter('remark', 'unittest4')->getFirstRecord(); $all->setTimezone(Tinebase_Core::getUserTimezone()); $customer1Invoices = $all->filter('costcenter_id', $cc1->getId())->sort('start_date'); $customer2Invoices = $all->filter('costcenter_id', $cc2->getId())->sort('start_date'); $customer3Invoices = $all->filter('costcenter_id', $cc3->getId())->sort('start_date'); $customer4Invoices = $all->filter('costcenter_id', $cc4->getId())->sort('start_date'); // customer 1 must have one invoice (timeaccount with budget has been billed the first month) $this->assertEquals(1, $customer1Invoices->count(), 'Customer 1 must have 1 invoice!'); // customer 2 must have one invoice (timeaccount with budget has been billed the first time) $this->assertEquals(1, $customer2Invoices->count(), 'Customer 2 must have 1 invoice!'); // there are timesheets in 2 intervals, so no empty invoice should be generated $this->assertEquals(2, $customer3Invoices->count(), 'Customer 3 must have 2 invoices!'); // there are 2 products, interval 3,6 -> so every quarter in this year and the first of next year must be found $this->assertEquals(5, $customer4Invoices->count(), 'Customer 4 must have 5 invoices!'); // test invoice positions $allInvoicePositions = Sales_Controller_InvoicePosition::getInstance()->getAll(); $this->assertEquals(1, $allInvoicePositions->filter('invoice_id', $customer1Invoices->getFirstRecord()->getId())->count()); $this->assertEquals(1, $allInvoicePositions->filter('invoice_id', $customer2Invoices->getFirstRecord()->getId())->count()); // each invoice should contain 1 timeaccount foreach ($customer3Invoices as $ci) { $this->assertEquals(1, $allInvoicePositions->filter('invoice_id', $ci->getId())->count()); } // we need 9,3,9,3,9 invoice positions $i = 1; foreach ($customer4Invoices as $ci) { $ip = $allInvoicePositions->filter('invoice_id', $ci->getId()); $this->assertEquals($i % 2 == 1 ? 9 : 3, $ip->count()); $i++; } // contract 1 gets billed at the begin of the period $c1IArray = $customer1Invoices->start_date; $this->assertEquals($this->_referenceYear . '-01-01 00:00:00', $c1IArray[0]->toString()); $c1IArray = $customer1Invoices->end_date; $this->assertEquals($this->_referenceYear . '-01-31 23:59:59', $c1IArray[0]->toString()); // contract 2 gets billed at the end of the period, and the second period ends at 1.8.20xx $c2IsArray = $customer2Invoices->start_date; $c2IeArray = $customer2Invoices->end_date; $this->assertEquals($this->_referenceYear . '-05-01 00:00:00', $c2IsArray[0]->toString()); $this->assertEquals($this->_referenceYear . '-05-31 23:59:59', $c2IeArray[0]->toString()); // test correct timesheet handling of customer 3 $c3IsArray = $customer3Invoices->start_date; $c3IeArray = $customer3Invoices->end_date; $this->assertEquals($this->_referenceYear . '-05-01 00:00:00', $c3IsArray[0]->toString()); $this->assertEquals($this->_referenceYear . '-05-31 23:59:59', $c3IeArray[0]->toString()); $this->assertEquals($this->_referenceYear . '-09-01 00:00:00', $c3IsArray[1]->toString()); $this->assertEquals($this->_referenceYear . '-09-30 23:59:59', $c3IeArray[1]->toString()); // test customer 4 having products only $c4IsArray = $customer4Invoices->start_date; $c4IeArray = $customer4Invoices->end_date; // should contain billeachquarter & billhalfyearly $this->assertEquals($this->_referenceYear . '-01-01 00:00:00', $c4IsArray[0]->toString()); $this->assertEquals($this->_referenceYear . '-06-30 23:59:59', $c4IeArray[0]->toString()); // should contain billeachquarter $this->assertEquals($this->_referenceYear . '-04-01 00:00:00', $c4IsArray[1]->toString()); $this->assertEquals($this->_referenceYear . '-06-30 23:59:59', $c4IeArray[1]->toString()); // should contain billeachquarter & billhalfyearly $this->assertEquals($this->_referenceYear . '-07-01 00:00:00', $c4IsArray[2]->toString()); $this->assertEquals($this->_referenceYear . '-12-31 23:59:59', $c4IeArray[2]->toString()); // should contain billeachquarter $this->assertEquals($this->_referenceYear . '-10-01 00:00:00', $c4IsArray[3]->toString()); $this->assertEquals($this->_referenceYear . '-12-31 23:59:59', $c4IeArray[3]->toString()); // look if hours of timesheets gets calculated properly $c3Invoice = $customer3Invoices->getFirstRecord(); $filter = new Sales_Model_InvoicePositionFilter(array()); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'invoice_id', 'operator' => 'equals', 'value' => $c3Invoice->getId()))); $c3InvoicePositions = Sales_Controller_InvoicePosition::getInstance()->search($filter); $this->assertEquals(1, $c3InvoicePositions->count()); $this->assertEquals(3.5, $c3InvoicePositions->getFirstRecord()->quantity); $invoice = $customer1Invoices->getFirstRecord(); $invoice->relations = Tinebase_Relations::getInstance()->getRelations('Sales_Model_Invoice', 'Sql', $invoice->getId())->toArray(); $filter = new Sales_Model_InvoicePositionFilter(array()); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'invoice_id', 'operator' => 'equals', 'value' => $invoice['id']))); $invoice->positions = Sales_Controller_InvoicePosition::getInstance()->search($filter); $invoice->cleared = 'CLEARED'; $invoice = $this->_invoiceController->update($invoice); // check correct number generation $this->assertEquals("R-00001", $invoice->number); $invoice = $customer2Invoices->getFirstRecord(); $invoice->relations = Tinebase_Relations::getInstance()->getRelations('Sales_Model_Invoice', 'Sql', $invoice->getId())->toArray(); $filter = new Sales_Model_InvoicePositionFilter(array()); $filter->addFilter(new Tinebase_Model_Filter_Text(array('field' => 'invoice_id', 'operator' => 'equals', 'value' => $invoice['id']))); $invoice->positions = Sales_Controller_InvoicePosition::getInstance()->search($filter); $invoice->cleared = 'CLEARED'; $invoice = $this->_invoiceController->update($invoice); $this->assertEquals("R-00002", $invoice->number); // check disallow editing invoice after clearing $invoice->credit_term = 20; $this->setExpectedException('Sales_Exception_InvoiceAlreadyClearedEdit'); $this->_invoiceController->update($invoice); }
/** * testTransfer * * @see 0009210: Allow to change relations * https://forge.tine20.org/mantisbt/view.php?id=9210 */ public function testTransfer() { $sclever = Addressbook_Controller_Contact::getInstance()->get($this->_personas['sclever']->contact_id, null, false); $pwulf = Addressbook_Controller_Contact::getInstance()->get($this->_personas['pwulf']->contact_id, null, false); $container = Tinebase_Container::getInstance()->create(new Tinebase_Model_Container(array('application_id' => Tinebase_Application::getInstance()->getApplicationByName('Sales')->getId(), 'type' => Tinebase_Model_Container::TYPE_SHARED, 'backend' => 'sql', 'name' => 'testsdf'))); $contract = new Sales_Model_Contract(array('number' => '23547', 'title' => 'test', 'container_id' => $container->getId())); $contract = Sales_Controller_Contract::getInstance()->create($contract); $contract2 = new Sales_Model_Contract(array('number' => '23347', 'title' => 'test', 'container_id' => $container->getId())); $contract2 = Sales_Controller_Contract::getInstance()->create($contract2); $json = new Sales_Frontend_Json(); $contractJson = $contract->toArray(); $contractJson['relations'][] = array('own_degree' => Tinebase_Model_Relation::DEGREE_SIBLING, 'related_model' => 'Addressbook_Model_Contact', 'related_record' => $sclever->toArray(), 'type' => 'CUSTOMER'); $contractJson = $json->saveContract($contractJson); $contract2Json = $contract2->toArray(); $contract2Json['relations'][] = array('own_degree' => Tinebase_Model_Relation::DEGREE_SIBLING, 'related_model' => 'Addressbook_Model_Contact', 'related_record' => $sclever->toArray(), 'type' => 'PARTNER'); $contract2Json['relations'][] = array('own_degree' => Tinebase_Model_Relation::DEGREE_SIBLING, 'related_model' => 'Addressbook_Model_Contact', 'related_record' => $pwulf->toArray(), 'type' => 'PARTNER'); $contract2Json = $json->saveContract($contract2Json); $this->assertEquals($sclever->getId(), $contractJson['relations'][0]['related_id']); $skipped = Tinebase_Relations::getInstance()->transferRelations($sclever->getId(), $pwulf->getId(), 'Addressbook_Model_Contact'); $this->assertEquals(1, count($skipped)); $skipped = array_pop($skipped); $this->assertEquals($sclever->getId(), $skipped['own_id']); $contractJson = $json->getContract($contract->getId()); $this->assertEquals($pwulf->getId(), $contractJson['relations'][0]['related_id']); $this->setExpectedException('Tinebase_Exception_NotFound'); Tinebase_Relations::getInstance()->transferRelations($sclever->getId(), $pwulf->getId(), 'Addressbook_Model_Contract'); }
/** * 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; }
/** * uninstall app * * @param Tinebase_Model_Application $_application * @throws Setup_Exception */ protected function _uninstallApplication(Tinebase_Model_Application $_application, $uninstallAll = false) { if ($this->_backend === null) { throw new Setup_Exception('No setup backend available'); } Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Uninstall ' . $_application); try { $applicationTables = Tinebase_Application::getInstance()->getApplicationTables($_application); } catch (Zend_Db_Statement_Exception $zdse) { Setup_Core::getLogger()->err(__METHOD__ . '::' . __LINE__ . " " . $zdse); throw new Setup_Exception('Could not uninstall ' . $_application . ' (you might need to remove the tables by yourself): ' . $zdse->getMessage()); } $disabledFK = FALSE; $db = Tinebase_Core::getDb(); do { $oldCount = count($applicationTables); if ($_application->name == 'Tinebase') { $installedApplications = Tinebase_Application::getInstance()->getApplications(NULL, 'id'); if (count($installedApplications) !== 1) { throw new Setup_Exception_Dependency('Failed to uninstall application "Tinebase" because of dependencies to other installed applications.'); } } foreach ($applicationTables as $key => $table) { Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Remove table: {$table}"); try { // drop foreign keys which point to current table first $foreignKeys = $this->_backend->getExistingForeignKeys($table); foreach ($foreignKeys as $foreignKey) { Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Drop index: " . $foreignKey['table_name'] . ' => ' . $foreignKey['constraint_name']); $this->_backend->dropForeignKey($foreignKey['table_name'], $foreignKey['constraint_name']); } // drop table $this->_backend->dropTable($table); if ($_application->name != 'Tinebase') { Tinebase_Application::getInstance()->removeApplicationTable($_application, $table); } unset($applicationTables[$key]); } catch (Zend_Db_Statement_Exception $e) { // we need to catch exceptions here, as we don't want to break here, as a table // might still have some foreign keys // this works with mysql only $message = $e->getMessage(); Setup_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " Could not drop table {$table} - " . $message); // remove app table if table not found in db if (preg_match('/SQLSTATE\\[42S02\\]: Base table or view not found/', $message) && $_application->name != 'Tinebase') { Tinebase_Application::getInstance()->removeApplicationTable($_application, $table); unset($applicationTables[$key]); } else { Setup_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . " Disabling foreign key checks ... "); if ($db instanceof Zend_Db_Adapter_Pdo_Mysql) { $db->query("SET FOREIGN_KEY_CHECKS=0"); } $disabledFK = TRUE; } } } if ($oldCount > 0 && count($applicationTables) == $oldCount) { throw new Setup_Exception('dead lock detected oldCount: ' . $oldCount); } } while (count($applicationTables) > 0); if ($disabledFK) { if ($db instanceof Zend_Db_Adapter_Pdo_Mysql) { Setup_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . " Enabling foreign key checks again... "); $db->query("SET FOREIGN_KEY_CHECKS=1"); } } if ($_application->name != 'Tinebase') { if (!$uninstallAll) { Tinebase_Relations::getInstance()->removeApplication($_application->name); Tinebase_Timemachine_ModificationLog::getInstance()->removeApplication($_application); // delete containers, config options and other data for app Tinebase_Application::getInstance()->removeApplicationData($_application); } // remove application from table of installed applications Tinebase_Application::getInstance()->deleteApplication($_application); } Setup_Uninitialize::uninitialize($_application); Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Removed app: " . $_application->name); }
/** * test if a user, who has no manage_invoices - right, is able tosave a timeaccount having an invoice linked */ public function testUpdateInvoiceLinkedTimeaccount() { $this->markTestSkipped('0010492: fix failing invoices and timetracker tests'); $ta = $this->_getTimeaccount(array('title' => 'to find'), true); $cc = Sales_Controller_CostCenter::getInstance()->create(new Sales_Model_CostCenter(array('number' => 1, 'title' => 'test'))); $customer = Sales_Controller_Customer::getInstance()->create(new Sales_Model_Customer(array('number' => 100, 'name' => 'test', 'description' => 'unittest', 'credit_term' => 1))); $address = Sales_Controller_Address::getInstance()->create(new Sales_Model_Address(array('street' => 'teststreet', 'locality' => 'testcity', 'customer_id' => $customer->id, 'postalcode' => 12345))); $invoice = Sales_Controller_Invoice::getInstance()->create(new Sales_Model_Invoice(array('description' => 'test', 'address_id' => $address->id, 'date' => Tinebase_DateTime::now(), 'credit_term' => 1, 'type' => 'INVOICE', 'start_date' => Tinebase_DateTime::now(), 'end_date' => Tinebase_DateTime::now()->addMonth(1), 'costcenter_id' => $cc->id))); Tinebase_Relations::getInstance()->setRelations('Sales_Model_Invoice', 'Sql', $invoice->id, array(array('related_id' => $ta->id, 'related_model' => 'Timetracker_Model_Timeaccount', 'related_record' => $ta, 'own_degree' => 'sibling', 'type' => 'INVOICE'))); // fetch user group $group = Tinebase_Group::getInstance()->getGroupByName('Users'); $groupId = $group->getId(); // create new user $user = new Tinebase_Model_FullUser(array('accountLoginName' => 'testuser', 'accountPrimaryGroup' => $groupId, 'accountDisplayName' => 'Test User', 'accountLastName' => 'User', 'accountFirstName' => 'Test', 'accountFullName' => 'Test User', 'accountEmailAddress' => '*****@*****.**')); $user = Admin_Controller_User::getInstance()->create($user, 'pw', 'pw'); // add tt-ta admin right to user role to allow user to update (manage) timeaccounts // user has no right to see sales contracts $fe = new Admin_Frontend_Json(); $userRoles = $fe->getRoles('user', array(), array(), 0, 1); $userRole = $fe->getRole($userRoles['results'][0]['id']); $roleRights = $fe->getRoleRights($userRole['id']); $roleMembers = $fe->getRoleMembers($userRole['id']); $roleMembers['results'][] = array('name' => 'testuser', 'type' => 'user', 'id' => $user->accountId); $app = Tinebase_Application::getInstance()->getApplicationByName('Timetracker'); $roleRights['results'][] = array('application_id' => $app->getId(), 'right' => Timetracker_Acl_Rights::MANAGE_TIMEACCOUNTS); $roleRights['results'][] = array('application_id' => $app->getId(), 'right' => Tinebase_Acl_Rights::ADMIN); $fe->saveRole($userRole, $roleMembers['results'], $roleRights['results']); // switch to other user $this->_testUser = Tinebase_Core::getUser(); Tinebase_Core::set(Tinebase_Core::USER, $user); $ta = $this->_json->getTimeaccount($ta->id); $this->assertTrue(empty($ta['relations']), 'relations are not empty: ' . print_r($ta['relations'], true)); // this must be possible $ta = $this->_json->saveTimeaccount($ta); Tinebase_Core::set(Tinebase_Core::USER, $this->_testUser); $ta = $this->_json->getTimeaccount($ta['id']); $this->assertTrue(count($ta['relations']) == 1); }
/** * returns recipients for a lead notification * * @param Crm_Model_Lead $_lead * @return Tinebase_Record_RecordSet of Addressbook_Model_Contact */ protected function _getNotificationRecipients(Crm_Model_Lead $_lead) { if (!$_lead->relations instanceof Tinebase_Record_RecordSet) { $_lead->relations = Tinebase_Relations::getInstance()->getRelations('Crm_Model_Lead', 'Sql', $_lead->getId(), true); } $recipients = $_lead->getResponsibles(); // if no responsibles are defined, send message to all readers of container if (count($recipients) === 0) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__CLASS__ . '::' . __METHOD__ . '::' . __LINE__ . ' no responsibles found for lead: ' . $_lead->getId() . ' sending notification to all people having read access to container ' . $_lead->container_id); } $containerGrants = Tinebase_Container::getInstance()->getGrantsOfContainer($_lead->container_id, TRUE); // NOTE: we just send notifications to users, not to groups or anyones! foreach ($containerGrants as $grant) { if ($grant['account_type'] == Tinebase_Acl_Rights::ACCOUNT_TYPE_USER && $grant[Tinebase_Model_Grants::GRANT_READ] == 1) { try { $contact = Addressbook_Controller_Contact::getInstance()->getContactByUserId($grant['account_id'], TRUE); $recipients->addRecord($contact); } catch (Addressbook_Exception_NotFound $aenf) { if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__CLASS__ . '::' . __METHOD__ . '::' . __LINE__ . ' Do not send notification to non-existant user: ' . $aenf->getMessage()); } } } } } return $recipients; }
/** * transfers all contracts starting with AB- to orderconfirmation */ public function transferContractsToOrderConfirmation() { $contractController = Sales_Controller_Contract::getInstance(); $ocController = Sales_Controller_OrderConfirmation::getInstance(); $rel = Tinebase_Relations::getInstance(); $filter = new Sales_Model_ContractFilter(array(array('field' => 'number', 'operator' => 'startswith', 'value' => 'AB-')), 'AND'); $contracts = $contractController->search($filter); foreach ($contracts as $contract) { $oc = $ocController->create(new Sales_Model_OrderConfirmation(array('number' => $contract->number, 'title' => $contract->title, 'description' => ''))); $rel->setRelations('Sales_Model_OrderConfirmation', 'Sql', $oc->getId(), array(array('own_degree' => 'sibling', 'related_degree' => 'sibling', 'related_model' => 'Sales_Model_Contract', 'related_backend' => 'Sql', 'related_id' => $contract->getId(), 'type' => 'CONTRACT'))); } }
/** * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. * * @access protected */ protected function setUp() { $this->_object = Tinebase_Relations::getInstance(); }
/** * returns path of record * * @param Tinebase_Record_Interface $record * @param boolean|int $depth * @return Tinebase_Record_RecordSet * @throws Tinebase_Exception_Record_NotAllowed * @throws Tinebase_Exception */ protected function _getPathsOfRecord(Tinebase_Record_Interface $record, $depth = false) { if (false !== $depth && $depth > 8) { throw new Tinebase_Exception('too many recursions while calculating record path'); } $result = new Tinebase_Record_RecordSet('Tinebase_Model_Path'); $parentRelations = Tinebase_Relations::getInstance()->getRelationsOfRecordByDegree($record, Tinebase_Model_Relation::DEGREE_PARENT); foreach ($parentRelations as $parent) { if (!is_object($parent->related_record)) { $parent->related_record = Tinebase_Core::getApplicationInstance($parent->related_model)->get($parent->related_id); } if (false === $depth) { // we do not need to generate the parents paths, they should be in DB $parentPaths = Tinebase_Record_Path::getInstance()->getPathsForRecords($parent->related_record); } else { // we have to regenerate parents paths $parentPaths = $this->_getPathsOfRecord($parent->related_record, $depth === true ? 1 : $depth + 1); } if (count($parentPaths) === 0) { $path = new Tinebase_Model_Path(array('path' => $this->_getPathPart($parent->related_record) . $this->_getPathPart($record, $parent), 'shadow_path' => '/' . $parent->related_id . $this->_getShadowPathPart($record, $parent), 'record_id' => $record->getId(), 'creation_time' => Tinebase_DateTime::now())); $result->addRecord($path); } else { // merge paths foreach ($parentPaths as $path) { $newPath = new Tinebase_Model_Path(array('path' => $path->path . $this->_getPathPart($record, $parent), 'shadow_path' => $path->shadow_path . $this->_getShadowPathPart($record, $parent), 'record_id' => $record->getId(), 'creation_time' => Tinebase_DateTime::now())); $result->addRecord($newPath); } } } return $result; }
/** * delete linked objects (notes, relations, ...) of record * * @param Tinebase_Record_Interface $_record */ protected function _deleteLinkedObjects(Tinebase_Record_Interface $_record) { // delete notes & relations if ($_record->has('notes')) { Tinebase_Notes::getInstance()->deleteNotesOfRecord($this->_modelName, $this->_backend->getType(), $_record->getId()); } if ($_record->has('relations')) { $relations = Tinebase_Relations::getInstance()->getRelations($this->_modelName, $this->_backend->getType(), $_record->getId()); if (!empty($relations)) { // remove relations Tinebase_Relations::getInstance()->setRelations($this->_modelName, $this->_backend->getType(), $_record->getId(), array()); // remove related objects if (!empty($this->_relatedObjectsToDelete)) { foreach ($relations as $relation) { if (in_array($relation->related_model, $this->_relatedObjectsToDelete)) { list($appName, $i, $itemName) = explode('_', $relation->related_model); $appController = Tinebase_Core::getApplicationInstance($appName, $itemName); $appController->delete($relation->related_id); } } } } } }
/** * delete linked relations * * @param Tinebase_Record_Interface $_record * * TODO check if this needs to be done, as we might already deleting this "from the other side" */ protected function _deleteLinkedRelations(Tinebase_Record_Interface $_record) { $relations = Tinebase_Relations::getInstance()->getRelations($this->_modelName, $this->_getBackendType(), $_record->getId()); if (empty($relations)) { return; } // remove relations Tinebase_Relations::getInstance()->setRelations($this->_modelName, $this->_getBackendType(), $_record->getId(), array()); if (empty($this->_relatedObjectsToDelete)) { return; } // remove related objects Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Deleting all ' . implode(',', $this->_relatedObjectsToDelete) . ' relations.'); foreach ($relations as $relation) { if (in_array($relation->related_model, $this->_relatedObjectsToDelete)) { list($appName, $i, $itemName) = explode('_', $relation->related_model); $appController = Tinebase_Core::getApplicationInstance($appName, $itemName); try { $appController->delete($relation->related_id); } catch (Exception $e) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Error deleting: ' . $e->getMessage()); } } } }
/** * resolve multiple record fields (Tinebase_ModelConfiguration._recordsFields) * * @param Tinebase_Record_RecordSet $_records * @param Tinebase_ModelConfiguration $modelConfiguration * @param boolean $multiple * @throws Tinebase_Exception_UnexpectedValue */ protected function _resolveMultipleRecordFields(Tinebase_Record_RecordSet $_records, $modelConfiguration = NULL, $multiple = false) { if (!$modelConfiguration || !$_records->count()) { return; } if (!($resolveFields = $modelConfiguration->recordsFields)) { return; } $ownIds = $_records->{$modelConfiguration->idProperty}; // iterate fields to resolve foreach ($resolveFields as $fieldKey => $c) { $config = $c['config']; // resolve records, if omitOnSearch is definitively set to FALSE (by default they won't be resolved on search) if ($multiple && !(isset($config['omitOnSearch']) && $config['omitOnSearch'] === FALSE)) { continue; } if (!isset($config['controllerClassName'])) { throw new Tinebase_Exception_UnexpectedValue('Controller class name needed'); } // fetch the fields by the refIfField /** @var Tinebase_Controller_Record_Interface|Tinebase_Controller_SearchInterface $controller */ /** @noinspection PhpUndefinedMethodInspection */ $controller = $config['controllerClassName']::getInstance(); $filterName = $config['filterClassName']; $filterArray = array(); // addFilters can be added and must be added if the same model resides in more than one records fields if (isset($config['addFilters']) && is_array($config['addFilters'])) { $filterArray = $config['addFilters']; } /** @var Tinebase_Model_Filter_FilterGroup $filter */ $filter = new $filterName($filterArray); $filter->addFilter(new Tinebase_Model_Filter_Id(array('field' => $config['refIdField'], 'operator' => 'in', 'value' => $ownIds))); $paging = NULL; if (isset($config['paging']) && is_array($config['paging'])) { $paging = new Tinebase_Model_Pagination($config['paging']); } $foreignRecords = $controller->search($filter, $paging); /** @var Tinebase_Record_Interface $foreignRecordClass */ $foreignRecordClass = $foreignRecords->getRecordClassName(); $foreignRecordModelConfiguration = $foreignRecordClass::getConfiguration(); $foreignRecords->setTimezone(Tinebase_Core::getUserTimezone()); $foreignRecords->convertDates = true; $fr = $foreignRecords->getFirstRecord(); // @todo: resolve alarms? // @todo: use parts parameter? if ($foreignRecordModelConfiguration->resolveRelated && $fr) { if ($fr->has('notes')) { Tinebase_Notes::getInstance()->getMultipleNotesOfRecords($foreignRecords); } if ($fr->has('tags')) { Tinebase_Tags::getInstance()->getMultipleTagsOfRecords($foreignRecords); } if ($fr->has('relations')) { $relations = Tinebase_Relations::getInstance()->getMultipleRelations($foreignRecordClass, 'Sql', $foreignRecords->{$fr->getIdProperty()}); $foreignRecords->setByIndices('relations', $relations); } if ($fr->has('customfields')) { Tinebase_CustomField::getInstance()->resolveMultipleCustomfields($foreignRecords); } if ($fr->has('attachments') && Tinebase_Core::isFilesystemAvailable()) { Tinebase_FileSystem_RecordAttachments::getInstance()->getMultipleAttachmentsOfRecords($foreignRecords); } } if ($foreignRecords->count() > 0) { /** @var Tinebase_Record_Interface $record */ foreach ($_records as $record) { $filtered = $foreignRecords->filter($config['refIdField'], $record->getId())->toArray(); $filtered = $this->_resolveAfterToArray($filtered, $foreignRecordModelConfiguration, TRUE); $record->{$fieldKey} = $filtered; } } else { $_records->{$fieldKey} = NULL; } } }
/** * append relation filter * * @param string $ownModel * @param array $relationsToSearchIn * @return Tinebase_Model_Filter_Id */ protected function _getAdvancedSearchFilter($ownModel = null, $relationsToSearchIn = null) { if (Tinebase_Core::get('ADVANCED_SEARCHING') || !Tinebase_Core::getPreference()->getValue(Tinebase_Preference::ADVANCED_SEARCH, false) || empty($relationsToSearchIn)) { return null; } if (0 === strpos($this->_operator, 'not')) { $not = true; $operator = substr($this->_operator, 3); } else { $not = false; $operator = $this->_operator; } $ownIds = array(); foreach ((array) $relationsToSearchIn as $relatedModel) { $filterModel = $relatedModel . 'Filter'; // prevent recursion here // TODO find a better way for this, maybe we could pass this an option to all filters in filter model Tinebase_Core::set('ADVANCED_SEARCHING', true); $relatedFilter = new $filterModel(array(array('field' => 'query', 'operator' => $operator, 'value' => $this->_value))); $relatedIds = Tinebase_Core::getApplicationInstance($relatedModel)->search($relatedFilter, NULL, FALSE, TRUE); Tinebase_Core::set('ADVANCED_SEARCHING', false); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Found ' . count($relatedIds) . ' related ids'); } $relationFilter = new Tinebase_Model_RelationFilter(array(array('field' => 'own_model', 'operator' => 'equals', 'value' => $ownModel), array('field' => 'related_model', 'operator' => 'equals', 'value' => $relatedModel), array('field' => 'related_id', 'operator' => 'in', 'value' => $relatedIds))); $ownIds = array_merge($ownIds, Tinebase_Relations::getInstance()->search($relationFilter, NULL)->own_id); } return new Tinebase_Model_Filter_Id('id', $not ? 'notin' : 'in', $ownIds); }
/** * 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); }
/** * 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(); } } $this->_currentBillingContract = $contract; $productAggregates = $this->_findProductAggregates(); } else { if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Could not find contract relation -> skip contract handling'); } $contract = null; $productAggregates = array(); } // 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) { //find the month of each productAggregate we have to set it back to $undoProductAggregates = array(); $paController = Sales_Controller_ProductAggregate::getInstance(); foreach ($invoicePositions as $inPos) { if ($inPos->model != 'Sales_Model_ProductAggregate') { continue; } //if we didnt find a month for the productAggreagte yet or if the month found is greater than the one we have at hands if (!isset($undoProductAggregates[$inPos->accountable_id]) || strcmp($undoProductAggregates[$inPos->accountable_id], $inPos->month) > 0) { $undoProductAggregates[$inPos->accountable_id] = $inPos->month; } } foreach ($productAggregates as $productAggregate) { if (!$productAggregate->last_autobill) { continue; } if (!isset($undoProductAggregates[$productAggregate->id])) { $product = $this->_cachedProducts->getById($productAggregate->product_id); if (!$product) { $product = Sales_Controller_Product::getInstance()->get($productAggregate->product_id); $this->_cachedProducts->addRecord($product); } if ($product->accountable == 'Sales_Model_Product' || $record->date != null && $record->date->isLater($productAggregate->last_autobill)) { continue; } $productAggregate->last_autobill->subMonth($productAggregate->interval); } else { $productAggregate->last_autobill = new Tinebase_DateTime($undoProductAggregates[$productAggregate->id] . '-01 00:00:00', Tinebase_Core::getUserTimezone()); if ($productAggregate->billing_point == 'begin') { $productAggregate->last_autobill->subMonth($productAggregate->interval); } if ($productAggregate->start_date && $productAggregate->last_autobill < $productAggregate->start_date) { $tmp = clone $productAggregate->start_date; $tmp->setTimezone(Tinebase_Core::getUserTimezone()); $tmp->setDate($tmp->format('Y'), $tmp->format('m'), 1); $tmp->setTime(0, 0, 0); if ($productAggregate->last_autobill < $tmp || $productAggregate->billing_point == 'end' && $productAggregate->last_autobill == $tmp) { $productAggregate->last_autobill = NULL; } } } $productAggregate->setTimezone('UTC'); $paController->update($productAggregate); $productAggregate->setTimezone(Tinebase_Core::getUserTimezone()); } } } } return $_ids; }
/** * returns recipients for a resource notification * * users who are allowed to edit a resource, should receive a notification * * @param Calendar_Model_Resource $_lead * @return array array of int|Addressbook_Model_Contact */ public function getNotificationRecipients(Calendar_Model_Resource $resource) { $recipients = array(); $relations = Tinebase_Relations::getInstance()->getRelations('Calendar_Model_Resource', 'Sql', $resource->getId(), true); foreach ($relations as $relation) { if ($relation->related_model == 'Addressbook_Model_Contact' && $relation->type == 'RESPONSIBLE') { $recipients[] = $relation->related_record; } } if (empty($recipients)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__CLASS__ . '::' . __METHOD__ . '::' . __LINE__ . ' no responsibles found for calendar resource: ' . $resource->getId() . ' sending notification to all people having edit access to container ' . $resource->container_id); } $containerGrants = Tinebase_Container::getInstance()->getGrantsOfContainer($resource->container_id, TRUE); foreach ($containerGrants as $grant) { if ($grant['account_type'] == Tinebase_Acl_Rights::ACCOUNT_TYPE_USER && $grant[Tinebase_Model_Grants::GRANT_EDIT] == 1) { try { $recipient = Addressbook_Controller_Contact::getInstance()->getContactByUserId($grant['account_id'], TRUE); $recipients[] = $recipient; } catch (Addressbook_Exception_NotFound $aenf) { if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__CLASS__ . '::' . __METHOD__ . '::' . __LINE__ . ' Do not send notification to non-existant user: ' . $aenf->getMessage()); } } } } } return $recipients; }
/** * create notification message for task alarm * * @return string * * @todo should we get the locale pref for each single user here instead of the default? * @todo move lead stuff to Crm(_Model_Lead)? * @todo add getSummary to Addressbook_Model_Contact for linked contacts? */ public function getNotificationMessage() { // get locale from prefs $localePref = Tinebase_Core::getPreference()->getValue(Tinebase_Preference::LOCALE); $locale = Tinebase_Translation::getLocale($localePref); $translate = Tinebase_Translation::getTranslation($this->_application, $locale); // get date strings $timezone = $this->originator_tz ? $this->originator_tz : Tinebase_Core::get(Tinebase_Core::USERTIMEZONE); $dueDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($this->due, $timezone, $locale); // resolve values Tinebase_User::getInstance()->resolveUsers($this, 'organizer', true); $status = Tasks_Config::getInstance()->get(Tasks_Config::TASK_STATUS)->records->getById($this->status); $organizerName = $this->organizer ? $this->organizer->accountDisplayName : ''; //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($this->toArray(), TRUE)); $text = $this->summary . "\n\n" . $translate->_('Due') . ': ' . $dueDateString . "\n" . $translate->_('Organizer') . ': ' . $organizerName . "\n" . $translate->_('Description') . ': ' . $this->description . "\n" . $translate->_('Priority') . ': ' . $this->priority . "\n" . $translate->_('Status') . ': ' . $translate->_($status['value']) . "\n" . $translate->_('Percent') . ': ' . $this->percent . "%\n\n"; // add relations (get with ignore acl) $relations = Tinebase_Relations::getInstance()->getRelations(get_class($this), 'Sql', $this->getId(), NULL, array('TASK'), TRUE); foreach ($relations as $relation) { if ($relation->related_model == 'Crm_Model_Lead') { $lead = $relation->related_record; $text .= $translate->_('Lead') . ': ' . $lead->lead_name . "\n"; $leadRelations = Tinebase_Relations::getInstance()->getRelations(get_class($lead), 'Sql', $lead->getId()); foreach ($leadRelations as $leadRelation) { if ($leadRelation->related_model == 'Addressbook_Model_Contact') { $contact = $leadRelation->related_record; $text .= $leadRelation->type . ': ' . $contact->n_fn . ' (' . $contact->org_name . ')' . "\n" . (!empty($contact->tel_work) ? "\t" . $translate->_('Telephone') . ': ' . $contact->tel_work . "\n" : '') . (!empty($contact->email) ? "\t" . $translate->_('Email') . ': ' . $contact->email . "\n" : ''); } } } } //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $text); return $text; }
/** * returns own ids defined by relation filter * * @param string $_modelName * @return array */ protected function _getOwnIds($_modelName) { $relationFilter = new Tinebase_Model_RelationFilter(array(array('field' => 'own_model', 'operator' => 'equals', 'value' => $_modelName), array('field' => 'related_model', 'operator' => 'equals', 'value' => $this->_options['related_model']), array('field' => 'related_id', 'operator' => 'in', 'value' => $this->_foreignIds))); if ($this->_relationTypeFilter) { $typeValue = $this->_relationTypeFilter['value']; if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . 'Adding Relation type filter: ' . (is_array($typeValue) ? implode(',', $typeValue) : $typeValue)); } $relationFilter->addFilter($relationFilter->createFilter('type', $this->_relationTypeFilter['operator'], $typeValue)); } $ownIds = Tinebase_Relations::getInstance()->search($relationFilter, NULL)->own_id; if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' own ids: ' . print_r($ownIds, TRUE)); } return $ownIds; }
/** * @param Sales_Model_Contract $contractId */ public function getTimeaccountsBySalesContract($contractId) { $contractId = is_string($contractId) ? $contractId : $contractId->getId(); $filter = new Tinebase_Model_RelationFilter(array(array('field' => 'related_model', 'operator' => 'equals', 'value' => 'Sales_Model_Contract'), array('field' => 'related_id', 'operator' => 'equals', 'value' => $contractId), array('field' => 'own_model', 'operator' => 'equals', 'value' => 'Timetracker_Model_Timeaccount'), array('field' => 'type', 'operator' => 'equals', 'value' => 'TIME_ACCOUNT')), 'AND'); return Sales_Controller_Contract::getInstance()->getMultiple(Tinebase_Relations::getInstance()->search($filter)->own_id); }
/** * transfers all contracts starting with AB- to orderconfirmation */ public function transferContractsToOrderConfirmation() { if (!Sales_Config::getInstance()->featureEnabled(Sales_Config::FEATURE_ORDERCONFIRMATIONS_MODULE)) { Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' transferContractsToOrderConfirmation ran allthoug feature ' . Sales_Config::FEATURE_ORDERCONFIRMATIONS_MODULE . ' is disabled'); return false; } $contractController = Sales_Controller_Contract::getInstance(); $ocController = Sales_Controller_OrderConfirmation::getInstance(); $rel = Tinebase_Relations::getInstance(); $filter = new Sales_Model_ContractFilter(array(array('field' => 'number', 'operator' => 'startswith', 'value' => 'AB-')), 'AND'); $contracts = $contractController->search($filter); foreach ($contracts as $contract) { $oc = $ocController->create(new Sales_Model_OrderConfirmation(array('number' => $contract->number, 'title' => $contract->title, 'description' => ''))); $rel->setRelations('Sales_Model_OrderConfirmation', 'Sql', $oc->getId(), array(array('related_degree' => 'sibling', 'related_degree' => 'sibling', 'related_model' => 'Sales_Model_Contract', 'related_backend' => 'Sql', 'related_id' => $contract->getId(), 'type' => 'CONTRACT'))); } }
/** * get all relations of a given record * * @param string $_model own model to get relations for * @param string $_id own id to get relations for * @param string $_degree only return relations of given degree * @param array $_type only return relations of given type * @param string $_relatedModel only return relations having this related model * @return array */ public function getRelations($model, $id, $degree = NULL, $type = array(), $relatedModel = NULL) { $relations = Tinebase_Relations::getInstance()->getRelations($model, 'Sql', $id, $degree, $type, false, $relatedModel); // @TODO we still have no converter for relations :-( // -> related records returned here are different to the records returned by the apps itself! // -> this problem also applies to to generic json converter! if (count($relations) > 0) { $relations->setTimezone(Tinebase_Core::getUserTimezone()); $relations->bypassFilters = true; $result = $relations->toArray(); } else { $result = array(); } return array('results' => array_values($result), 'totalcount' => count($result)); }
public function getRelationsOfRecordByDegree($record, $degree) { // get relations if not yet present OR use relation search here if (empty($record->relations)) { $backendType = 'Sql'; $modelName = get_class($record); $record->relations = Tinebase_Relations::getInstance()->getRelations($modelName, $backendType, $record->getId()); } $result = new Tinebase_Record_RecordSet('Tinebase_Model_Relation'); foreach ($record->relations as $relation) { if ($relation->related_degree === $degree) { $result->addRecord($relation); } } return $result; }