private function _fillMatrix()
 {
     foreach ($this->_operations->getOperations() as $operation) {
         $increment = new ReportMatrixIncrement($this->_currency);
         $increment->setOperation($operation);
         $this->_root->_pushIncrement($increment);
     }
 }
 /**
  * Выборка операций за период
  */
 public function testFillForPeriod()
 {
     $dateStart = new DateTime(date('Y-m-01'));
     $dateEnd = date_add(clone $dateStart, new DateInterval('P1M'));
     $op = $this->helper->makeOperation();
     $operationCollection = new OperationCollection($op->getUser());
     $operationCollection->setPeriodStartDate($dateStart)->setPeriodEndDate($dateEnd)->fill();
     $this->assertNotEquals(0, count($operationCollection->getOperations()));
 }
 /**
  * Строит матричный отчёт
  * @param User $user
  * @param Account $account
  * @param DateTime $startDate
  * @param DateTime $endDate
  * @param int $operationType
  */
 public function buildReport(User $user, Account $account = null, DateTime $startDate, DateTime $endDate, $operationType = null)
 {
     $totalLabel = "ИТОГО:";
     $operationCollection = new OperationCollection($user);
     $operationCollection->setPeriodStartDate($startDate)->setPeriodEndDate($endDate)->setAcceptedOnly(true)->fill();
     $operations = $operationCollection->getOperations();
     $this->_tags = array();
     $this->_categories = array();
     $this->_matrix = array();
     $this->_totalCategory = new Category();
     $this->_totalCategory->setId(-1);
     $this->_totalCategory->setName($totalLabel);
     $this->_totalCategory->setParentId(null);
     $this->_totalTag = $totalLabel;
     foreach ($operations as $operation) {
         if ($operationType !== null && $operationType != $operation->getType()) {
             continue;
         }
         if ($account && $operation->getAccount() != $account) {
             continue;
         }
         $category = $operation->getCategory();
         $opTags = array_map('trim', explode(',', $operation->getTags()));
         //возьмем первый тэг операции (считаем, что тэг - один)
         //если тэгов у операции нет, присвоим специальный тэг
         $tag = isset($opTags[0]) && strlen($opTags[0]) > 0 ? $opTags[0] : self::TAG_FOR_OPERATIONS_WITHOUT_TAGS;
         if ($tag && $category) {
             $this->_addTagAndCategory($tag, $category, $operation);
         }
     }
     //сортируем по алфавиту, но итоговые значения ставим самыми последними
     $sortLabelsWithTotal = function ($firstLabel, $secondLabel) use($totalLabel) {
         if ($firstLabel == $totalLabel) {
             return 1;
         } else {
             if ($secondLabel == $totalLabel) {
                 return -1;
             } else {
                 return $firstLabel < $secondLabel;
             }
         }
     };
     usort($this->_categories, $sortLabelsWithTotal);
     usort($this->_tags, $sortLabelsWithTotal);
     $this->_buildHeaderLeft($this->_categories);
     $this->_buildHeaderTop($this->_tags);
 }
 /**
  * Загружает список статей бюджета
  * @param User $user
  * @param DateTime $startDate - дата начала текущего месяца
  * @throws myBudgetWrongStartDateException
  */
 public function load(User $user, DateTime $startDate)
 {
     if ($startDate->format('d') !== '01') {
         throw new myBudgetWrongStartDateException(sprintf('Дата должна быть первым числом месяца, получена %s', $startDate->format('Y-m-d')));
     }
     //получим операции за этот месяц - для подсчета текущего бюджета,
     //и за предыдущие - для подсчета среднего показателя
     //средний показатель рассчитываем по трем предыдущим месяцам
     $meanRateMonthsAmount = 3;
     $beginDate = date_sub(clone $startDate, new DateInterval("P" . $meanRateMonthsAmount . "M"));
     //дата конца - последнее число заданного месяца, т.е. "начало месяца + 1 месяц - 1 день"
     $endDate = date_sub(date_add(clone $startDate, new DateInterval("P1M")), new DateInterval("P1D"));
     //получим выборку операций за рассчитанный период
     $operations = new OperationCollection($user);
     $operations->setPeriodStartDate($beginDate)->setPeriodEndDate($endDate)->fill();
     //получим бюджет на месяц (коллекцию статей бюджета на заданный месяц)
     $budget = new Budget();
     $budget->fill($user, $startDate);
     $calculator = new BudgetArticleIncrementCalculator($startDate, $user->getCurrency(), $meanRateMonthsAmount);
     //TODO: всю логику подсчета можно вынести в отдельный калькулятор бюджета и тестить его уже модульно,
     //без привлечения базы, передавая готовые операции и статьи бюджета
     //по каждой операции определим ее вклад в соотв. статью бюджета или средний показатель
     foreach ($operations->getOperations() as $operation) {
         $category = $operation->getCategory();
         // отсутствие категории -- штатная ситуация
         // например, перевод или неподтвежденная операция в календаре
         if ($category) {
             //определяем, к какой категории относится операция, и по ней определяем статью бюджета
             //категорию берем не напрямую из связи операции, а вычисляем для корректного учета переводов
             //если категория не запланирована, создается и возвращается пустая
             $currentBudgetArticle = $budget->getBudgetArticleByCategory($category);
             $increment = $calculator->calculate($operation);
             $increment->apply($currentBudgetArticle);
         }
     }
     //возвращаем уже заполненные категории
     return $budget->getBudgetArticles();
 }