mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-22 20:16:22 +00:00 
			
		
		
		
	PHPStorm can order methods by alphabet, who knew.
This commit is contained in:
		| @@ -57,13 +57,6 @@ class ListByCountRequest extends FormRequest | ||||
|         return http_build_query($array); | ||||
|     } | ||||
| 
 | ||||
|     public function getPage(): int | ||||
|     { | ||||
|         $page = $this->convertInteger('page'); | ||||
| 
 | ||||
|         return 0 === $page || $page > 65536 ? 1 : $page; | ||||
|     } | ||||
| 
 | ||||
|     public function getStartRow(): int | ||||
|     { | ||||
|         $startRow = $this->convertInteger('start_row'); | ||||
| @@ -88,6 +81,13 @@ class ListByCountRequest extends FormRequest | ||||
|         return $this->getCarbonDate('end'); | ||||
|     } | ||||
| 
 | ||||
|     public function getPage(): int | ||||
|     { | ||||
|         $page = $this->convertInteger('page'); | ||||
| 
 | ||||
|         return 0 === $page || $page > 65536 ? 1 : $page; | ||||
|     } | ||||
| 
 | ||||
|     public function getTransactionTypes(): array | ||||
|     { | ||||
|         $type = (string)$this->get('type', 'default'); | ||||
|   | ||||
| @@ -78,145 +78,6 @@ class StoreRequest extends FormRequest | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         app('log')->debug('V2: Collect rules of TransactionStoreRequest'); | ||||
| 
 | ||||
|         // at this point the userGroup can't be NULL because the
 | ||||
|         // authorize() method will complain. Loudly.
 | ||||
|         /** @var UserGroup $userGroup */ | ||||
|         $userGroup = $this->getUserGroup(); | ||||
| 
 | ||||
|         return [ | ||||
|             // basic fields for group:
 | ||||
|             'group_title'                            => 'min:1|max:1000|nullable', | ||||
|             'error_if_duplicate_hash'                => [new IsBoolean()], | ||||
|             'apply_rules'                            => [new IsBoolean()], | ||||
| 
 | ||||
|             // transaction rules (in array for splits):
 | ||||
|             'transactions.*.type'                    => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation', | ||||
|             'transactions.*.date'                    => ['required', new IsDateOrTime()], | ||||
|             'transactions.*.order'                   => 'numeric|min:0', | ||||
| 
 | ||||
|             // currency info
 | ||||
|             'transactions.*.currency_id'             => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.currency_code'           => 'min:3|max:51|exists:transaction_currencies,code|nullable', | ||||
|             'transactions.*.foreign_currency_id'     => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.foreign_currency_code'   => 'min:3|max:51|exists:transaction_currencies,code|nullable', | ||||
| 
 | ||||
|             // amount
 | ||||
|             'transactions.*.amount'                  => ['required', new IsValidPositiveAmount()], | ||||
|             'transactions.*.foreign_amount'          => ['nullable', new IsValidPositiveAmount()], | ||||
| 
 | ||||
|             // description
 | ||||
|             'transactions.*.description'             => 'nullable|min:1|max:1000', | ||||
| 
 | ||||
|             // source of transaction
 | ||||
|             'transactions.*.source_id'               => ['numeric', 'nullable', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.source_name'             => 'min:1|max:255|nullable', | ||||
|             'transactions.*.source_iban'             => 'min:1|max:255|nullable|iban', | ||||
|             'transactions.*.source_number'           => 'min:1|max:255|nullable', | ||||
|             'transactions.*.source_bic'              => 'min:1|max:255|nullable|bic', | ||||
| 
 | ||||
|             // destination of transaction
 | ||||
|             'transactions.*.destination_id'          => ['numeric', 'nullable', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.destination_name'        => 'min:1|max:255|nullable', | ||||
|             'transactions.*.destination_iban'        => 'min:1|max:255|nullable|iban', | ||||
|             'transactions.*.destination_number'      => 'min:1|max:255|nullable', | ||||
|             'transactions.*.destination_bic'         => 'min:1|max:255|nullable|bic', | ||||
| 
 | ||||
|             // budget, category, bill and piggy
 | ||||
|             'transactions.*.budget_id'               => ['mustExist:budgets,id', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.budget_name'             => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.category_id'             => ['mustExist:categories,id', new BelongsUserGroup($userGroup), 'nullable'], | ||||
|             'transactions.*.category_name'           => 'min:1|max:255|nullable', | ||||
|             'transactions.*.bill_id'                 => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.bill_name'               => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.piggy_bank_id'           => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.piggy_bank_name'         => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)], | ||||
| 
 | ||||
|             // other interesting fields
 | ||||
|             'transactions.*.reconciled'              => [new IsBoolean()], | ||||
|             'transactions.*.notes'                   => 'min:1|max:32768|nullable', | ||||
|             'transactions.*.tags'                    => 'min:0|max:255', | ||||
|             'transactions.*.tags.*'                  => 'min:0|max:255', | ||||
| 
 | ||||
|             // meta info fields
 | ||||
|             'transactions.*.internal_reference'      => 'min:1|max:255|nullable', | ||||
|             'transactions.*.external_id'             => 'min:1|max:255|nullable', | ||||
|             'transactions.*.recurrence_id'           => 'min:1|max:255|nullable', | ||||
|             'transactions.*.bunq_payment_id'         => 'min:1|max:255|nullable', | ||||
|             'transactions.*.external_url'            => 'min:1|max:255|nullable|url', | ||||
| 
 | ||||
|             // SEPA fields:
 | ||||
|             'transactions.*.sepa_cc'                 => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ct_op'              => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ct_id'              => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_db'                 => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_country'            => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ep'                 => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ci'                 => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_batch_id'           => 'min:1|max:255|nullable', | ||||
| 
 | ||||
|             // dates
 | ||||
|             'transactions.*.interest_date'           => 'date|nullable', | ||||
|             'transactions.*.book_date'               => 'date|nullable', | ||||
|             'transactions.*.process_date'            => 'date|nullable', | ||||
|             'transactions.*.due_date'                => 'date|nullable', | ||||
|             'transactions.*.payment_date'            => 'date|nullable', | ||||
|             'transactions.*.invoice_date'            => 'date|nullable', | ||||
| 
 | ||||
|             // TODO include location and ability to process it.
 | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user      = auth()->user(); | ||||
| 
 | ||||
|         /** @var UserGroup $userGroup */ | ||||
|         $userGroup = $this->getUserGroup(); | ||||
|         $validator->after( | ||||
|             function (Validator $validator) use ($user, $userGroup): void { | ||||
|                 // must be valid array.
 | ||||
|                 $this->validateTransactionArray($validator); // does not need group validation.
 | ||||
| 
 | ||||
|                 // must submit at least one transaction.
 | ||||
|                 app('log')->debug('Now going to validateOneTransaction'); | ||||
|                 $this->validateOneTransaction($validator);              // does not need group validation.
 | ||||
|                 app('log')->debug('Now done with validateOneTransaction'); | ||||
| 
 | ||||
|                 // all journals must have a description
 | ||||
|                 $this->validateDescriptions($validator);                // does not need group validation.
 | ||||
| 
 | ||||
|                 // all transaction types must be equal:
 | ||||
|                 $this->validateTransactionTypes($validator);            // does not need group validation.
 | ||||
| 
 | ||||
|                 // validate foreign currency info
 | ||||
|                 $this->validateForeignCurrencyInformation($validator);  // does not need group validation.
 | ||||
| 
 | ||||
|                 // validate all account info
 | ||||
|                 $this->validateAccountInformation($validator, $user, $userGroup); | ||||
| 
 | ||||
|                 // validate source/destination is equal, depending on the transaction journal type.
 | ||||
|                 $this->validateEqualAccounts($validator); | ||||
| 
 | ||||
|                 // the group must have a description if > 1 journal.
 | ||||
|                 $this->validateGroupDescription($validator); | ||||
|             } | ||||
|         ); | ||||
|         if ($validator->fails()) { | ||||
|             Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get transaction data. | ||||
|      */ | ||||
| @@ -313,4 +174,143 @@ class StoreRequest extends FormRequest | ||||
| 
 | ||||
|         return $return; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         app('log')->debug('V2: Collect rules of TransactionStoreRequest'); | ||||
| 
 | ||||
|         // at this point the userGroup can't be NULL because the
 | ||||
|         // authorize() method will complain. Loudly.
 | ||||
|         /** @var UserGroup $userGroup */ | ||||
|         $userGroup = $this->getUserGroup(); | ||||
| 
 | ||||
|         return [ | ||||
|             // basic fields for group:
 | ||||
|             'group_title'                          => 'min:1|max:1000|nullable', | ||||
|             'error_if_duplicate_hash'              => [new IsBoolean()], | ||||
|             'apply_rules'                          => [new IsBoolean()], | ||||
| 
 | ||||
|             // transaction rules (in array for splits):
 | ||||
|             'transactions.*.type'                  => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation', | ||||
|             'transactions.*.date'                  => ['required', new IsDateOrTime()], | ||||
|             'transactions.*.order'                 => 'numeric|min:0', | ||||
| 
 | ||||
|             // currency info
 | ||||
|             'transactions.*.currency_id'           => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.currency_code'         => 'min:3|max:51|exists:transaction_currencies,code|nullable', | ||||
|             'transactions.*.foreign_currency_id'   => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable', | ||||
| 
 | ||||
|             // amount
 | ||||
|             'transactions.*.amount'                => ['required', new IsValidPositiveAmount()], | ||||
|             'transactions.*.foreign_amount'        => ['nullable', new IsValidPositiveAmount()], | ||||
| 
 | ||||
|             // description
 | ||||
|             'transactions.*.description'           => 'nullable|min:1|max:1000', | ||||
| 
 | ||||
|             // source of transaction
 | ||||
|             'transactions.*.source_id'             => ['numeric', 'nullable', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.source_name'           => 'min:1|max:255|nullable', | ||||
|             'transactions.*.source_iban'           => 'min:1|max:255|nullable|iban', | ||||
|             'transactions.*.source_number'         => 'min:1|max:255|nullable', | ||||
|             'transactions.*.source_bic'            => 'min:1|max:255|nullable|bic', | ||||
| 
 | ||||
|             // destination of transaction
 | ||||
|             'transactions.*.destination_id'        => ['numeric', 'nullable', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.destination_name'      => 'min:1|max:255|nullable', | ||||
|             'transactions.*.destination_iban'      => 'min:1|max:255|nullable|iban', | ||||
|             'transactions.*.destination_number'    => 'min:1|max:255|nullable', | ||||
|             'transactions.*.destination_bic'       => 'min:1|max:255|nullable|bic', | ||||
| 
 | ||||
|             // budget, category, bill and piggy
 | ||||
|             'transactions.*.budget_id'             => ['mustExist:budgets,id', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.budget_name'           => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.category_id'           => ['mustExist:categories,id', new BelongsUserGroup($userGroup), 'nullable'], | ||||
|             'transactions.*.category_name'         => 'min:1|max:255|nullable', | ||||
|             'transactions.*.bill_id'               => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.bill_name'             => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.piggy_bank_id'         => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUserGroup($userGroup)], | ||||
|             'transactions.*.piggy_bank_name'       => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)], | ||||
| 
 | ||||
|             // other interesting fields
 | ||||
|             'transactions.*.reconciled'            => [new IsBoolean()], | ||||
|             'transactions.*.notes'                 => 'min:1|max:32768|nullable', | ||||
|             'transactions.*.tags'                  => 'min:0|max:255', | ||||
|             'transactions.*.tags.*'                => 'min:0|max:255', | ||||
| 
 | ||||
|             // meta info fields
 | ||||
|             'transactions.*.internal_reference'    => 'min:1|max:255|nullable', | ||||
|             'transactions.*.external_id'           => 'min:1|max:255|nullable', | ||||
|             'transactions.*.recurrence_id'         => 'min:1|max:255|nullable', | ||||
|             'transactions.*.bunq_payment_id'       => 'min:1|max:255|nullable', | ||||
|             'transactions.*.external_url'          => 'min:1|max:255|nullable|url', | ||||
| 
 | ||||
|             // SEPA fields:
 | ||||
|             'transactions.*.sepa_cc'               => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ct_op'            => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ct_id'            => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_db'               => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_country'          => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ep'               => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ci'               => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_batch_id'         => 'min:1|max:255|nullable', | ||||
| 
 | ||||
|             // dates
 | ||||
|             'transactions.*.interest_date'         => 'date|nullable', | ||||
|             'transactions.*.book_date'             => 'date|nullable', | ||||
|             'transactions.*.process_date'          => 'date|nullable', | ||||
|             'transactions.*.due_date'              => 'date|nullable', | ||||
|             'transactions.*.payment_date'          => 'date|nullable', | ||||
|             'transactions.*.invoice_date'          => 'date|nullable', | ||||
| 
 | ||||
|             // TODO include location and ability to process it.
 | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user      = auth()->user(); | ||||
| 
 | ||||
|         /** @var UserGroup $userGroup */ | ||||
|         $userGroup = $this->getUserGroup(); | ||||
|         $validator->after( | ||||
|             function (Validator $validator) use ($user, $userGroup): void { | ||||
|                 // must be valid array.
 | ||||
|                 $this->validateTransactionArray($validator); // does not need group validation.
 | ||||
| 
 | ||||
|                 // must submit at least one transaction.
 | ||||
|                 app('log')->debug('Now going to validateOneTransaction'); | ||||
|                 $this->validateOneTransaction($validator);              // does not need group validation.
 | ||||
|                 app('log')->debug('Now done with validateOneTransaction'); | ||||
| 
 | ||||
|                 // all journals must have a description
 | ||||
|                 $this->validateDescriptions($validator);                // does not need group validation.
 | ||||
| 
 | ||||
|                 // all transaction types must be equal:
 | ||||
|                 $this->validateTransactionTypes($validator);            // does not need group validation.
 | ||||
| 
 | ||||
|                 // validate foreign currency info
 | ||||
|                 $this->validateForeignCurrencyInformation($validator);  // does not need group validation.
 | ||||
| 
 | ||||
|                 // validate all account info
 | ||||
|                 $this->validateAccountInformation($validator, $user, $userGroup); | ||||
| 
 | ||||
|                 // validate source/destination is equal, depending on the transaction journal type.
 | ||||
|                 $this->validateEqualAccounts($validator); | ||||
| 
 | ||||
|                 // the group must have a description if > 1 journal.
 | ||||
|                 $this->validateGroupDescription($validator); | ||||
|             } | ||||
|         ); | ||||
|         if ($validator->fails()) { | ||||
|             Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -91,127 +91,6 @@ class UpdateRequest extends Request | ||||
|         return $data; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         app('log')->debug(sprintf('Now in %s', __METHOD__)); | ||||
|         $validProtocols = config('firefly.valid_url_protocols'); | ||||
| 
 | ||||
|         return [ | ||||
|             // basic fields for group:
 | ||||
|             'group_title'                            => 'min:1|max:1000|nullable', | ||||
|             'apply_rules'                            => [new IsBoolean()], | ||||
| 
 | ||||
|             // transaction rules (in array for splits):
 | ||||
|             'transactions.*.type'                    => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation', | ||||
|             'transactions.*.date'                    => [new IsDateOrTime()], | ||||
|             'transactions.*.order'                   => 'numeric|min:0', | ||||
| 
 | ||||
|             // group id:
 | ||||
|             'transactions.*.transaction_journal_id'  => ['nullable', 'numeric', new BelongsUser()], | ||||
| 
 | ||||
|             // currency info
 | ||||
|             'transactions.*.currency_id'             => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.currency_code'           => 'min:3|max:51|exists:transaction_currencies,code|nullable', | ||||
|             'transactions.*.foreign_currency_id'     => 'nullable|numeric|exists:transaction_currencies,id', | ||||
|             'transactions.*.foreign_currency_code'   => 'nullable|min:3|max:51|exists:transaction_currencies,code', | ||||
| 
 | ||||
|             // amount
 | ||||
|             'transactions.*.amount'                  => ['nullable', new IsValidPositiveAmount()], | ||||
|             'transactions.*.foreign_amount'          => ['nullable', new IsValidZeroOrMoreAmount()], | ||||
| 
 | ||||
|             // description
 | ||||
|             'transactions.*.description'             => 'nullable|min:1|max:1000', | ||||
| 
 | ||||
|             // source of transaction
 | ||||
|             'transactions.*.source_id'               => ['numeric', 'nullable', new BelongsUser()], | ||||
|             'transactions.*.source_name'             => 'min:1|max:255|nullable', | ||||
| 
 | ||||
|             // destination of transaction
 | ||||
|             'transactions.*.destination_id'          => ['numeric', 'nullable', new BelongsUser()], | ||||
|             'transactions.*.destination_name'        => 'min:1|max:255|nullable', | ||||
| 
 | ||||
|             // budget, category, bill and piggy
 | ||||
|             'transactions.*.budget_id'               => ['mustExist:budgets,id', new BelongsUser(), 'nullable'], | ||||
|             'transactions.*.budget_name'             => ['min:1', 'max:255', 'nullable', new BelongsUser()], | ||||
|             'transactions.*.category_id'             => ['mustExist:categories,id', new BelongsUser(), 'nullable'], | ||||
|             'transactions.*.category_name'           => 'min:1|max:255|nullable', | ||||
|             'transactions.*.bill_id'                 => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()], | ||||
|             'transactions.*.bill_name'               => ['min:1', 'max:255', 'nullable', new BelongsUser()], | ||||
| 
 | ||||
|             // other interesting fields
 | ||||
|             'transactions.*.reconciled'              => [new IsBoolean()], | ||||
|             'transactions.*.notes'                   => 'min:1|max:32768|nullable', | ||||
|             'transactions.*.tags'                    => 'min:0|max:255|nullable', | ||||
|             'transactions.*.tags.*'                  => 'min:0|max:255', | ||||
| 
 | ||||
|             // meta info fields
 | ||||
|             'transactions.*.internal_reference'      => 'min:1|max:255|nullable', | ||||
|             'transactions.*.external_id'             => 'min:1|max:255|nullable', | ||||
|             'transactions.*.recurrence_id'           => 'min:1|max:255|nullable', | ||||
|             'transactions.*.bunq_payment_id'         => 'min:1|max:255|nullable', | ||||
|             'transactions.*.external_url'            => sprintf('min:1|max:255|nullable|url:%s', $validProtocols), | ||||
| 
 | ||||
|             // SEPA fields:
 | ||||
|             'transactions.*.sepa_cc'                 => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ct_op'              => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ct_id'              => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_db'                 => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_country'            => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ep'                 => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ci'                 => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_batch_id'           => 'min:1|max:255|nullable', | ||||
| 
 | ||||
|             // dates
 | ||||
|             'transactions.*.interest_date'           => 'date|nullable', | ||||
|             'transactions.*.book_date'               => 'date|nullable', | ||||
|             'transactions.*.process_date'            => 'date|nullable', | ||||
|             'transactions.*.due_date'                => 'date|nullable', | ||||
|             'transactions.*.payment_date'            => 'date|nullable', | ||||
|             'transactions.*.invoice_date'            => 'date|nullable', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         app('log')->debug('Now in withValidator'); | ||||
| 
 | ||||
|         /** @var TransactionGroup $transactionGroup */ | ||||
|         $transactionGroup = $this->route()->parameter('userGroupTransaction'); | ||||
|         $validator->after( | ||||
|             function (Validator $validator) use ($transactionGroup): void { | ||||
|                 // if more than one, verify that there are journal ID's present.
 | ||||
|                 $this->validateJournalIds($validator, $transactionGroup); | ||||
| 
 | ||||
|                 // all transaction types must be equal:
 | ||||
|                 $this->validateTransactionTypesForUpdate($validator); | ||||
| 
 | ||||
|                 // user wants to update a reconciled transaction.
 | ||||
|                 // source, destination, amount + foreign_amount cannot be changed
 | ||||
|                 // and must be omitted from the request.
 | ||||
|                 $this->preventUpdateReconciled($validator, $transactionGroup); | ||||
| 
 | ||||
|                 // validate source/destination is equal, depending on the transaction journal type.
 | ||||
|                 $this->validateEqualAccountsForUpdate($validator, $transactionGroup); | ||||
| 
 | ||||
|                 // see method:
 | ||||
|                 // $this->preventNoAccountInfo($validator, );
 | ||||
| 
 | ||||
|                 // validate that the currency fits the source and/or destination account.
 | ||||
|                 // validate all account info
 | ||||
|                 $this->validateAccountInformationUpdate($validator, $transactionGroup); | ||||
|             } | ||||
|         ); | ||||
|         if ($validator->fails()) { | ||||
|             Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get transaction data. | ||||
|      * | ||||
| @@ -259,7 +138,7 @@ class UpdateRequest extends Request | ||||
|     { | ||||
|         foreach ($this->integerFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]); | ||||
|                 $current[$fieldName] = $this->integerFromValue((string)$transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @@ -274,7 +153,7 @@ class UpdateRequest extends Request | ||||
|     { | ||||
|         foreach ($this->stringFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->clearString((string) $transaction[$fieldName]); | ||||
|                 $current[$fieldName] = $this->clearString((string)$transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @@ -289,7 +168,7 @@ class UpdateRequest extends Request | ||||
|     { | ||||
|         foreach ($this->textareaFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->clearStringKeepNewlines((string) $transaction[$fieldName]); // keep newlines
 | ||||
|                 $current[$fieldName] = $this->clearStringKeepNewlines((string)$transaction[$fieldName]); // keep newlines
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @@ -305,8 +184,8 @@ class UpdateRequest extends Request | ||||
|         foreach ($this->dateFields as $fieldName) { | ||||
|             app('log')->debug(sprintf('Now at date field %s', $fieldName)); | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName])); | ||||
|                 $current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]); | ||||
|                 app('log')->debug(sprintf('New value: "%s"', (string)$transaction[$fieldName])); | ||||
|                 $current[$fieldName] = $this->dateFromValue((string)$transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @@ -321,7 +200,7 @@ class UpdateRequest extends Request | ||||
|     { | ||||
|         foreach ($this->booleanFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]); | ||||
|                 $current[$fieldName] = $this->convertBoolean((string)$transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @@ -356,11 +235,132 @@ class UpdateRequest extends Request | ||||
|                     $current[$fieldName] = sprintf('%.12f', $value); | ||||
|                 } | ||||
|                 if (!is_float($value)) { | ||||
|                     $current[$fieldName] = (string) $value; | ||||
|                     $current[$fieldName] = (string)$value; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $current; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         app('log')->debug(sprintf('Now in %s', __METHOD__)); | ||||
|         $validProtocols = config('firefly.valid_url_protocols'); | ||||
| 
 | ||||
|         return [ | ||||
|             // basic fields for group:
 | ||||
|             'group_title'                           => 'min:1|max:1000|nullable', | ||||
|             'apply_rules'                           => [new IsBoolean()], | ||||
| 
 | ||||
|             // transaction rules (in array for splits):
 | ||||
|             'transactions.*.type'                   => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation', | ||||
|             'transactions.*.date'                   => [new IsDateOrTime()], | ||||
|             'transactions.*.order'                  => 'numeric|min:0', | ||||
| 
 | ||||
|             // group id:
 | ||||
|             'transactions.*.transaction_journal_id' => ['nullable', 'numeric', new BelongsUser()], | ||||
| 
 | ||||
|             // currency info
 | ||||
|             'transactions.*.currency_id'            => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.currency_code'          => 'min:3|max:51|exists:transaction_currencies,code|nullable', | ||||
|             'transactions.*.foreign_currency_id'    => 'nullable|numeric|exists:transaction_currencies,id', | ||||
|             'transactions.*.foreign_currency_code'  => 'nullable|min:3|max:51|exists:transaction_currencies,code', | ||||
| 
 | ||||
|             // amount
 | ||||
|             'transactions.*.amount'                 => ['nullable', new IsValidPositiveAmount()], | ||||
|             'transactions.*.foreign_amount'         => ['nullable', new IsValidZeroOrMoreAmount()], | ||||
| 
 | ||||
|             // description
 | ||||
|             'transactions.*.description'            => 'nullable|min:1|max:1000', | ||||
| 
 | ||||
|             // source of transaction
 | ||||
|             'transactions.*.source_id'              => ['numeric', 'nullable', new BelongsUser()], | ||||
|             'transactions.*.source_name'            => 'min:1|max:255|nullable', | ||||
| 
 | ||||
|             // destination of transaction
 | ||||
|             'transactions.*.destination_id'         => ['numeric', 'nullable', new BelongsUser()], | ||||
|             'transactions.*.destination_name'       => 'min:1|max:255|nullable', | ||||
| 
 | ||||
|             // budget, category, bill and piggy
 | ||||
|             'transactions.*.budget_id'              => ['mustExist:budgets,id', new BelongsUser(), 'nullable'], | ||||
|             'transactions.*.budget_name'            => ['min:1', 'max:255', 'nullable', new BelongsUser()], | ||||
|             'transactions.*.category_id'            => ['mustExist:categories,id', new BelongsUser(), 'nullable'], | ||||
|             'transactions.*.category_name'          => 'min:1|max:255|nullable', | ||||
|             'transactions.*.bill_id'                => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()], | ||||
|             'transactions.*.bill_name'              => ['min:1', 'max:255', 'nullable', new BelongsUser()], | ||||
| 
 | ||||
|             // other interesting fields
 | ||||
|             'transactions.*.reconciled'             => [new IsBoolean()], | ||||
|             'transactions.*.notes'                  => 'min:1|max:32768|nullable', | ||||
|             'transactions.*.tags'                   => 'min:0|max:255|nullable', | ||||
|             'transactions.*.tags.*'                 => 'min:0|max:255', | ||||
| 
 | ||||
|             // meta info fields
 | ||||
|             'transactions.*.internal_reference'     => 'min:1|max:255|nullable', | ||||
|             'transactions.*.external_id'            => 'min:1|max:255|nullable', | ||||
|             'transactions.*.recurrence_id'          => 'min:1|max:255|nullable', | ||||
|             'transactions.*.bunq_payment_id'        => 'min:1|max:255|nullable', | ||||
|             'transactions.*.external_url'           => sprintf('min:1|max:255|nullable|url:%s', $validProtocols), | ||||
| 
 | ||||
|             // SEPA fields:
 | ||||
|             'transactions.*.sepa_cc'                => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ct_op'             => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ct_id'             => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_db'                => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_country'           => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ep'                => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_ci'                => 'min:1|max:255|nullable', | ||||
|             'transactions.*.sepa_batch_id'          => 'min:1|max:255|nullable', | ||||
| 
 | ||||
|             // dates
 | ||||
|             'transactions.*.interest_date'          => 'date|nullable', | ||||
|             'transactions.*.book_date'              => 'date|nullable', | ||||
|             'transactions.*.process_date'           => 'date|nullable', | ||||
|             'transactions.*.due_date'               => 'date|nullable', | ||||
|             'transactions.*.payment_date'           => 'date|nullable', | ||||
|             'transactions.*.invoice_date'           => 'date|nullable', | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         app('log')->debug('Now in withValidator'); | ||||
| 
 | ||||
|         /** @var TransactionGroup $transactionGroup */ | ||||
|         $transactionGroup = $this->route()->parameter('userGroupTransaction'); | ||||
|         $validator->after( | ||||
|             function (Validator $validator) use ($transactionGroup): void { | ||||
|                 // if more than one, verify that there are journal ID's present.
 | ||||
|                 $this->validateJournalIds($validator, $transactionGroup); | ||||
| 
 | ||||
|                 // all transaction types must be equal:
 | ||||
|                 $this->validateTransactionTypesForUpdate($validator); | ||||
| 
 | ||||
|                 // user wants to update a reconciled transaction.
 | ||||
|                 // source, destination, amount + foreign_amount cannot be changed
 | ||||
|                 // and must be omitted from the request.
 | ||||
|                 $this->preventUpdateReconciled($validator, $transactionGroup); | ||||
| 
 | ||||
|                 // validate source/destination is equal, depending on the transaction journal type.
 | ||||
|                 $this->validateEqualAccountsForUpdate($validator, $transactionGroup); | ||||
| 
 | ||||
|                 // see method:
 | ||||
|                 // $this->preventNoAccountInfo($validator, );
 | ||||
| 
 | ||||
|                 // validate that the currency fits the source and/or destination account.
 | ||||
|                 // validate all account info
 | ||||
|                 $this->validateAccountInformationUpdate($validator, $transactionGroup); | ||||
|             } | ||||
|         ); | ||||
|         if ($validator->fails()) { | ||||
|             Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user