2018-09-15 13:43:57 +02:00
< ? php
/**
* ConvertToDeposit . php
2020-02-16 13:57:05 +01:00
* Copyright ( c ) 2019 james @ firefly - iii . org
2018-09-15 13:43:57 +02:00
*
2019-10-02 06:37:26 +02:00
* This file is part of Firefly III ( https :// github . com / firefly - iii ) .
2018-09-15 13:43:57 +02:00
*
2019-10-02 06:37:26 +02: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-09-15 13:43:57 +02:00
*
2019-10-02 06:37:26 +02:00
* This program is distributed in the hope that it will be useful ,
2018-09-15 13:43:57 +02:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2019-10-02 06:37:26 +02:00
* GNU Affero General Public License for more details .
2018-09-15 13:43:57 +02:00
*
2019-10-02 06:37:26 +02: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-09-15 13:43:57 +02:00
*/
declare ( strict_types = 1 );
namespace FireflyIII\TransactionRules\Actions ;
2021-04-05 22:12:57 +02:00
2020-08-23 07:42:14 +02:00
use DB ;
2022-10-02 06:23:31 +02:00
use FireflyIII\Events\TriggeredAuditLog ;
2019-08-17 10:47:29 +02:00
use FireflyIII\Exceptions\FireflyException ;
2018-09-15 13:43:57 +02:00
use FireflyIII\Factory\AccountFactory ;
use FireflyIII\Models\AccountType ;
use FireflyIII\Models\RuleAction ;
2022-06-25 14:36:53 +02:00
use FireflyIII\Models\TransactionJournal ;
2018-09-15 13:43:57 +02:00
use FireflyIII\Models\TransactionType ;
2023-03-25 11:34:29 +01:00
use FireflyIII\Repositories\Account\AccountRepositoryInterface ;
2020-08-23 07:42:14 +02:00
use FireflyIII\User ;
2023-02-22 18:14:14 +01:00
use JsonException ;
2018-09-15 13:43:57 +02:00
use Log ;
/**
*
* Class ConvertToDeposit
*/
class ConvertToDeposit implements ActionInterface
{
2020-08-23 07:42:14 +02:00
private RuleAction $action ;
2018-09-15 13:43:57 +02:00
/**
* TriggerInterface constructor .
*
2022-12-29 19:42:26 +01:00
* @ param RuleAction $action
2018-09-15 13:43:57 +02:00
*/
public function __construct ( RuleAction $action )
{
$this -> action = $action ;
}
2020-08-23 07:42:14 +02:00
/**
2021-03-23 06:42:26 +01:00
* @ inheritDoc
2020-08-23 07:42:14 +02:00
* @ throws FireflyException
2023-03-25 13:42:26 +01:00
* @ throws JsonException
2020-08-23 07:42:14 +02:00
*/
2021-03-23 06:42:26 +01:00
public function actOnArray ( array $journal ) : bool
2020-08-23 07:42:14 +02:00
{
2022-06-25 14:36:53 +02:00
$groupCount = TransactionJournal :: where ( 'transaction_group_id' , $journal [ 'transaction_group_id' ]) -> count ();
2022-10-02 06:23:31 +02:00
if ( $groupCount > 1 ) {
2022-06-25 14:36:53 +02:00
Log :: error ( sprintf ( 'Group #%d has more than one transaction in it, cannot convert to deposit.' , $journal [ 'transaction_group_id' ]));
return false ;
}
2021-03-23 06:42:26 +01:00
Log :: debug ( sprintf ( 'Convert journal #%d to deposit.' , $journal [ 'transaction_journal_id' ]));
$type = $journal [ 'transaction_type_type' ];
if ( TransactionType :: DEPOSIT === $type ) {
Log :: error ( sprintf ( 'Journal #%d is already a deposit (rule #%d).' , $journal [ 'transaction_journal_id' ], $this -> action -> rule_id ));
2020-08-23 07:42:14 +02:00
2021-03-23 06:42:26 +01:00
return false ;
}
2020-08-23 07:42:14 +02:00
2021-03-23 06:42:26 +01:00
if ( TransactionType :: WITHDRAWAL === $type ) {
Log :: debug ( 'Going to transform a withdrawal to a deposit.' );
2022-10-02 06:23:31 +02:00
$object = TransactionJournal :: where ( 'user_id' , $journal [ 'user_id' ]) -> find ( $journal [ 'transaction_journal_id' ]);
2022-10-02 14:37:50 +02:00
event ( new TriggeredAuditLog ( $this -> action -> rule , $object , 'update_transaction_type' , TransactionType :: WITHDRAWAL , TransactionType :: DEPOSIT ));
2020-08-23 07:42:14 +02:00
2021-03-23 06:42:26 +01:00
return $this -> convertWithdrawalArray ( $journal );
}
if ( TransactionType :: TRANSFER === $type ) {
2022-10-02 06:23:31 +02:00
$object = TransactionJournal :: where ( 'user_id' , $journal [ 'user_id' ]) -> find ( $journal [ 'transaction_journal_id' ]);
2022-10-02 14:37:50 +02:00
event ( new TriggeredAuditLog ( $this -> action -> rule , $object , 'update_transaction_type' , TransactionType :: TRANSFER , TransactionType :: DEPOSIT ));
2021-03-23 06:42:26 +01:00
Log :: debug ( 'Going to transform a transfer to a deposit.' );
2020-08-23 07:42:14 +02:00
2021-03-23 06:42:26 +01:00
return $this -> convertTransferArray ( $journal );
}
2020-08-23 07:42:14 +02:00
2021-03-23 06:42:26 +01:00
return false ;
2020-08-23 07:42:14 +02:00
}
/**
* Input is a withdrawal from A to B
* Is converted to a deposit from C to A .
*
2022-12-29 19:42:26 +01:00
* @ param array $journal
2020-08-23 07:42:14 +02:00
*
* @ return bool
* @ throws FireflyException
2023-02-22 18:14:14 +01:00
* @ throws JsonException
2020-08-23 07:42:14 +02:00
*/
private function convertWithdrawalArray ( array $journal ) : bool
{
$user = User :: find ( $journal [ 'user_id' ]);
// find or create revenue account.
/** @var AccountFactory $factory */
$factory = app ( AccountFactory :: class );
$factory -> setUser ( $user );
2023-03-25 11:34:29 +01:00
$repository = app ( AccountRepositoryInterface :: class );
$repository -> setUser ( $user );
2020-08-23 07:42:14 +02:00
// get the action value, or use the original destination name in case the action value is empty:
2023-03-25 11:34:29 +01:00
// this becomes a new or existing (revenue) account, which is the source of the new deposit.
2023-03-25 13:42:26 +01:00
$opposingName = '' === $this -> action -> action_value ? $journal [ 'destination_account_name' ] : $this -> action -> action_value ;
2023-03-25 11:34:29 +01:00
// we check all possible source account types if one exists:
$validTypes = config ( 'firefly.expected_source_types.source.Deposit' );
2023-03-25 13:42:26 +01:00
$opposingAccount = $repository -> findByName ( $opposingName , $validTypes );
if ( null === $opposingAccount ) {
$opposingAccount = $factory -> findOrCreate ( $opposingName , AccountType :: REVENUE );
2023-03-25 11:34:29 +01:00
}
2020-08-23 07:42:14 +02:00
2023-03-25 13:42:26 +01:00
Log :: debug ( sprintf ( 'ConvertToDeposit. Action value is "%s", new opposing name is "%s"' , $this -> action -> action_value , $journal [ 'destination_account_name' ]));
2020-08-23 07:42:14 +02:00
// update the source transaction and put in the new revenue ID.
DB :: table ( 'transactions' )
-> where ( 'transaction_journal_id' , '=' , $journal [ 'transaction_journal_id' ])
-> where ( 'amount' , '<' , 0 )
2023-03-25 13:42:26 +01:00
-> update ([ 'account_id' => $opposingAccount -> id ]);
2020-08-23 07:42:14 +02:00
// update the destination transaction and put in the original source account ID.
DB :: table ( 'transactions' )
-> where ( 'transaction_journal_id' , '=' , $journal [ 'transaction_journal_id' ])
-> where ( 'amount' , '>' , 0 )
-> update ([ 'account_id' => $journal [ 'source_account_id' ]]);
// change transaction type of journal:
$newType = TransactionType :: whereType ( TransactionType :: DEPOSIT ) -> first ();
DB :: table ( 'transaction_journals' )
-> where ( 'id' , '=' , $journal [ 'transaction_journal_id' ])
2022-08-02 05:39:04 +02:00
-> update ([ 'transaction_type_id' => $newType -> id , 'bill_id' => null ]);
2020-08-23 07:42:14 +02:00
Log :: debug ( 'Converted withdrawal to deposit.' );
return true ;
}
/**
2021-03-23 06:42:26 +01:00
* Input is a transfer from A to B .
* Output is a deposit from C to B .
2023-03-25 13:42:26 +01:00
* The source account is replaced .
2021-03-23 06:42:26 +01:00
*
2022-12-29 19:42:26 +01:00
* @ param array $journal
2021-03-23 06:42:26 +01:00
*
* @ return bool
2020-08-23 07:42:14 +02:00
* @ throws FireflyException
2023-02-22 18:14:14 +01:00
* @ throws JsonException
2020-08-23 07:42:14 +02:00
*/
2021-03-23 06:42:26 +01:00
private function convertTransferArray ( array $journal ) : bool
2020-08-23 07:42:14 +02:00
{
2021-03-23 06:42:26 +01:00
$user = User :: find ( $journal [ 'user_id' ]);
// find or create revenue account.
/** @var AccountFactory $factory */
$factory = app ( AccountFactory :: class );
$factory -> setUser ( $user );
2020-08-23 07:42:14 +02:00
2023-03-25 13:42:26 +01:00
$repository = app ( AccountRepositoryInterface :: class );
$repository -> setUser ( $user );
2021-03-23 06:42:26 +01:00
// get the action value, or use the original source name in case the action value is empty:
2023-03-25 13:42:26 +01:00
// this becomes a new or existing (revenue) account, which is the source of the new deposit.
$opposingName = '' === $this -> action -> action_value ? $journal [ 'source_account_name' ] : $this -> action -> action_value ;
// we check all possible source account types if one exists:
$validTypes = config ( 'firefly.expected_source_types.source.Deposit' );
$opposingAccount = $repository -> findByName ( $opposingName , $validTypes );
if ( null === $opposingAccount ) {
$opposingAccount = $factory -> findOrCreate ( $opposingName , AccountType :: REVENUE );
}
2020-08-23 07:42:14 +02:00
2021-03-23 06:42:26 +01:00
Log :: debug ( sprintf ( 'ConvertToDeposit. Action value is "%s", revenue name is "%s"' , $this -> action -> action_value , $journal [ 'source_account_name' ]));
2020-08-23 07:42:14 +02:00
2021-03-23 06:42:26 +01:00
// update source transaction(s) to be revenue account
DB :: table ( 'transactions' )
-> where ( 'transaction_journal_id' , '=' , $journal [ 'transaction_journal_id' ])
-> where ( 'amount' , '<' , 0 )
2023-03-25 13:42:26 +01:00
-> update ([ 'account_id' => $opposingAccount -> id ]);
2020-08-23 07:42:14 +02:00
2021-03-23 06:42:26 +01:00
// change transaction type of journal:
$newType = TransactionType :: whereType ( TransactionType :: DEPOSIT ) -> first ();
DB :: table ( 'transaction_journals' )
-> where ( 'id' , '=' , $journal [ 'transaction_journal_id' ])
2022-08-02 05:39:04 +02:00
-> update ([ 'transaction_type_id' => $newType -> id , 'bill_id' => null ]);
2021-03-23 06:42:26 +01:00
Log :: debug ( 'Converted transfer to deposit.' );
return true ;
2020-08-23 07:42:14 +02:00
}
2018-12-31 07:48:23 +01:00
}