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
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\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Spatie\Period\Boundaries; use Spatie\Period\Boundaries;
use Spatie\Period\Period; use Spatie\Period\Period;
use Spatie\Period\Precision; use Spatie\Period\Precision;
@@ -45,7 +47,7 @@ class BudgetLimitHandler
*/ */
public function created(Created $event): void 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); $this->updateAvailableBudget($event->budgetLimit);
} }
@@ -55,7 +57,7 @@ class BudgetLimitHandler
*/ */
public function updated(Updated $event): void 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); $this->updateAvailableBudget($event->budgetLimit);
} }
@@ -65,7 +67,9 @@ class BudgetLimitHandler
*/ */
public function deleted(Deleted $event): void 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); $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)); Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount));
$availableBudget->amount = $newAmount; $availableBudget->amount = $newAmount;
$availableBudget->save(); $availableBudget->save();
@@ -135,6 +144,9 @@ class BudgetLimitHandler
*/ */
private function getDailyAmount(BudgetLimit $budgetLimit): string private function getDailyAmount(BudgetLimit $budgetLimit): string
{ {
if(0 === (int)$budgetLimit->id) {
return '0';
}
$limitPeriod = Period::make( $limitPeriod = Period::make(
$budgetLimit->start_date, $budgetLimit->start_date,
$budgetLimit->end_date, $budgetLimit->end_date,
@@ -152,9 +164,6 @@ class BudgetLimitHandler
/** /**
* @param BudgetLimit $budgetLimit * @param BudgetLimit $budgetLimit
* @return void * @return void
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/ */
private function updateAvailableBudget(BudgetLimit $budgetLimit): void 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 // 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. // either overlap multiple available budget periods or be contained in a single one.
// all have to be created or updated. // all have to be created or updated.
$viewRange = app('preferences')->get('viewRange', '1M')->data; try {
$start = app('navigation')->startOfPeriod($budgetLimit->start_date, $viewRange); $viewRange = app('preferences')->get('viewRange', '1M')->data;
$end = app('navigation')->startOfPeriod($budgetLimit->end_date, $viewRange); } catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
$end = app('navigation')->endOfPeriod($end, $viewRange); $viewRange = '1M';
$user = $budgetLimit->budget->user; }
$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: // limit period in total is:
$limitPeriod = Period::make($start, $end, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); $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. // no need to calculate if period is equal.
if ($currentPeriod->equals($limitPeriod)) { 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 // prep for next loop

View File

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