diff --git a/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php b/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php index 25e274634b..c8c47953c1 100644 --- a/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php @@ -292,6 +292,10 @@ class UpdateRequest extends FormRequest 'transactions.*.date' => [new IsDateOrTime], 'transactions.*.order' => 'numeric|min:0', + // group id: + 'transactions.*.transaction_journal_id' => ['numeric','exists:transaction_journals,id', new BelongsUser], + + // currency info 'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id', 'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code', @@ -375,6 +379,9 @@ class UpdateRequest extends FormRequest // validate source/destination is equal, depending on the transaction journal type. $this->validateEqualAccountsForUpdate($validator, $transactionGroup); + // a catch when users submit splits with no source or destination info at all. + $this->preventNoAccountInfo($validator,); + // validate that the currency fits the source and/or destination account. // validate all account info $this->validateAccountInformationUpdate($validator, $transactionGroup); diff --git a/app/Handlers/Events/UpdatedGroupEventHandler.php b/app/Handlers/Events/UpdatedGroupEventHandler.php index 280065b0e9..0fb4958dcf 100644 --- a/app/Handlers/Events/UpdatedGroupEventHandler.php +++ b/app/Handlers/Events/UpdatedGroupEventHandler.php @@ -131,6 +131,12 @@ class UpdatedGroupEventHandler ->orderBy('transaction_journals.id', 'DESC') ->orderBy('transaction_journals.description', 'DESC') ->first(); + + if(null === $first) { + Log::warning(sprintf('Group #%d has no transaction journals.', $group->id)); + return; + } + $all = $group->transactionJournals()->get()->pluck('id')->toArray(); /** @var Account $sourceAccount */ $sourceAccount = $first->transactions()->where('amount', '<', '0')->first()->account; diff --git a/app/Rules/BelongsUser.php b/app/Rules/BelongsUser.php index f740aab087..027b6b8dbe 100644 --- a/app/Rules/BelongsUser.php +++ b/app/Rules/BelongsUser.php @@ -30,6 +30,7 @@ use FireflyIII\Models\Bill; use FireflyIII\Models\Budget; use FireflyIII\Models\Category; use FireflyIII\Models\PiggyBank; +use FireflyIII\Models\TransactionJournal; use Illuminate\Contracts\Validation\Rule; use Log; @@ -83,6 +84,7 @@ class BelongsUser implements Rule 'piggy_bank_id' => $this->validatePiggyBankId((int)$value), 'piggy_bank_name' => $this->validatePiggyBankName($value), 'bill_id' => $this->validateBillId((int)$value), + 'transaction_journal_id' => $this->validateJournalId((int)$value), 'bill_name' => $this->validateBillName($value), 'budget_id' => $this->validateBudgetId((int)$value), 'category_id' => $this->validateCategoryId((int)$value), @@ -185,6 +187,21 @@ class BelongsUser implements Rule return 1 === $count; } + /** + * @param int $value + * + * @return bool + */ + private function validateJournalId(int $value): bool + { + if (0 === $value) { + return true; + } + $count = TransactionJournal::where('id', '=', $value)->where('user_id', '=', auth()->user()->id)->count(); + + return 1 === $count; + } + /** * @param string $value * diff --git a/app/Validation/GroupValidation.php b/app/Validation/GroupValidation.php index 78fc3760eb..ffe6067c65 100644 --- a/app/Validation/GroupValidation.php +++ b/app/Validation/GroupValidation.php @@ -83,6 +83,30 @@ trait GroupValidation } } + protected function preventNoAccountInfo(Validator $validator): void + { + $transactions = $this->getTransactionsArray($validator); + $hasAccountInfo = false; + $keys = ['source_id', 'destination_id', 'source_name', 'destination_name', 'source_iban', 'destination_iban', 'source_number', + 'destination_number']; + /** @var array $transaction */ + foreach ($transactions as $transaction) { + foreach($keys as $key) { + if(array_key_exists($key, $transaction) && '' !== $transaction[$key]) { + $hasAccountInfo = true; + } + } + } + if(false === $hasAccountInfo) { + $validator->errors()->add( + 'transactions.0.source_id', (string)trans('validation.generic_no_source') + ); + $validator->errors()->add( + 'transactions.0.destination_id', (string)trans('validation.generic_no_destination') + ); + } + } + /** * This method validates if the user has submitted transaction journal ID's for each array they submit, if they've submitted more than 1 transaction * journal. This check is necessary because Firefly III isn't able to distinguish between journals without the ID. diff --git a/resources/lang/en_US/validation.php b/resources/lang/en_US/validation.php index 8a4bf1e955..c531d26ab3 100644 --- a/resources/lang/en_US/validation.php +++ b/resources/lang/en_US/validation.php @@ -214,6 +214,9 @@ return [ 'generic_invalid_source' => 'You can\'t use this account as the source account.', 'generic_invalid_destination' => 'You can\'t use this account as the destination account.', + 'generic_no_source' => 'You must submit source account information.', + 'generic_no_destination' => 'You must submit destination account information.', + 'gte.numeric' => 'The :attribute must be greater than or equal to :value.', 'gt.numeric' => 'The :attribute must be greater than :value.', 'gte.file' => 'The :attribute must be greater than or equal to :value kilobytes.',