mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 10:47:00 +00:00 
			
		
		
		
	Fix #2820
This commit is contained in:
		| @@ -71,109 +71,6 @@ trait AugumentData | ||||
|         return $combined; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Group by category (earnings). | ||||
|      * | ||||
|      * @param Collection $assets | ||||
|      * @param Collection $opposing | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      * | ||||
|      */ | ||||
|     protected function earnedByCategory(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array // get data + augment with info | ||||
|     { | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector = app(GroupCollectorInterface::class); | ||||
|  | ||||
|         $total = $assets->merge($opposing); | ||||
|         $collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($total); | ||||
|         $collector->withCategoryInformation(); | ||||
|         $journals = $collector->getExtractedJournals(); | ||||
|         $sum      = []; | ||||
|         // loop to support multi currency | ||||
|         foreach ($journals as $journal) { | ||||
|             $currencyId   = $journal['currency_id']; | ||||
|             $categoryName = $journal['category_name']; | ||||
|             $categoryId   = (int)$journal['category_id']; | ||||
|  | ||||
|             // if not set, set to zero: | ||||
|             if (!isset($sum[$categoryId][$currencyId])) { | ||||
|                 $sum[$categoryId] = [ | ||||
|                     'grand_total'  => '0', | ||||
|                     'name'         => $categoryName, | ||||
|                     'per_currency' => [ | ||||
|                         $currencyId => [ | ||||
|                             'sum'      => '0', | ||||
|                             'category' => [ | ||||
|                                 'id'   => $categoryId, | ||||
|                                 'name' => $categoryName, | ||||
|                             ], | ||||
|                             'currency' => [ | ||||
|                                 'symbol' => $journal['currency_symbol'], | ||||
|                                 'dp'     => $journal['currency_decimal_places'], | ||||
|                             ], | ||||
|                         ], | ||||
|                     ], | ||||
|                 ]; | ||||
|             } | ||||
|  | ||||
|             // add amount | ||||
|             $sum[$categoryId]['per_currency'][$currencyId]['sum'] = bcadd( | ||||
|                 $sum[$categoryId]['per_currency'][$currencyId]['sum'], $journal['amount'] | ||||
|             ); | ||||
|             $sum[$categoryId]['grand_total']                      = bcadd($sum[$categoryId]['grand_total'], $journal['amount']); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Earned in period for accounts. | ||||
|      * | ||||
|      * @param Collection $assets | ||||
|      * @param Collection $opposing | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function earnedInPeriod(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array // get data + augment with info | ||||
|     { | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector = app(GroupCollectorInterface::class); | ||||
|  | ||||
|         $total = $assets->merge($opposing); | ||||
|         $collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($total); | ||||
|         $journals = $collector->getExtractedJournals(); | ||||
|         $sum      = [ | ||||
|             'grand_sum'    => '0', | ||||
|             'per_currency' => [], | ||||
|         ]; | ||||
|         // loop to support multi currency | ||||
|         foreach ($journals as $journal) { | ||||
|             $currencyId = (int)$journal['currency_id']; | ||||
|  | ||||
|             // if not set, set to zero: | ||||
|             if (!isset($sum['per_currency'][$currencyId])) { | ||||
|                 $sum['per_currency'][$currencyId] = [ | ||||
|                     'sum'      => '0', | ||||
|                     'currency' => [ | ||||
|                         'symbol'         => $journal['currency_symbol'], | ||||
|                         'decimal_places' => $journal['currency_decimal_places'], | ||||
|                     ], | ||||
|                 ]; | ||||
|             } | ||||
|  | ||||
|             // add amount | ||||
|             $sum['per_currency'][$currencyId]['sum'] = bcadd($sum['per_currency'][$currencyId]['sum'], $journal['amount']); | ||||
|             $sum['grand_sum']                        = bcadd($sum['grand_sum'], $journal['amount']); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Small helper function for the revenue and expense account charts. | ||||
|      * | ||||
| @@ -209,34 +106,6 @@ trait AugumentData | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the budget limits belonging to the given budget and valid on the given day. | ||||
|      * | ||||
|      * @param Collection $budgetLimits | ||||
|      * @param Budget     $budget | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     protected function filterBudgetLimits(Collection $budgetLimits, Budget $budget, Carbon $start, Carbon $end): Collection // filter data | ||||
|     { | ||||
|         $set = $budgetLimits->filter( | ||||
|             static function (BudgetLimit $budgetLimit) use ($budget, $start, $end) { | ||||
|                 if ($budgetLimit->budget_id === $budget->id | ||||
|                     && $budgetLimit->start_date->lte($start) // start of budget limit is on or before start | ||||
|                     && $budgetLimit->end_date->gte($end) // end of budget limit is on or after end | ||||
|                 ) { | ||||
|                     return $budgetLimit; | ||||
|                 } | ||||
|  | ||||
|                 return false; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the account names belonging to a bunch of account ID's. | ||||
|      * | ||||
| @@ -285,39 +154,6 @@ trait AugumentData | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the amount of money budgeted in a period. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getBudgetedInPeriod(Budget $budget, Carbon $start, Carbon $end): array // get data + augment with info | ||||
|     { | ||||
|         /** @var BudgetLimitRepositoryInterface $blRepository */ | ||||
|         $blRepository = app(BudgetLimitRepositoryInterface::class); | ||||
|  | ||||
|         $key      = app('navigation')->preferredCarbonFormat($start, $end); | ||||
|         $range    = app('navigation')->preferredRangeFormat($start, $end); | ||||
|         $current  = clone $start; | ||||
|         $budgeted = []; | ||||
|         while ($current < $end) { | ||||
|             /** @var Carbon $currentStart */ | ||||
|             $currentStart = app('navigation')->startOfPeriod($current, $range); | ||||
|             /** @var Carbon $currentEnd */ | ||||
|             $currentEnd       = app('navigation')->endOfPeriod($current, $range); | ||||
|             $budgetLimits     = $blRepository->getBudgetLimits($budget, $currentStart, $currentEnd); | ||||
|             $index            = $currentStart->format($key); | ||||
|             $budgeted[$index] = $budgetLimits->sum('amount'); | ||||
|             $currentEnd->addDay(); | ||||
|             $current = clone $currentEnd; | ||||
|         } | ||||
|  | ||||
|         return $budgeted; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the category names from a set of category ID's. Small helper function for some of the charts. | ||||
|      * | ||||
| @@ -342,48 +178,6 @@ trait AugumentData | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the expenses for a budget in a date range. | ||||
|      * | ||||
|      * @param Collection $limits | ||||
|      * @param Budget     $budget | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      * | ||||
|      */ | ||||
|     protected function getExpensesForBudget(Collection $limits, Budget $budget, Carbon $start, Carbon $end): array // get data + augment with info | ||||
|     { | ||||
|         /** @var BudgetRepositoryInterface $repository */ | ||||
|         $repository = app(BudgetRepositoryInterface::class); | ||||
|  | ||||
|         /** @var OperationsRepositoryInterface $opsRepository */ | ||||
|         $opsRepository = app(OperationsRepositoryInterface::class); | ||||
|  | ||||
|         $return = []; | ||||
|         if (0 === $limits->count()) { | ||||
|             $spent = $opsRepository->spentInPeriod(new Collection([$budget]), new Collection, $start, $end); | ||||
|             if (0 !== bccomp($spent, '0')) { | ||||
|                 $return[$budget->name]['spent']     = bcmul($spent, '-1'); | ||||
|                 $return[$budget->name]['left']      = 0; | ||||
|                 $return[$budget->name]['overspent'] = 0; | ||||
|             } | ||||
|  | ||||
|             return $return; | ||||
|         } | ||||
|  | ||||
|         $rows = $this->spentInPeriodMulti($budget, $limits); | ||||
|         foreach ($rows as $name => $row) { | ||||
|             if (0 !== bccomp($row['spent'], '0') || 0 !== bccomp($row['left'], '0')) { | ||||
|                 $return[$name] = $row; | ||||
|             } | ||||
|         } | ||||
|         unset($rows); | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets all budget limits for a budget. | ||||
|      * | ||||
| @@ -425,48 +219,6 @@ trait AugumentData | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Helper function that groups expenses. | ||||
|      * | ||||
|      * @param array $array | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function groupByBudget(array $array): array // filter + group data | ||||
|     { | ||||
|         // group by category ID: | ||||
|         $grouped = []; | ||||
|         /** @var array $journal */ | ||||
|         foreach ($array as $journal) { | ||||
|             $budgetId           = (int)$journal['budget_id']; | ||||
|             $grouped[$budgetId] = $grouped[$budgetId] ?? '0'; | ||||
|             $grouped[$budgetId] = bcadd($journal['amount'], $grouped[$budgetId]); | ||||
|         } | ||||
|  | ||||
|         return $grouped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Group transactions by category. | ||||
|      * | ||||
|      * @param array $array | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function groupByCategory(array $array): array // filter + group data | ||||
|     { | ||||
|         // group by category ID: | ||||
|         $grouped = []; | ||||
|         /** @var array $journal */ | ||||
|         foreach ($array as $journal) { | ||||
|             $categoryId           = (int)$journal['category_id']; | ||||
|             $grouped[$categoryId] = $grouped[$categoryId] ?? '0'; | ||||
|             $grouped[$categoryId] = bcadd($journal['amount'], $grouped[$categoryId]); | ||||
|         } | ||||
|  | ||||
|         return $grouped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Group set of transactions by name of opposing account. | ||||
|      * | ||||
| @@ -496,147 +248,6 @@ trait AugumentData | ||||
|         return $grouped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Group transactions by tag. | ||||
|      * | ||||
|      * @param array $array | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function groupByTag(array $array): array // filter + group data | ||||
|     { | ||||
|         // group by category ID: | ||||
|         $grouped = []; | ||||
|         /** @var array $journal */ | ||||
|         foreach ($array as $journal) { | ||||
|             $tags = $journal['tags'] ?? []; | ||||
|             /** | ||||
|              * @var int   $id | ||||
|              * @var array $tag | ||||
|              */ | ||||
|             foreach ($tags as $id => $tag) { | ||||
|                 $grouped[$id] = $grouped[$id] ?? '0'; | ||||
|                 $grouped[$id] = bcadd($journal['amount'], $grouped[$id]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $grouped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Spent by budget. | ||||
|      * | ||||
|      * @param Collection $assets | ||||
|      * @param Collection $opposing | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      * | ||||
|      */ | ||||
|     protected function spentByBudget(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array // get data + augment with info | ||||
|     { | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector = app(GroupCollectorInterface::class); | ||||
|         $total     = $assets->merge($opposing); | ||||
|         $collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($total); | ||||
|         $collector->withBudgetInformation(); | ||||
|         $journals = $collector->getExtractedJournals(); | ||||
|         $sum      = []; | ||||
|         // loop to support multi currency | ||||
|         foreach ($journals as $journal) { | ||||
|             $currencyId = $journal['currency_id']; | ||||
|             $budgetName = $journal['budget_name']; | ||||
|             $budgetId   = (int)$journal['budget_id']; | ||||
|  | ||||
|             // if not set, set to zero: | ||||
|             if (!isset($sum[$budgetId][$currencyId])) { | ||||
|                 $sum[$budgetId] = [ | ||||
|                     'grand_total'  => '0', | ||||
|                     'name'         => $budgetName, | ||||
|                     'per_currency' => [ | ||||
|                         $currencyId => [ | ||||
|                             'sum'      => '0', | ||||
|                             'budget'   => [ | ||||
|                                 'id'   => $budgetId, | ||||
|                                 'name' => $budgetName, | ||||
|                             ], | ||||
|                             'currency' => [ | ||||
|                                 'symbol' => $journal['currency_symbol'], | ||||
|                                 'dp'     => $journal['currency_decimal_places'], | ||||
|                             ], | ||||
|                         ], | ||||
|                     ], | ||||
|                 ]; | ||||
|             } | ||||
|  | ||||
|             // add amount | ||||
|             $sum[$budgetId]['per_currency'][$currencyId]['sum'] = bcadd( | ||||
|                 $sum[$budgetId]['per_currency'][$currencyId]['sum'], $journal['amount'] | ||||
|             ); | ||||
|             $sum[$budgetId]['grand_total']                      = bcadd($sum[$budgetId]['grand_total'], $journal['amount']); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Spent by category. | ||||
|      * | ||||
|      * @param Collection $assets | ||||
|      * @param Collection $opposing | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      * | ||||
|      */ | ||||
|     protected function spentByCategory(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array // get data + augment with info | ||||
|     { | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector = app(GroupCollectorInterface::class); | ||||
|         $total     = $assets->merge($opposing); | ||||
|         $collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($total); | ||||
|         $collector->withCategoryInformation(); | ||||
|         $journals = $collector->getExtractedJournals(); | ||||
|         $sum      = []; | ||||
|         // loop to support multi currency | ||||
|         foreach ($journals as $journal) { | ||||
|             $currencyId   = (int)$journal['currency_id']; | ||||
|             $categoryName = $journal['category_name']; | ||||
|             $categoryId   = (int)$journal['category_id']; | ||||
|  | ||||
|             // if not set, set to zero: | ||||
|             if (!isset($sum[$categoryId][$currencyId])) { | ||||
|                 $sum[$categoryId] = [ | ||||
|                     'grand_total'  => '0', | ||||
|                     'name'         => $categoryName, | ||||
|                     'per_currency' => [ | ||||
|                         $currencyId => [ | ||||
|                             'sum'      => '0', | ||||
|                             'category' => [ | ||||
|                                 'id'   => $categoryId, | ||||
|                                 'name' => $categoryName, | ||||
|                             ], | ||||
|                             'currency' => [ | ||||
|                                 'symbol' => $journal['currency_symbol'], | ||||
|                                 'dp'     => $journal['currency_decimal_places'], | ||||
|                             ], | ||||
|                         ], | ||||
|                     ], | ||||
|                 ]; | ||||
|             } | ||||
|  | ||||
|             // add amount | ||||
|             $sum[$categoryId]['per_currency'][$currencyId]['sum'] = bcadd( | ||||
|                 $sum[$categoryId]['per_currency'][$currencyId]['sum'], $journal['amount'] | ||||
|             ); | ||||
|             $sum[$categoryId]['grand_total']                      = bcadd($sum[$categoryId]['grand_total'], $journal['amount']); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Spent in a period. | ||||
|      * | ||||
| @@ -682,85 +293,4 @@ trait AugumentData | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * Returns an array with the following values: | ||||
|      * 0 => | ||||
|      *   'name' => name of budget + repetition | ||||
|      *   'left' => left in budget repetition (always zero) | ||||
|      *   'overspent' => spent more than budget repetition? (always zero) | ||||
|      *   'spent' => actually spent in period for budget | ||||
|      * 1 => (etc) | ||||
|      * | ||||
|      * @param Budget     $budget | ||||
|      * @param Collection $limits | ||||
|      * | ||||
|      * @return array | ||||
|      * | ||||
|      */ | ||||
|     protected function spentInPeriodMulti(Budget $budget, Collection $limits): array // get data + augment with info | ||||
|     { | ||||
|         /** @var BudgetRepositoryInterface $repository */ | ||||
|         $repository = app(BudgetRepositoryInterface::class); | ||||
|  | ||||
|         /** @var OperationsRepositoryInterface $opsRepository */ | ||||
|         $opsRepository = app(OperationsRepositoryInterface::class); | ||||
|  | ||||
|         $return = []; | ||||
|         $format = (string)trans('config.month_and_day'); | ||||
|         $name   = $budget->name; | ||||
|         /** @var BudgetLimit $budgetLimit */ | ||||
|         foreach ($limits as $budgetLimit) { | ||||
|             $expenses = $opsRepository->spentInPeriod(new Collection([$budget]), new Collection, $budgetLimit->start_date, $budgetLimit->end_date); | ||||
|             $expenses = app('steam')->positive($expenses); | ||||
|  | ||||
|             if ($limits->count() > 1) { | ||||
|                 $name = $budget->name . ' ' . trans( | ||||
|                         'firefly.between_dates', | ||||
|                         [ | ||||
|                             'start' => $budgetLimit->start_date->formatLocalized($format), | ||||
|                             'end'   => $budgetLimit->end_date->formatLocalized($format), | ||||
|                         ] | ||||
|                     ); | ||||
|             } | ||||
|             $amount       = $budgetLimit->amount; | ||||
|             $leftInLimit  = bcsub($amount, $expenses); | ||||
|             $hasOverspent = bccomp($leftInLimit, '0') === -1; | ||||
|             $left         = $hasOverspent ? '0' : bcsub($amount, $expenses); | ||||
|             $spent        = $hasOverspent ? $amount : $expenses; | ||||
|             $overspent    = $hasOverspent ? app('steam')->positive($leftInLimit) : '0'; | ||||
|  | ||||
|             $return[$name] = [ | ||||
|                 'left'      => $left, | ||||
|                 'overspent' => $overspent, | ||||
|                 'spent'     => $spent, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with the following values: | ||||
|      * 'name' => "no budget" in local language | ||||
|      * 'repetition_left' => left in budget repetition (always zero) | ||||
|      * 'repetition_overspent' => spent more than budget repetition? (always zero) | ||||
|      * 'spent' => actually spent in period for budget. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function spentInPeriodWithout(Carbon $start, Carbon $end): string // get data + augment with info | ||||
|     { | ||||
|         // collector | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector = app(GroupCollectorInterface::class); | ||||
|         $types     = [TransactionType::WITHDRAWAL]; | ||||
|         $collector->setTypes($types)->setRange($start, $end)->withoutBudget(); | ||||
|  | ||||
|         return $collector->getSum(); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user