diff --git a/app/Factory/PiggyBankFactory.php b/app/Factory/PiggyBankFactory.php index cd41ee1deb..84dbab3853 100644 --- a/app/Factory/PiggyBankFactory.php +++ b/app/Factory/PiggyBankFactory.php @@ -28,6 +28,7 @@ use FireflyIII\Models\PiggyBank; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\User; use Illuminate\Database\QueryException; @@ -37,6 +38,7 @@ use Illuminate\Database\QueryException; */ class PiggyBankFactory { + use CreatesObjectGroups; public User $user { set(User $value) { $this->user = $value; diff --git a/app/Http/Controllers/PiggyBank/CreateController.php b/app/Http/Controllers/PiggyBank/CreateController.php index a0626b5c3b..d3af975cc2 100644 --- a/app/Http/Controllers/PiggyBank/CreateController.php +++ b/app/Http/Controllers/PiggyBank/CreateController.php @@ -31,6 +31,7 @@ use FireflyIII\Http\Requests\PiggyBankStoreRequest; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; +use Illuminate\Http\Request; use Illuminate\Routing\Redirector; use Illuminate\Support\Facades\Log; use Illuminate\View\View; @@ -52,7 +53,7 @@ class CreateController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string)trans('firefly.piggyBanks')); + app('view')->share('title', (string) trans('firefly.piggyBanks')); app('view')->share('mainTitleIcon', 'fa-bullseye'); $this->attachments = app(AttachmentHelperInterface::class); @@ -68,10 +69,12 @@ class CreateController extends Controller * * @return Factory|View */ - public function create() + public function create(Request $request) { - $subTitle = (string)trans('firefly.new_piggy_bank'); + $subTitle = (string) trans('firefly.new_piggy_bank'); $subTitleIcon = 'fa-plus'; + $hasOldInput = null !== $request->old('_token'); + $preFilled = $request->old(); // put previous url in session if not redirect from store (not "create another"). if (true !== session('piggy-banks.create.fromStore')) { @@ -79,7 +82,7 @@ class CreateController extends Controller } session()->forget('piggy-banks.create.fromStore'); - return view('piggy-banks.create', compact('subTitle', 'subTitleIcon')); + return view('piggy-banks.create', compact('subTitle', 'subTitleIcon', 'preFilled')); } /** @@ -91,33 +94,34 @@ class CreateController extends Controller */ public function store(PiggyBankStoreRequest $request) { - $data = $request->getPiggyBankData(); + $data = $request->getPiggyBankData(); + if (null === $data['start_date']) { $data['start_date'] = today(config('app.timezone')); } $piggyBank = $this->piggyRepos->store($data); - var_dump($data);exit; - session()->flash('success', (string)trans('firefly.stored_piggy_bank', ['name' => $piggyBank->name])); + session()->flash('success', (string) trans('firefly.stored_piggy_bank', ['name' => $piggyBank->name])); + session()->flash('success_url', route('piggy-banks.show', [$piggyBank->id])); app('preferences')->mark(); // store attachment(s): /** @var null|array $files */ - $files = $request->hasFile('attachments') ? $request->file('attachments') : null; + $files = $request->hasFile('attachments') ? $request->file('attachments') : null; if (null !== $files && !auth()->user()->hasRole('demo')) { $this->attachments->saveAttachmentsForModel($piggyBank, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { Log::channel('audit')->warning(sprintf('The demo user is trying to upload attachments in %s.', __METHOD__)); - session()->flash('info', (string)trans('firefly.no_att_demo_user')); + session()->flash('info', (string) trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); } - $redirect = redirect($this->getPreviousUrl('piggy-banks.create.url')); + $redirect = redirect($this->getPreviousUrl('piggy-banks.create.url')); - if (1 === (int)$request->get('create_another')) { + if (1 === (int) $request->get('create_another')) { session()->put('piggy-banks.create.fromStore', true); $redirect = redirect(route('piggy-banks.create'))->withInput(); diff --git a/app/Http/Requests/PiggyBankStoreRequest.php b/app/Http/Requests/PiggyBankStoreRequest.php index 467cfe607e..bc796e74a1 100644 --- a/app/Http/Requests/PiggyBankStoreRequest.php +++ b/app/Http/Requests/PiggyBankStoreRequest.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; @@ -43,18 +45,21 @@ class PiggyBankStoreRequest extends FormRequest */ public function getPiggyBankData(): array { - $data = [ - 'name' => $this->convertString('name'), - 'start_date' => $this->getCarbonDate('start_date'), - //'account_id' => $this->convertInteger('account_id'), - 'accounts' => $this->get('accounts'), - 'target_amount' => $this->convertString('target_amount'), - 'target_date' => $this->getCarbonDate('target_date'), - 'notes' => $this->stringWithNewlines('notes'), - 'object_group_title' => $this->convertString('object_group'), + $accounts = $this->get('accounts'); + $data = [ + 'name' => $this->convertString('name'), + 'start_date' => $this->getCarbonDate('start_date'), + 'target_amount' => $this->convertString('target_amount'), + 'transaction_currency_id' => $this->convertInteger('transaction_currency_id'), + 'target_date' => $this->getCarbonDate('target_date'), + 'notes' => $this->stringWithNewlines('notes'), + 'object_group_title' => $this->convertString('object_group'), ]; - if(!is_array($data['accounts'])) { - $data['accounts'] = []; + if (!is_array($accounts)) { + $accounts = []; + } + foreach ($accounts as $item) { + $data['accounts'][] = ['account_id' => (int) ($item)]; } return $data; @@ -66,15 +71,15 @@ class PiggyBankStoreRequest extends FormRequest public function rules(): array { return [ - 'name' => 'required|min:1|max:255|uniquePiggyBankForUser', - 'accounts' => 'required|array', - 'accounts.*' => 'required|belongsToUser:accounts', + 'name' => 'required|min:1|max:255|uniquePiggyBankForUser', + 'accounts' => 'required|array', + 'accounts.*' => 'required|belongsToUser:accounts', 'target_amount' => ['nullable', new IsValidPositiveAmount()], 'start_date' => 'date', 'target_date' => 'date|nullable', - 'order' => 'integer|min:1', - 'object_group' => 'min:0|max:255', - 'notes' => 'min:1|max:32768|nullable', + 'order' => 'integer|min:1', + 'object_group' => 'min:0|max:255', + 'notes' => 'min:1|max:32768|nullable', ]; } @@ -82,10 +87,46 @@ class PiggyBankStoreRequest extends FormRequest { // need to have more than one account. // accounts need to have the same currency or be multi-currency(?). - + $validator->after( + function (Validator $validator): void { + // validate start before end only if both are there. + $data = $validator->getData(); + $currency = $this->getCurrencyFromData($data); + if (array_key_exists('accounts', $data) && is_array($data['accounts'])) { + $repository = app(AccountRepositoryInterface::class); + $types = config('firefly.piggy_bank_account_types'); + foreach ($data['accounts'] as $value) { + $accountId = (int) $value; + $account = $repository->find($accountId); + if (null !== $account) { + // check currency here. + $accountCurrency = $repository->getAccountCurrency($account); + $isMultiCurrency = $repository->getMetaValue($account, 'is_multi_currency'); + if ($accountCurrency->id !== $currency->id && 'true' !== $isMultiCurrency) { + $validator->errors()->add('accounts', trans('validation.invalid_account_currency')); + } + $type = $account->accountType->type; + if (!in_array($type, $types, true)) { + $validator->errors()->add('accounts', trans('validation.invalid_account_type')); + } + } + } + } + } + ); if ($validator->fails()) { Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); } } + + private function getCurrencyFromData(array $data): TransactionCurrency + { + $currencyId = (int) ($data['transaction_currency_id'] ?? 0); + $currency = TransactionCurrency::find($currencyId); + if (null === $currency) { + return app('amount')->getDefaultCurrency(); + } + return $currency; + } } diff --git a/app/Support/Form/AccountForm.php b/app/Support/Form/AccountForm.php index 8034bf93e6..63f4bb4130 100644 --- a/app/Support/Form/AccountForm.php +++ b/app/Support/Form/AccountForm.php @@ -157,7 +157,6 @@ class AccountForm { $types = [AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value,AccountTypeEnum::LOAN->value]; $grouped = $this->getAccountsGrouped($types); - return $this->multiSelect($name, $grouped, $value, $options); } diff --git a/app/Support/Form/FormSupport.php b/app/Support/Form/FormSupport.php index 09c8de4910..4ba51bb046 100644 --- a/app/Support/Form/FormSupport.php +++ b/app/Support/Form/FormSupport.php @@ -63,6 +63,7 @@ trait FormSupport $options = $this->expandOptionArray($name, $label, $options); $classes = $this->getHolderClasses($name); $selected = $this->fillFieldValue($name, $selected); + unset($options['autocomplete'], $options['placeholder']); try { diff --git a/resources/views/piggy-banks/create.twig b/resources/views/piggy-banks/create.twig index 84662207a4..ad944792fa 100644 --- a/resources/views/piggy-banks/create.twig +++ b/resources/views/piggy-banks/create.twig @@ -16,9 +16,9 @@