/**
  * export invoices
  *
  * @param string $filter JSON encoded string with employee ids for multi export or employee filter
  * @param string $options format or export definition id
  */
 public function exportInvoices($filter, $options)
 {
     $decodedFilter = Zend_Json::decode($filter);
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Export filter: ' . print_r($decodedFilter, TRUE));
     }
     if (!is_array($decodedFilter)) {
         $decodedFilter = array(array('field' => 'id', 'operator' => 'equals', 'value' => $decodedFilter));
     }
     $filter = new Sales_Model_InvoiceFilter($decodedFilter);
     parent::_export($filter, Zend_Json::decode($options), Sales_Controller_Invoice::getInstance());
 }
 /**
  * the singleton pattern
  *
  * @return Sales_Controller_Invoice
  */
 public static function getInstance()
 {
     if (self::$_instance === NULL) {
         self::$_instance = new self();
     }
     return self::$_instance;
 }
 protected function _removeFixtures()
 {
     if ($this->_customerRecords) {
         Sales_Controller_Customer::getInstance()->delete($this->_customerRecords->getId());
     }
     if ($this->_contactRecords) {
         $this->_contactController->delete($this->_contactRecords->getId());
     }
     if ($this->_addressRecords) {
         $this->_addressController->delete($this->_addressRecords->getId());
     }
     if ($this->_contractRecords) {
         Sales_Controller_Contract::getInstance()->delete($this->_contractRecords->getId());
     }
     $paController = Sales_Controller_ProductAggregate::getInstance();
     $paController->deleteByFilter(new Sales_Model_ProductAggregateFilter(array()));
     $this->_invoiceController = Sales_Controller_Invoice::getInstance();
     $this->_invoiceController->deleteByFilter(new Sales_Model_InvoiceFilter(array()));
 }
 /**
  * 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);
         }
     }
 }
 /**
  * deletes existing records
  *
  * @param  array $ids
  * @return string
  */
 public function deleteInvoices($ids)
 {
     return $this->_delete($ids, Sales_Controller_Invoice::getInstance());
 }
 /**
  * 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);
         }
     }
 }
 /**
  * tests special auto invoice creation
  */
 public function testSpecialExportInvoice()
 {
     $this->_createFullFixtures();
     $date = clone $this->_referenceDate;
     $i = 0;
     // until 1.7
     while ($i < 8) {
         $this->_invoiceController->createAutoInvoices($date);
         $date->addMonth(1);
         $i++;
     }
     $definition = dirname(dirname(dirname(dirname(__FILE__)))) . '/tine20/Sales/Export/definitions/invoice_special_ods.xml';
     $filter = new Sales_Model_InvoiceFilter(array());
     $exporter = new Sales_Export_Ods_Invoice($filter, Sales_Controller_Invoice::getInstance(), array('definitionFilename' => $definition));
     $doc = $exporter->generate();
     $xml = $this->_getContentXML($doc);
     $ns = $xml->getNamespaces(true);
     $spreadsheetXml = $xml->children($ns['office'])->{'body'}->{'spreadsheet'};
     // the product should be found here
     $this->assertEquals('Debitor', (string) $spreadsheetXml->children($ns['table'])->{'table'}->{'table-row'}->{1}->children($ns['table'])->{'table-cell'}->{3}->children($ns['text'])->{0});
 }
 /**
  * tests special auto invoice creation
  */
 public function testSpecialExportInvoice()
 {
     if ($this->_dbIsPgsql()) {
         $this->markTestSkipped('0011670: fix Sales_Invoices Tests with postgresql backend');
     }
     $this->_createFullFixtures();
     $date = clone $this->_referenceDate;
     $i = 0;
     // until 1.7
     while ($i < 8) {
         $this->_invoiceController->createAutoInvoices($date);
         $date->addMonth(1);
         $i++;
     }
     $definition = dirname(dirname(dirname(dirname(__FILE__)))) . '/tine20/Sales/Export/definitions/invoice_special_ods.xml';
     $filter = new Sales_Model_InvoiceFilter(array());
     $exporter = new Sales_Export_Ods_Invoice($filter, Sales_Controller_Invoice::getInstance(), array('definitionFilename' => $definition));
     $doc = $exporter->generate();
     $xml = $this->_getContentXML($doc);
     $ns = $xml->getNamespaces(true);
     $spreadsheetXml = $xml->children($ns['office'])->{'body'}->{'spreadsheet'};
     $text = $spreadsheetXml->xpath('((.//table:table/table:table-row)[2]/table:table-cell)[4]/text:p');
     $text = $text[0];
     // the product should be found here
     $this->assertEquals('Debitor', (string) $text);
 }
 /**
  * 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);
 }
 /**
  * creates the invoices - no containers, just "shared"
  */
 protected function _createSharedInvoices()
 {
     $sic = Sales_Controller_Invoice::getInstance();
     $now = new Tinebase_DateTime();
     $now->setTimezone(Tinebase_Core::getUserTimezone());
     $now->setDate($now->format('Y'), $now->format('m'), 1);
     $now->setTime(3, 0, 0);
     $date = clone $this->_referenceDate;
     while ($date < $now) {
         $sic->createAutoInvoices($date);
         $date->addMonth(1);
     }
 }
 /**
  * returns multiple records prepared for json transport
  * NOTE: we can't use parent::_multipleRecordsToJson here because of the different container handling
  *
  * @param Tinebase_Record_RecordSet $_records Tinebase_Record_Abstract
  * @param Tinebase_Model_Filter_FilterGroup
  * @param Tinebase_Model_Pagination $_pagination
  * @return array data
  * 
  * @todo replace with Timetracker_Convert_*
  */
 protected function _multipleRecordsToJson(Tinebase_Record_RecordSet $_records, $_filter = NULL, $_pagination = NULL)
 {
     if (count($_records) == 0) {
         return array();
     }
     switch ($_records->getRecordClassName()) {
         case 'Timetracker_Model_Timesheet':
             // resolve timeaccounts
             $timeaccountIds = $_records->timeaccount_id;
             $timeaccounts = $this->_timeaccountController->getMultiple(array_unique(array_values($timeaccountIds)));
             $invoices = FALSE;
             Timetracker_Model_TimeaccountGrants::getGrantsOfRecords($timeaccounts, Tinebase_Core::get('currentAccount'));
             foreach ($_records as $record) {
                 $idx = $timeaccounts->getIndexById($record->timeaccount_id);
                 if ($idx !== FALSE) {
                     $record->timeaccount_id = $timeaccounts[$idx];
                     $record->timeaccount_id->account_grants = $this->_resolveTimesheetGrantsByTimeaccountGrants($record->timeaccount_id->account_grants, $record->account_id);
                 } else {
                     Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Could not resolve timeaccount (id: ' . $record->timeaccount_id . '). No permission?');
                 }
             }
             // resolve user afterwards because we compare ids in _resolveTimesheetGrantsByTimeaccountGrants()
             Tinebase_User::getInstance()->resolveMultipleUsers($_records, array('account_id', 'created_by', 'last_modified_by'), true);
             break;
         case 'Timetracker_Model_Timeaccount':
             // resolve timeaccounts grants
             Timetracker_Model_TimeaccountGrants::getGrantsOfRecords($_records, Tinebase_Core::get('currentAccount'));
             $this->_resolveTimeaccountGrants($_records);
             break;
     }
     if (Tinebase_Core::getUser()->hasRight('Sales', 'manage_invoices')) {
         $invoiceIds = array_unique(array_values($_records->invoice_id));
         $invoices = Sales_Controller_Invoice::getInstance()->getMultiple($invoiceIds);
         foreach ($_records as $record) {
             if ($invoices && $record->invoice_id) {
                 $record->invoice_id = $invoices->getById($record->invoice_id);
             }
         }
     }
     Tinebase_Tags::getInstance()->getMultipleTagsOfRecords($_records);
     $_records->setTimezone(Tinebase_Core::getUserTimezone());
     $_records->convertDates = true;
     $result = $_records->toArray();
     return $result;
 }