mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-12 15:35:15 +00:00
Optimize queries for statistics.
This commit is contained in:
@@ -69,9 +69,9 @@ class FrontpageChartGenerator
|
||||
Log::debug('Now in generate for budget chart.');
|
||||
$budgets = $this->budgetRepository->getActiveBudgets();
|
||||
$data = [
|
||||
['label' => (string) trans('firefly.spent_in_budget'), 'entries' => [], 'type' => 'bar'],
|
||||
['label' => (string) trans('firefly.left_to_spend'), 'entries' => [], 'type' => 'bar'],
|
||||
['label' => (string) trans('firefly.overspent'), 'entries' => [], 'type' => 'bar'],
|
||||
['label' => (string)trans('firefly.spent_in_budget'), 'entries' => [], 'type' => 'bar'],
|
||||
['label' => (string)trans('firefly.left_to_spend'), 'entries' => [], 'type' => 'bar'],
|
||||
['label' => (string)trans('firefly.overspent'), 'entries' => [], 'type' => 'bar'],
|
||||
];
|
||||
|
||||
// loop al budgets:
|
||||
@@ -84,6 +84,64 @@ class FrontpageChartGenerator
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function setEnd(Carbon $end): void
|
||||
{
|
||||
$this->end = $end;
|
||||
}
|
||||
|
||||
public function setStart(Carbon $start): void
|
||||
{
|
||||
$this->start = $start;
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic setter for the user. Also updates the repositories with the right user.
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->budgetRepository->setUser($user);
|
||||
$this->blRepository->setUser($user);
|
||||
$this->opsRepository->setUser($user);
|
||||
|
||||
$locale = app('steam')->getLocale();
|
||||
$this->monthAndDayFormat = (string)trans('config.month_and_day_js', [], $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a budget has budget limit, each limit is processed individually.
|
||||
*/
|
||||
private function budgetLimits(array $data, Budget $budget, Collection $limits): array
|
||||
{
|
||||
Log::debug('Start processing budget limits.');
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
$data = $this->processLimit($data, $budget, $limit);
|
||||
}
|
||||
Log::debug('Done processing budget limits.');
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* When no limits are present, the expenses of the whole period are collected and grouped.
|
||||
* This is grouped per currency. Because there is no limit set, "left to spend" and "overspent" are empty.
|
||||
*/
|
||||
private function noBudgetLimits(array $data, Budget $budget): array
|
||||
{
|
||||
$spent = $this->opsRepository->sumExpenses($this->start, $this->end, null, new Collection()->push($budget));
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($spent as $entry) {
|
||||
$title = sprintf('%s (%s)', $budget->name, $entry['currency_name']);
|
||||
$data[0]['entries'][$title] = bcmul((string)$entry['sum'], '-1'); // spent
|
||||
$data[1]['entries'][$title] = 0; // left to spend
|
||||
$data[2]['entries'][$title] = 0; // overspent
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* For each budget, gets all budget limits for the current time range.
|
||||
* When no limits are present, the time range is used to collect information on money spent.
|
||||
@@ -108,41 +166,6 @@ class FrontpageChartGenerator
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* When no limits are present, the expenses of the whole period are collected and grouped.
|
||||
* This is grouped per currency. Because there is no limit set, "left to spend" and "overspent" are empty.
|
||||
*/
|
||||
private function noBudgetLimits(array $data, Budget $budget): array
|
||||
{
|
||||
$spent = $this->opsRepository->sumExpenses($this->start, $this->end, null, new Collection()->push($budget));
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($spent as $entry) {
|
||||
$title = sprintf('%s (%s)', $budget->name, $entry['currency_name']);
|
||||
$data[0]['entries'][$title] = bcmul((string) $entry['sum'], '-1'); // spent
|
||||
$data[1]['entries'][$title] = 0; // left to spend
|
||||
$data[2]['entries'][$title] = 0; // overspent
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a budget has budget limit, each limit is processed individually.
|
||||
*/
|
||||
private function budgetLimits(array $data, Budget $budget, Collection $limits): array
|
||||
{
|
||||
Log::debug('Start processing budget limits.');
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
$data = $this->processLimit($data, $budget, $limit);
|
||||
}
|
||||
Log::debug('Done processing budget limits.');
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* For each limit, the expenses from the time range of the limit are collected. Each row from the result is
|
||||
* processed individually.
|
||||
@@ -158,7 +181,7 @@ class FrontpageChartGenerator
|
||||
Log::debug(sprintf('Processing limit #%d with %s %s', $limit->id, $limit->transactionCurrency->code, $limit->amount));
|
||||
}
|
||||
|
||||
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
|
||||
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
|
||||
Log::debug(sprintf('Spent array has %d entries.', count($spent)));
|
||||
|
||||
/** @var array $entry */
|
||||
@@ -185,7 +208,7 @@ class FrontpageChartGenerator
|
||||
*/
|
||||
private function processRow(array $data, Budget $budget, BudgetLimit $limit, array $entry): array
|
||||
{
|
||||
$title = sprintf('%s (%s)', $budget->name, $entry['currency_name']);
|
||||
$title = sprintf('%s (%s)', $budget->name, $entry['currency_name']);
|
||||
Log::debug(sprintf('Title is "%s"', $title));
|
||||
if ($limit->start_date->startOfDay()->ne($this->start->startOfDay()) || $limit->end_date->startOfDay()->ne($this->end->startOfDay())) {
|
||||
$title = sprintf(
|
||||
@@ -196,22 +219,22 @@ class FrontpageChartGenerator
|
||||
$limit->end_date->isoFormat($this->monthAndDayFormat)
|
||||
);
|
||||
}
|
||||
$usePrimary = $this->convertToPrimary && $this->default->id !== $limit->transaction_currency_id;
|
||||
$amount = $limit->amount;
|
||||
$usePrimary = $this->convertToPrimary && $this->default->id !== $limit->transaction_currency_id;
|
||||
$amount = $limit->amount;
|
||||
Log::debug(sprintf('Amount is "%s".', $amount));
|
||||
if ($usePrimary && $limit->transaction_currency_id !== $this->default->id) {
|
||||
$amount = $limit->native_amount;
|
||||
Log::debug(sprintf('Amount is now "%s".', $amount));
|
||||
}
|
||||
$amount ??= '0';
|
||||
$sumSpent = bcmul((string) $entry['sum'], '-1'); // spent
|
||||
$sumSpent = bcmul((string)$entry['sum'], '-1'); // spent
|
||||
$data[0]['entries'][$title] ??= '0';
|
||||
$data[1]['entries'][$title] ??= '0';
|
||||
$data[2]['entries'][$title] ??= '0';
|
||||
|
||||
$data[0]['entries'][$title] = bcadd((string) $data[0]['entries'][$title], 1 === bccomp($sumSpent, $amount) ? $amount : $sumSpent); // spent
|
||||
$data[1]['entries'][$title] = bcadd((string) $data[1]['entries'][$title], 1 === bccomp($amount, $sumSpent) ? bcadd((string) $entry['sum'], $amount) : '0'); // left to spent
|
||||
$data[2]['entries'][$title] = bcadd((string) $data[2]['entries'][$title], 1 === bccomp($amount, $sumSpent) ? '0' : bcmul(bcadd((string) $entry['sum'], $amount), '-1')); // overspent
|
||||
$data[0]['entries'][$title] = bcadd((string)$data[0]['entries'][$title], 1 === bccomp($sumSpent, $amount) ? $amount : $sumSpent); // spent
|
||||
$data[1]['entries'][$title] = bcadd((string)$data[1]['entries'][$title], 1 === bccomp($amount, $sumSpent) ? bcadd((string)$entry['sum'], $amount) : '0'); // left to spent
|
||||
$data[2]['entries'][$title] = bcadd((string)$data[2]['entries'][$title], 1 === bccomp($amount, $sumSpent) ? '0' : bcmul(bcadd((string)$entry['sum'], $amount), '-1')); // overspent
|
||||
|
||||
Log::debug(sprintf('Amount [spent] is now %s.', $data[0]['entries'][$title]));
|
||||
Log::debug(sprintf('Amount [left] is now %s.', $data[1]['entries'][$title]));
|
||||
@@ -219,27 +242,4 @@ class FrontpageChartGenerator
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function setEnd(Carbon $end): void
|
||||
{
|
||||
$this->end = $end;
|
||||
}
|
||||
|
||||
public function setStart(Carbon $start): void
|
||||
{
|
||||
$this->start = $start;
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic setter for the user. Also updates the repositories with the right user.
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->budgetRepository->setUser($user);
|
||||
$this->blRepository->setUser($user);
|
||||
$this->opsRepository->setUser($user);
|
||||
|
||||
$locale = app('steam')->getLocale();
|
||||
$this->monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user