From 2ece754927f3fecae3133643bc38bc4ca7eed8a1 Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 13 Mar 2020 21:35:22 +0100 Subject: [PATCH] Can now store and validate auto budget --- .../Controllers/Budget/CreateController.php | 7 +- .../Controllers/Budget/EditController.php | 8 +- app/Http/Requests/BudgetFormStoreRequest.php | 116 ++++++++++++++++++ ...equest.php => BudgetFormUpdateRequest.php} | 6 +- app/Models/AutoBudget.php | 12 +- app/Models/Budget.php | 11 ++ app/Repositories/Budget/BudgetRepository.php | 17 ++- resources/lang/en_US/validation.php | 4 + 8 files changed, 168 insertions(+), 13 deletions(-) create mode 100644 app/Http/Requests/BudgetFormStoreRequest.php rename app/Http/Requests/{BudgetFormRequest.php => BudgetFormUpdateRequest.php} (94%) diff --git a/app/Http/Controllers/Budget/CreateController.php b/app/Http/Controllers/Budget/CreateController.php index 8230eb333f..81dd47e09b 100644 --- a/app/Http/Controllers/Budget/CreateController.php +++ b/app/Http/Controllers/Budget/CreateController.php @@ -26,7 +26,7 @@ namespace FireflyIII\Http\Controllers\Budget; use FireflyIII\AutoBudget; use FireflyIII\Http\Controllers\Controller; -use FireflyIII\Http\Requests\BudgetFormRequest; +use FireflyIII\Http\Requests\BudgetFormStoreRequest; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -106,13 +106,14 @@ class CreateController extends Controller /** * Stores a budget. * - * @param BudgetFormRequest $request + * @param BudgetFormStoreRequest $request * * @return \Illuminate\Http\RedirectResponse */ - public function store(BudgetFormRequest $request): RedirectResponse + public function store(BudgetFormStoreRequest $request): RedirectResponse { $data = $request->getBudgetData(); + $budget = $this->repository->store($data); $this->repository->cleanupBudgets(); $request->session()->flash('success', (string)trans('firefly.stored_new_budget', ['name' => $budget->name])); diff --git a/app/Http/Controllers/Budget/EditController.php b/app/Http/Controllers/Budget/EditController.php index f7af796cd7..91125c6e4d 100644 --- a/app/Http/Controllers/Budget/EditController.php +++ b/app/Http/Controllers/Budget/EditController.php @@ -25,7 +25,7 @@ namespace FireflyIII\Http\Controllers\Budget; use FireflyIII\Http\Controllers\Controller; -use FireflyIII\Http\Requests\BudgetFormRequest; +use FireflyIII\Http\Requests\BudgetFormUpdateRequest; use FireflyIII\Models\Budget; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use Illuminate\Http\RedirectResponse; @@ -90,12 +90,12 @@ class EditController extends Controller /** * Budget update routine. * - * @param BudgetFormRequest $request - * @param Budget $budget + * @param BudgetFormUpdateRequest $request + * @param Budget $budget * * @return \Illuminate\Http\RedirectResponse */ - public function update(BudgetFormRequest $request, Budget $budget): RedirectResponse + public function update(BudgetFormUpdateRequest $request, Budget $budget): RedirectResponse { $data = $request->getBudgetData(); $this->repository->update($budget, $data); diff --git a/app/Http/Requests/BudgetFormStoreRequest.php b/app/Http/Requests/BudgetFormStoreRequest.php new file mode 100644 index 0000000000..f7287c4ff3 --- /dev/null +++ b/app/Http/Requests/BudgetFormStoreRequest.php @@ -0,0 +1,116 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Http\Requests; + +use FireflyIII\AutoBudget; +use Illuminate\Validation\Validator; + +/** + * @codeCoverageIgnore + * Class BudgetFormStoreRequest + */ +class BudgetFormStoreRequest extends Request +{ + /** + * Verify the request. + * + * @return bool + */ + public function authorize(): bool + { + return auth()->check(); + } + + /** + * Returns the data required by the controller. + * + * @return array + */ + public function getBudgetData(): array + { + return [ + 'name' => $this->string('name'), + 'active' => $this->boolean('active'), + 'auto_budget_option' => $this->integer('auto_budget_option'), + 'transaction_currency_id' => $this->integer('transaction_currency_id'), + 'auto_budget_amount' => $this->string('auto_budget_amount'), + 'auto_budget_period' => $this->string('auto_budget_period'), + ]; + } + + /** + * Rules for this request. + * + * @return array + */ + public function rules(): array + { + return [ + 'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name', + 'active' => 'numeric|between:0,1', + 'auto_budget_option' => 'numeric|between:0,2', + 'transaction_currency_id' => 'required|exists:transaction_currencies,id', + '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->validateAmount($validator); + } + ); + } + + /** + * @param Validator $validator + */ + private function validateAmount(Validator $validator): void + { + $data = $validator->getData(); + $option = (int)$data['auto_budget_option']; + $amount = $data['auto_budget_amount'] ?? ''; + switch ($option) { + case AutoBudget::AUTO_BUDGET_RESET: + case AutoBudget::AUTO_BUDGET_ROLLOVER: + // basic float check: + if ('' === $amount) { + $validator->errors()->add('auto_budget_amount', (string)trans('validation.amount_required_for_auto_budget')); + } + if (1 !== bccomp((string)$amount, '0')) { + $validator->errors()->add('auto_budget_amount', (string)trans('validation.auto_budget_amount_positive')); + } + break; + } + } +} diff --git a/app/Http/Requests/BudgetFormRequest.php b/app/Http/Requests/BudgetFormUpdateRequest.php similarity index 94% rename from app/Http/Requests/BudgetFormRequest.php rename to app/Http/Requests/BudgetFormUpdateRequest.php index 4d0924e7c1..ed01f1ee6c 100644 --- a/app/Http/Requests/BudgetFormRequest.php +++ b/app/Http/Requests/BudgetFormUpdateRequest.php @@ -25,12 +25,10 @@ namespace FireflyIII\Http\Requests; use FireflyIII\Models\Budget; /** - * Class BudgetFormRequest. - * * @codeCoverageIgnore - * TODO AFTER 4.8,0, split for update/store + * Class BudgetFormUpdateRequest */ -class BudgetFormRequest extends Request +class BudgetFormUpdateRequest extends Request { /** * Verify the request. diff --git a/app/Models/AutoBudget.php b/app/Models/AutoBudget.php index 882b9c6ed8..fef108460d 100644 --- a/app/Models/AutoBudget.php +++ b/app/Models/AutoBudget.php @@ -21,7 +21,9 @@ namespace FireflyIII; +use FireflyIII\Models\Budget; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; /** @@ -35,5 +37,13 @@ class AutoBudget extends Model public const AUTO_BUDGET_ROLLOVER = 2; use SoftDeletes; - // + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function budget(): BelongsTo + { + return $this->belongsTo(Budget::class); + } } diff --git a/app/Models/Budget.php b/app/Models/Budget.php index 41b81292ee..298a7c7475 100644 --- a/app/Models/Budget.php +++ b/app/Models/Budget.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Models; use Carbon\Carbon; +use FireflyIII\AutoBudget; use FireflyIII\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -122,6 +123,16 @@ class Budget extends Model return $this->hasMany(BudgetLimit::class); } + + /** + * @codeCoverageIgnore + * @return HasMany + */ + public function autoBudgets(): HasMany + { + return $this->hasMany(AutoBudget::class); + } + /** * @codeCoverageIgnore * @return BelongsToMany diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index c6c90a432c..1ac9eca663 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -25,6 +25,7 @@ namespace FireflyIII\Repositories\Budget; use Carbon\Carbon; use DB; use Exception; +use FireflyIII\AutoBudget; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; @@ -282,10 +283,24 @@ class BudgetRepository implements BudgetRepositoryInterface 'name' => $data['name'], ] ); - } catch(QueryException $e) { + } catch (QueryException $e) { + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException('400002: Could not store budget.'); } + // try to create associated auto budget: + $option = $data['auto_budget_option'] ?? 0; + if (0 === $option) { + return $newBudget; + } + $autoBudget = new AutoBudget; + $autoBudget->budget()->associate($newBudget); + $autoBudget->transaction_currency_id = $data['transaction_currency_id'] ?? 1; + $autoBudget->auto_budget_type = $option; + $autoBudget->amount = $data['auto_budget_amount'] ?? '1'; + $autoBudget->period = $data['auto_budget_period'] ?? 'monthly'; + $autoBudget->save(); return $newBudget; } diff --git a/resources/lang/en_US/validation.php b/resources/lang/en_US/validation.php index f339d2502e..caaed38148 100644 --- a/resources/lang/en_US/validation.php +++ b/resources/lang/en_US/validation.php @@ -130,6 +130,7 @@ return [ 'amount_zero' => 'The total amount cannot be zero.', 'current_target_amount' => 'The current amount must be less than the target amount.', 'unique_piggy_bank_for_user' => 'The name of the piggy bank must be unique.', + 'secure_password' => 'This is not a secure password. Please try again. For more information, visit https://bit.ly/FF3-password-security', 'valid_recurrence_rep_type' => 'Invalid repetition type for recurring transactions.', 'valid_recurrence_rep_moment' => 'Invalid repetition moment for this type of repetition.', @@ -200,4 +201,7 @@ return [ 'gte.file' => 'The :attribute must be greater than or equal to :value kilobytes.', 'gte.string' => 'The :attribute must be greater than or equal to :value characters.', 'gte.array' => 'The :attribute must have :value items or more.', + + 'amount_required_for_auto_budget' => 'The amount is required.', + 'auto_budget_amount_positive' => 'The amount must be more than zero.', ];