From 9075fa8ac8690763ce5fabce362567986c47d235 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 14 Sep 2025 09:21:32 +0200 Subject: [PATCH] Allow webhooks to be send for budget limit update. --- .../Models/BudgetLimit/UpdateController.php | 1 + .../Models/BudgetLimit/UpdateRequest.php | 7 + app/Handlers/Observer/BudgetLimitObserver.php | 25 ++-- .../Budget/BudgetLimitRepository.php | 124 +++++++++--------- .../Budget/BudgetLimitRepositoryInterface.php | 2 +- 5 files changed, 88 insertions(+), 71 deletions(-) diff --git a/app/Api/V1/Controllers/Models/BudgetLimit/UpdateController.php b/app/Api/V1/Controllers/Models/BudgetLimit/UpdateController.php index cd17067b5c..cca3953140 100644 --- a/app/Api/V1/Controllers/Models/BudgetLimit/UpdateController.php +++ b/app/Api/V1/Controllers/Models/BudgetLimit/UpdateController.php @@ -77,6 +77,7 @@ class UpdateController extends Controller throw new FireflyException('20028: The budget limit does not belong to the budget.'); } $data = $request->getAll(); + $data['fire_webhooks'] = $data['fire_webhooks'] ?? true; $data['budget_id'] = $budget->id; $budgetLimit = $this->blRepository->update($budgetLimit, $data); $manager = $this->getManager(); diff --git a/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php b/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php index 42f7849292..4f877b4865 100644 --- a/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\BudgetLimit; +use FireflyIII\Rules\IsBoolean; use Illuminate\Validation\Validator; use Carbon\Carbon; use FireflyIII\Rules\IsValidPositiveAmount; @@ -52,6 +53,9 @@ class UpdateRequest extends FormRequest 'currency_id' => ['currency_id', 'convertInteger'], 'currency_code' => ['currency_code', 'convertString'], 'notes' => ['notes', 'stringWithNewlines'], + + // webhooks + 'fire_webhooks' => ['fire_webhooks','boolean'] ]; if (false === $this->has('notes')) { // ignore notes, not submitted. @@ -73,6 +77,9 @@ class UpdateRequest extends FormRequest 'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_code' => 'min:3|max:51|exists:transaction_currencies,code', 'notes' => 'nullable|min:0|max:32768', + + // webhooks + 'fire_webhooks' => [new IsBoolean()], ]; } diff --git a/app/Handlers/Observer/BudgetLimitObserver.php b/app/Handlers/Observer/BudgetLimitObserver.php index c29b30dbde..4fb16a06fa 100644 --- a/app/Handlers/Observer/BudgetLimitObserver.php +++ b/app/Handlers/Observer/BudgetLimitObserver.php @@ -75,7 +75,7 @@ class BudgetLimitObserver $userCurrency = app('amount')->getPrimaryCurrencyByUserGroup($budgetLimit->budget->user->userGroup); $budgetLimit->native_amount = null; if ($budgetLimit->transactionCurrency->id !== $userCurrency->id) { - $converter = new ExchangeRateConverter(); + $converter = new ExchangeRateConverter(); $converter->setUserGroup($budgetLimit->budget->user->userGroup); $converter->setIgnoreSettings(true); $budgetLimit->native_amount = $converter->convert($budgetLimit->transactionCurrency, $userCurrency, today(), $budgetLimit->amount); @@ -90,16 +90,21 @@ class BudgetLimitObserver $this->updatePrimaryCurrencyAmount($budgetLimit); $this->updateAvailableBudget($budgetLimit); - $user = $budgetLimit->budget->user; + // this is a lame trick to communicate with the observer. + $singleton = PreferencesSingleton::getInstance(); - /** @var MessageGeneratorInterface $engine */ - $engine = app(MessageGeneratorInterface::class); - $engine->setUser($user); - $engine->setObjects(new Collection()->push($budgetLimit)); - $engine->setTrigger(WebhookTrigger::STORE_UPDATE_BUDGET_LIMIT); - $engine->generateMessages(); + if (true === $singleton->getPreference('fire_webhooks_bl_update')) { + $user = $budgetLimit->budget->user; - Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__)); - event(new RequestedSendWebhookMessages()); + /** @var MessageGeneratorInterface $engine */ + $engine = app(MessageGeneratorInterface::class); + $engine->setUser($user); + $engine->setObjects(new Collection()->push($budgetLimit)); + $engine->setTrigger(WebhookTrigger::STORE_UPDATE_BUDGET_LIMIT); + $engine->generateMessages(); + + Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__)); + event(new RequestedSendWebhookMessages()); + } } } diff --git a/app/Repositories/Budget/BudgetLimitRepository.php b/app/Repositories/Budget/BudgetLimitRepository.php index 67378a92d4..857052b081 100644 --- a/app/Repositories/Budget/BudgetLimitRepository.php +++ b/app/Repositories/Budget/BudgetLimitRepository.php @@ -375,11 +375,15 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup } // catch unexpected null: if (null === $currency) { - $currency = $budgetLimit->transactionCurrency ?? app('amount')->getPrimaryCurrencyByUserGroup($this->user->userGroup); + $currency = $budgetLimit->transactionCurrency ?? Amount::getPrimaryCurrencyByUserGroup($this->user->userGroup); } $currency->enabled = true; $currency->save(); + // this is a lame trick to communicate with the observer. + $singleton = PreferencesSingleton::getInstance(); + $singleton->setPreference('fire_webhooks_bl_update', $data['fire_webhooks'] ?? true); + $budgetLimit->transaction_currency_id = $currency->id; $budgetLimit->save(); @@ -391,63 +395,63 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup return $budgetLimit; } - public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit - { - // count the limits: - $limits = $budget->budgetlimits() - ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00')) - ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00')) - ->count('budget_limits.*') - ; - Log::debug(sprintf('Found %d budget limits.', $limits)); - - // there might be a budget limit for these dates: - /** @var null|BudgetLimit $limit */ - $limit = $budget->budgetlimits() - ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00')) - ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00')) - ->first(['budget_limits.*']) - ; - - // if more than 1 limit found, delete the others: - if ($limits > 1 && null !== $limit) { - Log::debug(sprintf('Found more than 1, delete all except #%d', $limit->id)); - $budget->budgetlimits() - ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00')) - ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00')) - ->where('budget_limits.id', '!=', $limit->id)->delete() - ; - } - - // delete if amount is zero. - // Returns 0 if the two operands are equal, - // 1 if the left_operand is larger than the right_operand, -1 otherwise. - if (null !== $limit && bccomp($amount, '0') <= 0) { - Log::debug(sprintf('%s is zero, delete budget limit #%d', $amount, $limit->id)); - $limit->delete(); - - return null; - } - // update if exists: - if (null !== $limit) { - Log::debug(sprintf('Existing budget limit is #%d, update this to amount %s', $limit->id, $amount)); - $limit->amount = $amount; - $limit->save(); - - return $limit; - } - Log::debug('No existing budget limit, create a new one'); - // or create one and return it. - $limit = new BudgetLimit(); - $limit->budget()->associate($budget); - $limit->start_date = $start->startOfDay(); - $limit->start_date_tz = $start->format('e'); - $limit->end_date = $end->startOfDay(); - $limit->end_date_tz = $end->format('e'); - $limit->amount = $amount; - $limit->save(); - Log::debug(sprintf('Created new budget limit with ID #%d and amount %s', $limit->id, $amount)); - - return $limit; - } +// public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit +// { +// // count the limits: +// $limits = $budget->budgetlimits() +// ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00')) +// ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00')) +// ->count('budget_limits.*') +// ; +// Log::debug(sprintf('Found %d budget limits.', $limits)); +// +// // there might be a budget limit for these dates: +// /** @var null|BudgetLimit $limit */ +// $limit = $budget->budgetlimits() +// ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00')) +// ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00')) +// ->first(['budget_limits.*']) +// ; +// +// // if more than 1 limit found, delete the others: +// if ($limits > 1 && null !== $limit) { +// Log::debug(sprintf('Found more than 1, delete all except #%d', $limit->id)); +// $budget->budgetlimits() +// ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00')) +// ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00')) +// ->where('budget_limits.id', '!=', $limit->id)->delete() +// ; +// } +// +// // delete if amount is zero. +// // Returns 0 if the two operands are equal, +// // 1 if the left_operand is larger than the right_operand, -1 otherwise. +// if (null !== $limit && bccomp($amount, '0') <= 0) { +// Log::debug(sprintf('%s is zero, delete budget limit #%d', $amount, $limit->id)); +// $limit->delete(); +// +// return null; +// } +// // update if exists: +// if (null !== $limit) { +// Log::debug(sprintf('Existing budget limit is #%d, update this to amount %s', $limit->id, $amount)); +// $limit->amount = $amount; +// $limit->save(); +// +// return $limit; +// } +// Log::debug('No existing budget limit, create a new one'); +// // or create one and return it. +// $limit = new BudgetLimit(); +// $limit->budget()->associate($budget); +// $limit->start_date = $start->startOfDay(); +// $limit->start_date_tz = $start->format('e'); +// $limit->end_date = $end->startOfDay(); +// $limit->end_date_tz = $end->format('e'); +// $limit->amount = $amount; +// $limit->save(); +// Log::debug(sprintf('Created new budget limit with ID #%d and amount %s', $limit->id, $amount)); +// +// return $limit; +// } } diff --git a/app/Repositories/Budget/BudgetLimitRepositoryInterface.php b/app/Repositories/Budget/BudgetLimitRepositoryInterface.php index c56093ef61..7d8ccde5bb 100644 --- a/app/Repositories/Budget/BudgetLimitRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetLimitRepositoryInterface.php @@ -81,5 +81,5 @@ interface BudgetLimitRepositoryInterface public function update(BudgetLimit $budgetLimit, array $data): BudgetLimit; - public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit; + //public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit; }