2018-07-05 11:02:02 -05:00
< ? php
/**
2019-10-01 23:37:26 -05:00
* RecurrenceValidation . php
2020-02-16 06:58:22 -06:00
* Copyright ( c ) 2019 james @ firefly - iii . org
2018-07-05 11:02:02 -05:00
*
2019-10-01 23:37:26 -05:00
* This file is part of Firefly III ( https :// github . com / firefly - iii ) .
2018-07-05 11:02:02 -05:00
*
2019-10-01 23:37:26 -05:00
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
2018-07-05 11:02:02 -05:00
*
2019-10-01 23:37:26 -05:00
* This program is distributed in the hope that it will be useful ,
2018-07-05 11:02:02 -05:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2019-10-01 23:37:26 -05:00
* GNU Affero General Public License for more details .
2018-07-05 11:02:02 -05:00
*
2019-10-01 23:37:26 -05:00
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
2018-07-05 11:02:02 -05:00
*/
declare ( strict_types = 1 );
namespace FireflyIII\Validation ;
use Carbon\Carbon ;
2021-03-15 13:51:55 -05:00
use FireflyIII\Models\Recurrence ;
use FireflyIII\Models\RecurrenceTransaction ;
2018-07-05 11:02:02 -05:00
use Illuminate\Validation\Validator ;
/**
* Trait RecurrenceValidation
*
* Contains advanced validation rules used in validation of new and existing recurrences .
*/
trait RecurrenceValidation
{
2019-08-26 22:57:09 -05:00
/**
* Validate account information input for recurrences which are being updated .
*
2022-10-30 05:43:17 -05:00
* TODO Must always trigger when the type of the recurrence changes .
2019-08-26 22:57:09 -05:00
*/
public function valUpdateAccountInfo ( Validator $validator ) : void
{
2024-01-01 07:43:56 -06:00
$data = $validator -> getData ();
2019-08-26 22:57:09 -05:00
2024-01-01 07:43:56 -06:00
$transactionType = $data [ 'type' ] ? ? 'invalid' ;
2021-03-15 13:51:55 -05:00
// grab model from parameter and try to set the transaction type from it
if ( 'invalid' === $transactionType ) {
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'Type is invalid but we will search for it.' );
2023-12-20 12:35:52 -06:00
/** @var null|Recurrence $recurrence */
2023-11-28 23:36:48 -06:00
$recurrence = $this -> route () ? -> parameter ( 'recurrence' );
2021-03-15 13:51:55 -05:00
if ( null !== $recurrence ) {
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'There is a recurrence in the route.' );
2023-12-20 12:35:52 -06:00
2021-03-15 13:51:55 -05:00
// ok so we have a recurrence should be able to extract type somehow.
2023-12-20 12:35:52 -06:00
/** @var null|RecurrenceTransaction $first */
2021-03-15 13:51:55 -05:00
$first = $recurrence -> recurrenceTransactions () -> first ();
if ( null !== $first ) {
2023-11-05 02:40:45 -06:00
$transactionType = null !== $first -> transactionType ? $first -> transactionType -> type : 'withdrawal' ;
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( sprintf ( 'Determined type to be %s.' , $transactionType ));
2021-03-15 13:51:55 -05:00
}
2021-03-21 03:15:40 -05:00
if ( null === $first ) {
2022-10-30 08:44:49 -05:00
app ( 'log' ) -> warning ( 'Just going to assume type is a withdrawal.' );
2021-03-15 13:51:55 -05:00
$transactionType = 'withdrawal' ;
}
}
}
2024-01-01 07:43:56 -06:00
$transactions = $data [ 'transactions' ] ? ? [];
2019-08-26 22:57:09 -05:00
/** @var AccountValidator $accountValidator */
$accountValidator = app ( AccountValidator :: class );
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( sprintf ( 'Going to loop %d transaction(s)' , count ( $transactions )));
2019-08-26 22:57:09 -05:00
foreach ( $transactions as $index => $transaction ) {
2024-01-01 07:43:56 -06:00
$transactionType = $transaction [ 'type' ] ? ? $transactionType ;
2019-08-26 22:57:09 -05:00
$accountValidator -> setTransactionType ( $transactionType );
2021-03-21 03:15:40 -05:00
if (
! array_key_exists ( 'source_id' , $transaction )
&& ! array_key_exists ( 'destination_id' , $transaction )
&& ! array_key_exists ( 'source_name' , $transaction )
&& ! array_key_exists ( 'destination_name' , $transaction )
2021-03-20 13:17:22 -05:00
) {
continue ;
}
2019-08-26 22:57:09 -05:00
// validate source account.
2024-02-22 13:11:09 -06:00
$sourceId = array_key_exists ( 'source_id' , $transaction ) ? ( int ) $transaction [ 'source_id' ] : null ;
2024-01-01 07:43:56 -06:00
$sourceName = $transaction [ 'source_name' ] ? ? null ;
$validSource = $accountValidator -> validateSource ([ 'id' => $sourceId , 'name' => $sourceName ]);
2019-08-26 22:57:09 -05:00
// do something with result:
if ( false === $validSource ) {
$validator -> errors () -> add ( sprintf ( 'transactions.%d.source_id' , $index ), $accountValidator -> sourceError );
$validator -> errors () -> add ( sprintf ( 'transactions.%d.source_name' , $index ), $accountValidator -> sourceError );
return ;
}
// validate destination account
2024-02-22 13:11:09 -06:00
$destinationId = array_key_exists ( 'destination_id' , $transaction ) ? ( int ) $transaction [ 'destination_id' ] : null ;
2019-08-26 22:57:09 -05:00
$destinationName = $transaction [ 'destination_name' ] ? ? null ;
2023-12-20 12:35:52 -06:00
$validDestination = $accountValidator -> validateDestination ([ 'id' => $destinationId , 'name' => $destinationName ]);
2019-08-26 22:57:09 -05:00
// do something with result:
if ( false === $validDestination ) {
$validator -> errors () -> add ( sprintf ( 'transactions.%d.destination_id' , $index ), $accountValidator -> destError );
$validator -> errors () -> add ( sprintf ( 'transactions.%d.destination_name' , $index ), $accountValidator -> destError );
return ;
}
}
}
2018-08-06 12:14:30 -05:00
/**
* Adds an error to the validator when there are no repetitions in the array of data .
*/
public function validateOneRepetition ( Validator $validator ) : void
{
$data = $validator -> getData ();
$repetitions = $data [ 'repetitions' ] ? ? [];
// need at least one transaction
2022-11-03 23:11:05 -05:00
if ( ! is_countable ( $repetitions ) || 0 === count ( $repetitions )) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( 'repetitions' , ( string ) trans ( 'validation.at_least_one_repetition' ));
2018-08-06 12:14:30 -05:00
}
}
2019-08-26 12:09:55 -05:00
/**
* Adds an error to the validator when there are no repetitions in the array of data .
*/
public function validateOneRepetitionUpdate ( Validator $validator ) : void
{
$data = $validator -> getData ();
$repetitions = $data [ 'repetitions' ] ? ? null ;
if ( null === $repetitions ) {
return ;
}
// need at least one transaction
2022-11-03 23:11:05 -05:00
if ( 0 === count ( $repetitions )) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( 'repetitions' , ( string ) trans ( 'validation.at_least_one_repetition' ));
2019-08-26 12:09:55 -05:00
}
}
2018-08-06 12:14:30 -05:00
/**
* Validates that the recurrence has valid repetition information . It either doesn ' t stop ,
* or stops after X times or at X date . Not both of them . ,
*/
public function validateRecurrenceRepetition ( Validator $validator ) : void
{
$data = $validator -> getData ();
$repetitions = $data [ 'nr_of_repetitions' ] ? ? null ;
$repeatUntil = $data [ 'repeat_until' ] ? ? null ;
if ( null !== $repetitions && null !== $repeatUntil ) {
// expect a date OR count:
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( 'repeat_until' , ( string ) trans ( 'validation.require_repeat_until' ));
$validator -> errors () -> add ( 'nr_of_repetitions' , ( string ) trans ( 'validation.require_repeat_until' ));
2018-08-06 12:14:30 -05:00
}
}
2023-12-20 22:07:26 -06:00
public function validateRecurringConfig ( Validator $validator ) : void
2021-03-21 03:15:40 -05:00
{
$data = $validator -> getData ();
2024-02-22 13:11:09 -06:00
$reps = array_key_exists ( 'nr_of_repetitions' , $data ) ? ( int ) $data [ 'nr_of_repetitions' ] : null ;
2021-03-21 03:15:40 -05:00
$repeatUntil = array_key_exists ( 'repeat_until' , $data ) ? new Carbon ( $data [ 'repeat_until' ]) : null ;
if ( null === $reps && null === $repeatUntil ) {
$validator -> errors () -> add ( 'nr_of_repetitions' , trans ( 'validation.require_repeat_until' ));
$validator -> errors () -> add ( 'repeat_until' , trans ( 'validation.require_repeat_until' ));
return ;
}
if ( $reps > 0 && null !== $repeatUntil ) {
$validator -> errors () -> add ( 'nr_of_repetitions' , trans ( 'validation.require_repeat_until' ));
$validator -> errors () -> add ( 'repeat_until' , trans ( 'validation.require_repeat_until' ));
}
}
2018-07-05 11:02:02 -05:00
public function validateRepetitionMoment ( Validator $validator ) : void
{
$data = $validator -> getData ();
$repetitions = $data [ 'repetitions' ] ? ? [];
2021-03-06 09:15:39 -06:00
if ( ! is_array ( $repetitions )) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'repetitions.%d.type' , 0 ), ( string ) trans ( 'validation.valid_recurrence_rep_type' ));
2021-03-06 09:15:39 -06:00
return ;
}
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
/**
2023-06-21 05:34:58 -05:00
* @ var int $index
2018-07-05 11:02:02 -05:00
* @ var array $repetition
*/
foreach ( $repetitions as $index => $repetition ) {
2021-03-12 11:31:19 -06:00
if ( ! array_key_exists ( 'moment' , $repetition )) {
2023-06-03 10:16:28 -05:00
$repetition [ 'moment' ] = '' ;
2021-03-12 11:31:19 -06:00
}
if ( null === $repetition [ 'moment' ]) {
2021-03-06 09:15:39 -06:00
$repetition [ 'moment' ] = '' ;
}
2023-06-03 10:16:28 -05:00
2019-08-22 10:56:48 -05:00
switch ( $repetition [ 'type' ] ? ? 'empty' ) {
2018-07-05 11:02:02 -05:00
default :
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'repetitions.%d.type' , $index ), ( string ) trans ( 'validation.valid_recurrence_rep_type' ));
2018-07-05 11:02:02 -05:00
return ;
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
case 'daily' :
2024-02-22 13:11:09 -06:00
$this -> validateDaily ( $validator , $index , ( string ) $repetition [ 'moment' ]);
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
break ;
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
case 'monthly' :
2024-02-22 13:11:09 -06:00
$this -> validateMonthly ( $validator , $index , ( int ) $repetition [ 'moment' ]);
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
break ;
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
case 'ndom' :
2024-02-22 13:11:09 -06:00
$this -> validateNdom ( $validator , $index , ( string ) $repetition [ 'moment' ]);
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
break ;
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
case 'weekly' :
2024-02-22 13:11:09 -06:00
$this -> validateWeekly ( $validator , $index , ( int ) $repetition [ 'moment' ]);
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
break ;
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
case 'yearly' :
2024-02-22 13:11:09 -06:00
$this -> validateYearly ( $validator , $index , ( string ) $repetition [ 'moment' ]);
2023-12-20 12:35:52 -06:00
2018-07-05 11:02:02 -05:00
break ;
}
}
}
/**
* If the repetition type is daily , the moment should be empty .
*/
protected function validateDaily ( Validator $validator , int $index , string $moment ) : void
{
if ( '' !== $moment ) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'repetitions.%d.moment' , $index ), ( string ) trans ( 'validation.valid_recurrence_rep_moment' ));
2018-07-05 11:02:02 -05:00
}
}
/**
* If the repetition type is monthly , the moment should be a day between 1 - 31 ( inclusive ) .
*/
protected function validateMonthly ( Validator $validator , int $index , int $dayOfMonth ) : void
{
if ( $dayOfMonth < 1 || $dayOfMonth > 31 ) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'repetitions.%d.moment' , $index ), ( string ) trans ( 'validation.valid_recurrence_rep_moment' ));
2018-07-05 11:02:02 -05:00
}
}
/**
* If the repetition type is " ndom " , the first part must be between 1 - 5 ( inclusive ), for the week in the month ,
* and the second one must be between 1 - 7 ( inclusive ) for the day of the week .
*/
protected function validateNdom ( Validator $validator , int $index , string $moment ) : void
{
$parameters = explode ( ',' , $moment );
2019-05-30 05:31:19 -05:00
if ( 2 !== count ( $parameters )) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'repetitions.%d.moment' , $index ), ( string ) trans ( 'validation.valid_recurrence_rep_moment' ));
2018-07-05 11:02:02 -05:00
return ;
}
2024-02-22 13:11:09 -06:00
$nthDay = ( int )( $parameters [ 0 ] ? ? 0.0 );
$dayOfWeek = ( int )( $parameters [ 1 ] ? ? 0.0 );
2018-07-05 11:02:02 -05:00
if ( $nthDay < 1 || $nthDay > 5 ) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'repetitions.%d.moment' , $index ), ( string ) trans ( 'validation.valid_recurrence_rep_moment' ));
2018-07-05 11:02:02 -05:00
return ;
}
if ( $dayOfWeek < 1 || $dayOfWeek > 7 ) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'repetitions.%d.moment' , $index ), ( string ) trans ( 'validation.valid_recurrence_rep_moment' ));
2018-07-05 11:02:02 -05:00
}
}
2023-06-03 14:17:49 -05:00
/**
2023-06-21 05:34:58 -05:00
* If the repetition type is weekly , the moment should be a day between 1 - 7 ( inclusive ) .
*/
protected function validateWeekly ( Validator $validator , int $index , int $dayOfWeek ) : void
{
if ( $dayOfWeek < 1 || $dayOfWeek > 7 ) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'repetitions.%d.moment' , $index ), ( string ) trans ( 'validation.valid_recurrence_rep_moment' ));
2023-06-21 05:34:58 -05:00
}
}
/**
* If the repetition type is yearly , the moment should be a valid date .
*/
protected function validateYearly ( Validator $validator , int $index , string $moment ) : void
{
try {
Carbon :: createFromFormat ( 'Y-m-d' , $moment );
2023-12-20 12:35:52 -06:00
} catch ( \InvalidArgumentException $e ) { // @phpstan-ignore-line
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( sprintf ( 'Invalid argument for Carbon: %s' , $e -> getMessage ()));
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'repetitions.%d.moment' , $index ), ( string ) trans ( 'validation.valid_recurrence_rep_moment' ));
2023-06-21 05:34:58 -05:00
}
}
2023-12-22 13:12:38 -06:00
/**
* @ SuppressWarnings ( PHPMD . NPathComplexity )
*/
2023-06-03 14:17:49 -05:00
protected function validateTransactionId ( Recurrence $recurrence , Validator $validator ) : void
{
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'Now in validateTransactionId' );
2023-06-03 14:17:49 -05:00
$transactions = $this -> getTransactionData ();
$submittedTrCount = count ( $transactions );
if ( 0 === $submittedTrCount ) {
2023-10-29 00:31:13 -05:00
app ( 'log' ) -> warning ( '[b] User submitted no transactions.' );
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( 'transactions' , ( string ) trans ( 'validation.at_least_one_transaction' ));
2023-12-20 12:35:52 -06:00
2023-06-03 14:17:49 -05:00
return ;
}
2024-01-01 07:43:56 -06:00
$originalTrCount = $recurrence -> recurrenceTransactions () -> count ();
2023-06-03 14:17:49 -05:00
if ( 1 === $submittedTrCount && 1 === $originalTrCount ) {
2024-01-01 07:43:56 -06:00
$first = $transactions [ 0 ]; // can safely assume index 0.
2023-06-03 14:17:49 -05:00
if ( ! array_key_exists ( 'id' , $first )) {
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'Single count and no ID, done.' );
2023-12-20 12:35:52 -06:00
2023-06-03 14:17:49 -05:00
return ; // home safe!
}
2024-01-01 07:43:56 -06:00
$id = $first [ 'id' ];
2024-02-22 13:11:09 -06:00
if ( '' === ( string ) $id ) {
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'Single count and empty ID, done.' );
2023-12-20 12:35:52 -06:00
2023-06-03 14:17:49 -05:00
return ; // home safe!
}
2024-02-22 13:11:09 -06:00
$integer = ( int ) $id ;
2023-06-03 14:17:49 -05:00
$secondCount = $recurrence -> recurrenceTransactions () -> where ( 'recurrences_transactions.id' , $integer ) -> count ();
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( sprintf ( 'Result of ID count: %d' , $secondCount ));
2023-06-03 14:17:49 -05:00
if ( 0 === $secondCount ) {
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( 'transactions.0.id' , ( string ) trans ( 'validation.id_does_not_match' , [ 'id' => $integer ]));
2023-06-03 14:17:49 -05:00
}
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'Single ID validation done.' );
2023-12-20 12:35:52 -06:00
2023-06-03 14:17:49 -05:00
return ;
}
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'Multi ID validation.' );
2024-01-01 07:43:56 -06:00
$idsMandatory = false ;
2023-06-03 14:17:49 -05:00
if ( $submittedTrCount < $originalTrCount ) {
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( sprintf ( 'User submits %d transaction, recurrence has %d transactions. All entries must have ID.' , $submittedTrCount , $originalTrCount ));
2023-06-03 14:17:49 -05:00
$idsMandatory = true ;
}
2023-12-20 12:35:52 -06:00
2023-06-03 14:17:49 -05:00
/**
* Loop all transactions submitted by the user .
* If the user has submitted fewer transactions than the original recurrence has , all submitted entries must have an ID .
* Any ID ' s missing will be deleted later on .
*
* If the user submits more or the same number of transactions ( n ), the following rules apply :
*
* 1. Any 1 transaction does not need to have an ID . Since the other n - 1 can be matched , the last one can be assumed .
* 2. If the user submits more transactions than already present , count the number of existing transactions . At least those must be matched . After that , submit as many as you like .
* 3. If the user submits the same number of transactions as already present , all but one must have an ID .
*/
2024-01-01 07:43:56 -06:00
$unmatchedIds = 0 ;
2023-06-03 14:17:49 -05:00
foreach ( $transactions as $index => $transaction ) {
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( sprintf ( 'Now at %d/%d' , $index + 1 , $submittedTrCount ));
2023-06-03 14:17:49 -05:00
if ( ! is_array ( $transaction )) {
2023-10-29 00:31:13 -05:00
app ( 'log' ) -> warning ( 'Not an array. Give error.' );
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'transactions.%d.id' , $index ), ( string ) trans ( 'validation.at_least_one_transaction' ));
2023-12-20 12:35:52 -06:00
2023-06-03 14:17:49 -05:00
return ;
}
if ( ! array_key_exists ( 'id' , $transaction ) && $idsMandatory ) {
2023-10-29 00:31:13 -05:00
app ( 'log' ) -> warning ( 'ID is mandatory but array has no ID.' );
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( sprintf ( 'transactions.%d.id' , $index ), ( string ) trans ( 'validation.need_id_to_match' ));
2023-12-20 12:35:52 -06:00
2023-06-03 14:17:49 -05:00
return ;
}
if ( array_key_exists ( 'id' , $transaction )) { // don't matter if $idsMandatory
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'Array has ID.' );
2024-02-22 13:11:09 -06:00
$idCount = $recurrence -> recurrenceTransactions () -> where ( 'recurrences_transactions.id' , ( int ) $transaction [ 'id' ]) -> count ();
2023-06-03 14:17:49 -05:00
if ( 0 === $idCount ) {
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'ID does not exist or no match. Count another unmatched ID.' );
2023-12-20 12:35:52 -06:00
++ $unmatchedIds ;
2023-06-03 14:17:49 -05:00
}
}
if ( ! array_key_exists ( 'id' , $transaction ) && ! $idsMandatory ) {
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'Array has no ID but was not mandatory at this point.' );
2023-12-20 12:35:52 -06:00
++ $unmatchedIds ;
2023-06-03 14:17:49 -05:00
}
}
// if too many don't match, but you haven't submitted more than already present:
2024-01-01 07:43:56 -06:00
$maxUnmatched = max ( 1 , $submittedTrCount - $originalTrCount );
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( sprintf ( 'Submitted: %d. Original: %d. User can submit %d unmatched transactions.' , $submittedTrCount , $originalTrCount , $maxUnmatched ));
2023-06-03 14:17:49 -05:00
if ( $unmatchedIds > $maxUnmatched ) {
2023-10-29 00:31:13 -05:00
app ( 'log' ) -> warning ( sprintf ( 'Too many unmatched transactions (%d).' , $unmatchedIds ));
2024-02-22 13:11:09 -06:00
$validator -> errors () -> add ( 'transactions.0.id' , ( string ) trans ( 'validation.too_many_unmatched' ));
2023-12-20 12:35:52 -06:00
2023-06-03 14:17:49 -05:00
return ;
}
2023-10-29 00:33:43 -05:00
app ( 'log' ) -> debug ( 'Done with ID validation.' );
2023-06-03 14:17:49 -05:00
}
2018-07-22 13:32:02 -05:00
}