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(); }