Convert more charts.

This commit is contained in:
James Cole
2024-12-24 10:29:07 +01:00
parent e8ef630424
commit 7e2e49e129
15 changed files with 454 additions and 303 deletions

View File

@@ -26,11 +26,13 @@ namespace FireflyIII\Support\Chart\Budget;
use Carbon\Carbon;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Class FrontpageChartGenerator
@@ -43,6 +45,9 @@ class FrontpageChartGenerator
private Carbon $end;
private string $monthAndDayFormat;
private Carbon $start;
public bool $convertToNative = false;
public TransactionCurrency $default;
/**
* FrontpageChartGenerator constructor.
@@ -62,6 +67,7 @@ class FrontpageChartGenerator
*/
public function generate(): array
{
Log::debug('Now in generate for budget chart.');
$budgets = $this->budgetRepository->getActiveBudgets();
$data = [
['label' => (string) trans('firefly.spent_in_budget'), 'entries' => [], 'type' => 'bar'],
@@ -74,6 +80,7 @@ class FrontpageChartGenerator
foreach ($budgets as $budget) {
$data = $this->processBudget($data, $budget);
}
Log::debug('DONE with generate budget chart.');
return $data;
}
@@ -85,15 +92,19 @@ class FrontpageChartGenerator
*/
private function processBudget(array $data, Budget $budget): array
{
Log::debug(sprintf('Now processing budget #%d ("%s")', $budget->id, $budget->name));
// get all limits:
$limits = $this->blRepository->getBudgetLimits($budget, $this->start, $this->end);
Log::debug(sprintf('Found %d limit(s) for budget #%d.', $limits->count(), $budget->id));
// if no limits
if (0 === $limits->count()) {
return $this->noBudgetLimits($data, $budget);
$result = $this->noBudgetLimits($data, $budget);
Log::debug(sprintf('Now DONE processing budget #%d ("%s")', $budget->id, $budget->name));
return $result;
}
return $this->budgetLimits($data, $budget, $limits);
$result = $this->budgetLimits($data, $budget, $limits);
Log::debug(sprintf('Now DONE processing budget #%d ("%s")', $budget->id, $budget->name));
return $result;
}
/**
@@ -120,10 +131,12 @@ class FrontpageChartGenerator
*/
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;
}
@@ -134,12 +147,24 @@ class FrontpageChartGenerator
*/
private function processLimit(array $data, Budget $budget, BudgetLimit $limit): array
{
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $limit->transactionCurrency);
$useNative = $this->convertToNative && $this->default->id !== $limit->transaction_currency_id;
$currency = $limit->transactionCurrency;
if ($useNative) {
Log::debug(sprintf('Processing limit #%d with %s %s', $limit->id, $this->default->code, $limit->native_amount));
$currency = null;
}
if (!$useNative) {
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([$budget]), $currency);
Log::debug(sprintf('Spent array has %d entries.', count($spent)));
/** @var array $entry */
foreach ($spent as $entry) {
// only spent the entry where the entry's currency matches the budget limit's currency
if ($entry['currency_id'] === $limit->transaction_currency_id) {
// or when useNative is true.
if ($entry['currency_id'] === $limit->transaction_currency_id || $useNative) {
Log::debug(sprintf('Process spent row (%s)', $entry['currency_code']));
$data = $this->processRow($data, $budget, $limit, $entry);
}
}
@@ -155,7 +180,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']);
if ($limit->start_date->startOfDay()->ne($this->start->startOfDay()) || $limit->end_date->startOfDay()->ne($this->end->startOfDay())) {
$title = sprintf(
'%s (%s) (%s - %s)',
@@ -165,11 +190,15 @@ class FrontpageChartGenerator
$limit->end_date->isoFormat($this->monthAndDayFormat)
);
}
$sumSpent = bcmul($entry['sum'], '-1'); // spent
$sumSpent = bcmul($entry['sum'], '-1'); // spent
$data[0]['entries'][$title] ??= '0';
$data[1]['entries'][$title] ??= '0';
$data[2]['entries'][$title] ??= '0';
$data[0]['entries'][$title] = 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent; // spent
$data[1]['entries'][$title] = 1 === bccomp($limit->amount, $sumSpent) ? bcadd($entry['sum'], $limit->amount) : '0'; // left to spent
$data[2]['entries'][$title] = 1 === bccomp($limit->amount, $sumSpent) ? '0' : bcmul(bcadd($entry['sum'], $limit->amount), '-1'); // overspent
$data[0]['entries'][$title] = bcadd($data[0]['entries'][$title], 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent); // spent
$data[1]['entries'][$title] = bcadd($data[1]['entries'][$title],1 === bccomp($limit->amount, $sumSpent) ? bcadd($entry['sum'], $limit->amount) : '0'); // left to spent
$data[2]['entries'][$title] = bcadd($data[2]['entries'][$title],1 === bccomp($limit->amount, $sumSpent) ? '0' : bcmul(bcadd($entry['sum'], $limit->amount), '-1')); // overspent
return $data;
}