diff --git a/app/Api/V1/Requests/BudgetStoreRequest.php b/app/Api/V1/Requests/BudgetStoreRequest.php index 5c3f530f0e..21799684ac 100644 --- a/app/Api/V1/Requests/BudgetStoreRequest.php +++ b/app/Api/V1/Requests/BudgetStoreRequest.php @@ -78,7 +78,7 @@ class BudgetStoreRequest extends Request return [ 'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name', 'active' => [new IsBoolean], - 'auto_budget_type' => 'in:reset,rollover', + 'auto_budget_type' => 'in:reset,rollover,none', 'auto_budget_currency_id' => 'exists:transaction_currencies,id', 'auto_budget_currency_code' => 'exists:transaction_currencies,code', 'auto_budget_amount' => 'min:0|max:1000000000', diff --git a/app/Api/V1/Requests/BudgetUpdateRequest.php b/app/Api/V1/Requests/BudgetUpdateRequest.php index 738c5ff35a..0861c5be25 100644 --- a/app/Api/V1/Requests/BudgetUpdateRequest.php +++ b/app/Api/V1/Requests/BudgetUpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests; use FireflyIII\Rules\IsBoolean; +use Illuminate\Validation\Validator; /** * Class BudgetUpdateRequest @@ -56,9 +57,14 @@ class BudgetUpdateRequest extends Request } return [ - 'name' => $this->string('name'), - 'active' => $active, - 'order' => 0, + 'name' => $this->string('name'), + 'active' => $active, + 'order' => 0, + 'auto_budget_type' => $this->string('auto_budget_type'), + 'transaction_currency_id' => $this->integer('auto_budget_currency_id'), + 'transaction_currency_code' => $this->string('auto_budget_currency_code'), + 'auto_budget_amount' => $this->string('auto_budget_amount'), + 'auto_budget_period' => $this->string('auto_budget_period'), ]; } @@ -72,8 +78,30 @@ class BudgetUpdateRequest extends Request $budget = $this->route()->parameter('budget'); return [ - 'name' => sprintf('required|between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id), - 'active' => [new IsBoolean], + 'name' => sprintf('required|between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id), + 'active' => [new IsBoolean], + 'auto_budget_type' => 'in:reset,rollover,none', + 'auto_budget_currency_id' => 'exists:transaction_currencies,id', + 'auto_budget_currency_code' => 'exists:transaction_currencies,code', + 'auto_budget_amount' => 'min:0|max:1000000000', + 'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly', ]; } + + /** + * Configure the validator instance with special rules for after the basic validation rules. + * + * @param Validator $validator + * + * @return void + */ + public function withValidator(Validator $validator): void + { + $validator->after( + function (Validator $validator) { + // validate all account info + $this->validateAutoBudgetAmount($validator); + } + ); + } } diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index b83d0da209..6820074bfd 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -305,7 +305,6 @@ class BudgetRepository implements BudgetRepositoryInterface $currencyId = (int)($data['transaction_currency_id'] ?? 0); $currencyCode = (string)($data['transaction_currency_code'] ?? ''); - $currency = $repos->findNull($currencyId); if(null === $currency) { $currency = $repos->findByCodeNull($currencyCode); @@ -339,20 +338,48 @@ class BudgetRepository implements BudgetRepositoryInterface $budget->save(); // update or create auto-budget: - $autoBudgetType = $data['auto_budget_option'] ?? 0; + $autoBudgetType = $data['auto_budget_type'] ?? 0; + if ('reset' === $autoBudgetType) { + $autoBudgetType = AutoBudget::AUTO_BUDGET_RESET; + } + if ('rollover' === $autoBudgetType) { + $autoBudgetType = AutoBudget::AUTO_BUDGET_ROLLOVER; + } + if ('none' === $autoBudgetType) { + $autoBudgetType = 0; + } + if (0 !== $autoBudgetType) { $autoBudget = $this->getAutoBudget($budget); if (null === $autoBudget) { $autoBudget = new AutoBudget; $autoBudget->budget()->associate($budget); } - $autoBudget->transaction_currency_id = $data['transaction_currency_id'] ?? 1; + + $repos = app(CurrencyRepositoryInterface::class); + $currencyId = (int)($data['transaction_currency_id'] ?? 0); + $currencyCode = (string)($data['transaction_currency_code'] ?? ''); + + $currency = $repos->findNull($currencyId); + if(null === $currency) { + $currency = $repos->findByCodeNull($currencyCode); + } + if(null === $currency) { + $currency = app('amount')->getDefaultCurrencyByUser($this->user); + } + + $autoBudget->transaction_currency_id = $currency->id; $autoBudget->auto_budget_type = $autoBudgetType; $autoBudget->amount = $data['auto_budget_amount'] ?? '0'; $autoBudget->period = $data['auto_budget_period'] ?? 'monthly'; $autoBudget->save(); } - + if (0 === $autoBudgetType) { + $autoBudget = $this->getAutoBudget($budget); + if (null !== $autoBudget) { + $this->destroyAutoBudget($budget); + } + } $this->updateRuleTriggers($oldName, $data['name']); $this->updateRuleActions($oldName, $data['name']); app('preferences')->mark(); @@ -425,4 +452,15 @@ class BudgetRepository implements BudgetRepositoryInterface { return $budget->autoBudgets()->first(); } + + /** + * @inheritDoc + */ + public function destroyAutoBudget(Budget $budget): void + { + /** @var AutoBudget $autoBudget */ + foreach ($budget->autoBudgets()->get() as $autoBudget) { + $autoBudget->delete(); + } + } } diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index a58d29a96f..c7e008f96f 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -46,6 +46,11 @@ interface BudgetRepositoryInterface */ public function getAutoBudget(Budget $budget): ?AutoBudget; + /** + * @param Budget $budget + */ + public function destroyAutoBudget(Budget $budget): void; + /** * @return bool