Various optimizations in budget limit handling.

This commit is contained in:
James Cole 2023-04-30 06:45:25 +02:00
parent 0ef1d1834f
commit 46bba9d799
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
2 changed files with 44 additions and 26 deletions

View File

@ -30,6 +30,8 @@ use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use Illuminate\Support\Facades\Log;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Spatie\Period\Boundaries;
use Spatie\Period\Period;
use Spatie\Period\Precision;
@ -45,7 +47,7 @@ class BudgetLimitHandler
*/
public function created(Created $event): void
{
Log::debug(sprintf('BudgetLimitHandler::created(%s)', $event->budgetLimit->id));
Log::debug(sprintf('BudgetLimitHandler::created(#%s)', $event->budgetLimit->id));
$this->updateAvailableBudget($event->budgetLimit);
}
@ -55,7 +57,7 @@ class BudgetLimitHandler
*/
public function updated(Updated $event): void
{
Log::debug(sprintf('BudgetLimitHandler::updated(%s)', $event->budgetLimit->id));
Log::debug(sprintf('BudgetLimitHandler::updated(#%s)', $event->budgetLimit->id));
$this->updateAvailableBudget($event->budgetLimit);
}
@ -65,7 +67,9 @@ class BudgetLimitHandler
*/
public function deleted(Deleted $event): void
{
Log::debug(sprintf('BudgetLimitHandler::deleted(%s)', $event->budgetLimit->id));
Log::debug(sprintf('BudgetLimitHandler::deleted(#%s)', $event->budgetLimit->id));
$budgetLimit = $event->budgetLimit;
$budgetLimit->id = null;
$this->updateAvailableBudget($event->budgetLimit);
}
@ -124,6 +128,11 @@ class BudgetLimitHandler
}
}
}
if (0 === bccomp('0', $newAmount)) {
Log::debug('New amount is zero, deleting AB.');
$availableBudget->delete();
return;
}
Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount));
$availableBudget->amount = $newAmount;
$availableBudget->save();
@ -135,6 +144,9 @@ class BudgetLimitHandler
*/
private function getDailyAmount(BudgetLimit $budgetLimit): string
{
if(0 === (int)$budgetLimit->id) {
return '0';
}
$limitPeriod = Period::make(
$budgetLimit->start_date,
$budgetLimit->end_date,
@ -152,9 +164,6 @@ class BudgetLimitHandler
/**
* @param BudgetLimit $budgetLimit
* @return void
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
private function updateAvailableBudget(BudgetLimit $budgetLimit): void
{
@ -163,11 +172,15 @@ class BudgetLimitHandler
// based on the view range of the user (month week quarter etc) the budget limit could
// either overlap multiple available budget periods or be contained in a single one.
// all have to be created or updated.
$viewRange = app('preferences')->get('viewRange', '1M')->data;
$start = app('navigation')->startOfPeriod($budgetLimit->start_date, $viewRange);
$end = app('navigation')->startOfPeriod($budgetLimit->end_date, $viewRange);
$end = app('navigation')->endOfPeriod($end, $viewRange);
$user = $budgetLimit->budget->user;
try {
$viewRange = app('preferences')->get('viewRange', '1M')->data;
} catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
$viewRange = '1M';
}
$start = app('navigation')->startOfPeriod($budgetLimit->start_date, $viewRange);
$end = app('navigation')->startOfPeriod($budgetLimit->end_date, $viewRange);
$end = app('navigation')->endOfPeriod($end, $viewRange);
$user = $budgetLimit->budget->user;
// limit period in total is:
$limitPeriod = Period::make($start, $end, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
@ -195,19 +208,24 @@ class BudgetLimitHandler
// no need to calculate if period is equal.
if ($currentPeriod->equals($limitPeriod)) {
$amount = $budgetLimit->amount;
$amount = 0 === (int)$budgetLimit->id ? '0' : $budgetLimit->amount;
}
if(0 === bccomp($amount,'0')) {
Log::debug('Amount is zero, will not create AB.');
}
if(0 !== bccomp($amount,'0')) {
Log::debug(sprintf('Will create AB for period %s to %s', $current->format('Y-m-d'), $currentEnd->format('Y-m-d')));
$availableBudget = new AvailableBudget(
[
'user_id' => $budgetLimit->budget->user->id,
'transaction_currency_id' => $budgetLimit->transaction_currency_id,
'start_date' => $current,
'end_date' => $currentEnd,
'amount' => $amount,
]
);
$availableBudget->save();
}
Log::debug(sprintf('Will create AB for period %s to %s', $current->format('Y-m-d'), $currentEnd->format('Y-m-d')));
$availableBudget = new AvailableBudget(
[
'user_id' => $budgetLimit->budget->user->id,
'transaction_currency_id' => $budgetLimit->transaction_currency_id,
'start_date' => $current,
'end_date' => $currentEnd,
'amount' => $amount,
]
);
$availableBudget->save();
}
// prep for next loop

View File

@ -298,7 +298,7 @@ class OperationsRepository implements OperationsRepositoryInterface
?Collection $budgets = null,
?TransactionCurrency $currency = null
): array {
Log::debug(sprintf('Now in %s', __METHOD__));
//Log::debug(sprintf('Now in %s', __METHOD__));
$start->startOfDay();
$end->endOfDay();
@ -340,7 +340,7 @@ class OperationsRepository implements OperationsRepositoryInterface
// same but for foreign currencies:
if (null !== $currency) {
Log::debug(sprintf('Currency is "%s".', $currency->name));
//Log::debug(sprintf('Currency is "%s".', $currency->name));
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])
@ -350,7 +350,7 @@ class OperationsRepository implements OperationsRepositoryInterface
$collector->setAccounts($accounts);
}
$result = $collector->getExtractedJournals();
Log::debug(sprintf('Found %d journals with currency %s.', count($result), $currency->code));
//Log::debug(sprintf('Found %d journals with currency %s.', count($result), $currency->code));
// do not use array_merge because you want keys to overwrite (otherwise you get double results):
$journals = $result + $journals;
}