2018-02-18 12:55:35 -06:00
< ? php
2018-05-11 03:08:34 -05:00
2018-02-18 12:55:35 -06:00
/**
* AccountFactory . php
2020-02-16 07:00:57 -06:00
* Copyright ( c ) 2019 james @ firefly - iii . org
2018-02-18 12:55:35 -06:00
*
2019-10-01 23:37:26 -05:00
* This file is part of Firefly III ( https :// github . com / firefly - iii ) .
2018-02-18 12:55:35 -06: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-02-18 12:55:35 -06:00
*
2019-10-01 23:37:26 -05:00
* This program is distributed in the hope that it will be useful ,
2018-02-18 12:55:35 -06: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-02-18 12:55:35 -06: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-02-18 12:55:35 -06:00
*/
2018-05-11 03:08:34 -05:00
declare ( strict_types = 1 );
2018-02-18 12:55:35 -06:00
namespace FireflyIII\Factory ;
2018-07-06 12:06:08 -05:00
use FireflyIII\Exceptions\FireflyException ;
2018-02-18 12:55:35 -06:00
use FireflyIII\Models\Account ;
use FireflyIII\Models\AccountType ;
2019-06-16 06:15:32 -05:00
use FireflyIII\Repositories\Account\AccountRepositoryInterface ;
2018-02-21 14:06:59 -06:00
use FireflyIII\Services\Internal\Support\AccountServiceTrait ;
2020-01-01 07:27:43 -06:00
use FireflyIII\Services\Internal\Support\LocationServiceTrait ;
2018-02-18 12:55:35 -06:00
use FireflyIII\User ;
2018-08-04 10:30:47 -05:00
use Log ;
2018-02-18 12:55:35 -06:00
/**
2018-02-19 12:44:46 -06:00
* Factory to create or return accounts .
*
2018-02-18 12:55:35 -06:00
* Class AccountFactory
*/
class AccountFactory
{
2020-01-01 07:27:43 -06:00
use AccountServiceTrait , LocationServiceTrait ;
2019-06-22 03:25:34 -05:00
2020-07-31 22:32:38 -05:00
protected AccountRepositoryInterface $accountRepository ;
protected array $validAssetFields ;
protected array $validCCFields ;
protected array $validFields ;
private array $canHaveVirtual ;
private User $user ;
2019-08-24 01:22:46 -05:00
2018-09-06 05:29:32 -05:00
/**
2018-12-21 09:38:10 -06:00
* AccountFactory constructor .
2019-02-13 10:38:41 -06:00
*
2018-12-21 09:38:10 -06:00
* @ codeCoverageIgnore
2018-09-06 05:29:32 -05:00
*/
public function __construct ()
{
2019-06-16 06:15:32 -05:00
$this -> canHaveVirtual = [ AccountType :: ASSET , AccountType :: DEBT , AccountType :: LOAN , AccountType :: MORTGAGE , AccountType :: CREDITCARD ];
$this -> accountRepository = app ( AccountRepositoryInterface :: class );
2020-07-24 09:41:58 -05:00
$this -> validAssetFields = [ 'account_role' , 'account_number' , 'currency_id' , 'BIC' , 'include_net_worth' ];
$this -> validCCFields = [ 'account_role' , 'cc_monthly_payment_date' , 'cc_type' , 'account_number' , 'currency_id' , 'BIC' , 'include_net_worth' ];
$this -> validFields = [ 'account_number' , 'currency_id' , 'BIC' , 'interest' , 'interest_period' , 'include_net_worth' ];
2018-09-06 05:29:32 -05:00
}
2018-02-18 12:55:35 -06:00
/**
* @ param array $data
*
2020-03-17 08:57:04 -05:00
* @ return Account
2020-07-31 22:32:38 -05:00
* @ throws FireflyException
2018-02-18 12:55:35 -06:00
*/
public function create ( array $data ) : Account
{
2020-08-01 00:55:55 -05:00
$type = $this -> getAccountType ( $data [ 'account_type_id' ] ? ? null , $data [ 'account_type' ] ? ? null );
2018-07-06 12:06:08 -05:00
if ( null === $type ) {
2020-08-01 00:55:55 -05:00
throw new FireflyException ( sprintf ( 'AccountFactory::create() was unable to find account type #%d ("%s").' , $data [ 'account_type_id' ] ? ? null , $data [ 'account_type' ] ? ? null ));
2018-07-06 12:06:08 -05:00
}
2018-02-21 14:06:59 -06:00
2019-06-16 06:15:32 -05:00
$data [ 'iban' ] = $this -> filterIban ( $data [ 'iban' ] ? ? null );
2018-02-21 14:06:59 -06:00
// account may exist already:
2019-03-17 11:05:16 -05:00
Log :: debug ( 'Data array is as follows' , $data );
2018-07-06 12:06:08 -05:00
$return = $this -> find ( $data [ 'name' ], $type -> type );
2018-02-21 14:06:59 -06:00
2018-07-06 12:06:08 -05:00
if ( null === $return ) {
// create it:
2020-07-31 22:32:38 -05:00
$databaseData = [ 'user_id' => $this -> user -> id , 'account_type_id' => $type -> id , 'name' => $data [ 'name' ], 'order' => $data [ 'order' ] ? ? 0 , 'virtual_balance' => $data [ 'virtual_balance' ] ? ? null , 'active' => true === $data [ 'active' ], 'iban' => $data [ 'iban' ],];
$currency = $this -> getCurrency (( int )( $data [ 'currency_id' ] ? ? null ), ( string )( $data [ 'currency_code' ] ? ? null ));
2018-12-21 09:38:10 -06:00
unset ( $data [ 'currency_code' ]);
$data [ 'currency_id' ] = $currency -> id ;
2019-06-16 06:15:32 -05:00
2018-08-04 10:30:47 -05:00
// remove virtual balance when not an asset account or a liability
2019-06-16 06:15:32 -05:00
if ( ! in_array ( $type -> type , $this -> canHaveVirtual , true )) {
2020-04-13 00:57:32 -05:00
$databaseData [ 'virtual_balance' ] = null ;
2018-07-06 12:06:08 -05:00
}
2018-02-21 14:06:59 -06:00
2018-07-06 12:06:08 -05:00
// fix virtual balance when it's empty
2020-07-31 22:32:38 -05:00
if ( '' === ( string ) $databaseData [ 'virtual_balance' ]) {
2020-04-13 00:57:32 -05:00
$databaseData [ 'virtual_balance' ] = null ;
2018-07-06 12:06:08 -05:00
}
2018-04-03 12:15:06 -05:00
2018-07-06 12:06:08 -05:00
$return = Account :: create ( $databaseData );
$this -> updateMetaData ( $return , $data );
2018-02-21 14:06:59 -06:00
2019-06-16 06:15:32 -05:00
// if it can have a virtual balance, it can also have an opening balance.
if ( in_array ( $type -> type , $this -> canHaveVirtual , true )) {
if ( $this -> validOBData ( $data )) {
$this -> updateOBGroup ( $return , $data );
2018-07-06 12:06:08 -05:00
}
2019-06-16 06:15:32 -05:00
if ( ! $this -> validOBData ( $data )) {
$this -> deleteOBGroup ( $return );
2018-07-06 12:06:08 -05:00
}
}
$this -> updateNote ( $return , $data [ 'notes' ] ? ? '' );
2019-12-28 12:49:33 -06:00
// store location
2020-01-01 07:27:43 -06:00
$this -> storeNewLocation ( $return , $data );
2018-02-21 14:06:59 -06:00
}
2018-07-06 12:06:08 -05:00
return $return ;
2018-02-21 14:06:59 -06:00
}
/**
* @ param string $accountName
* @ param string $accountType
*
* @ return Account | null
*/
public function find ( string $accountName , string $accountType ) : ? Account
{
2019-06-16 06:15:32 -05:00
$type = AccountType :: whereType ( $accountType ) -> first ();
2018-02-21 14:06:59 -06:00
2019-06-16 06:15:32 -05:00
return $this -> user -> accounts () -> where ( 'account_type_id' , $type -> id ) -> where ( 'name' , $accountName ) -> first ();
2018-02-18 12:55:35 -06:00
}
/**
* @ param string $accountName
* @ param string $accountType
*
2020-03-17 08:57:04 -05:00
* @ return Account
2020-07-31 22:32:38 -05:00
* @ throws FireflyException
2018-02-18 12:55:35 -06:00
*/
public function findOrCreate ( string $accountName , string $accountType ) : Account
{
2018-09-26 23:26:03 -05:00
Log :: debug ( sprintf ( 'Searching for "%s" of type "%s"' , $accountName , $accountType ));
2019-06-16 06:15:32 -05:00
/** @var AccountType $type */
$type = AccountType :: whereType ( $accountType ) -> first ();
2020-07-31 22:32:38 -05:00
$return = $this -> user -> accounts -> where ( 'account_type_id' , $type -> id ) -> where ( 'name' , $accountName ) -> first ();
2019-06-16 06:15:32 -05:00
2018-07-06 12:06:08 -05:00
if ( null === $return ) {
2018-09-26 23:26:03 -05:00
Log :: debug ( 'Found nothing. Will create a new one.' );
2020-07-31 22:32:38 -05:00
$return = $this -> create ([ 'user_id' => $this -> user -> id , 'name' => $accountName , 'account_type_id' => $type -> id , 'account_type' => null , 'virtual_balance' => '0' , 'iban' => null , 'active' => true ,]);
2018-07-06 12:06:08 -05:00
}
2018-02-18 12:55:35 -06:00
2018-07-06 12:06:08 -05:00
return $return ;
2018-02-18 12:55:35 -06:00
}
/**
* @ param User $user
*/
public function setUser ( User $user ) : void
{
$this -> user = $user ;
}
2018-02-21 14:06:59 -06:00
/**
2020-03-17 08:57:04 -05:00
* @ param int | null $accountTypeId
2018-02-21 14:06:59 -06:00
* @ param null | string $accountType
*
* @ return AccountType | null
*/
protected function getAccountType ( ? int $accountTypeId , ? string $accountType ) : ? AccountType
{
2020-07-31 22:32:38 -05:00
$accountTypeId = ( int ) $accountTypeId ;
2018-07-06 12:06:08 -05:00
$result = null ;
2018-02-21 14:06:59 -06:00
if ( $accountTypeId > 0 ) {
2018-07-06 12:06:08 -05:00
$result = AccountType :: find ( $accountTypeId );
2018-02-21 14:06:59 -06:00
}
2018-07-06 12:06:08 -05:00
if ( null === $result ) {
2018-08-04 10:30:47 -05:00
Log :: debug ( sprintf ( 'No account type found by ID, continue search for "%s".' , $accountType ));
/** @var array $types */
$types = config ( 'firefly.accountTypeByIdentifier.' . $accountType ) ? ? [];
2019-05-30 05:31:19 -05:00
if ( count ( $types ) > 0 ) {
Log :: debug ( sprintf ( '%d accounts in list from config' , count ( $types )), $types );
2018-08-05 13:42:45 -05:00
$result = AccountType :: whereIn ( 'type' , $types ) -> first ();
2018-08-04 10:30:47 -05:00
}
2018-07-06 12:06:08 -05:00
if ( null === $result && null !== $accountType ) {
// try as full name:
$result = AccountType :: whereType ( $accountType ) -> first ();
}
2018-03-24 12:55:02 -05:00
}
2019-03-17 11:05:16 -05:00
if ( null === $result ) {
Log :: warning ( sprintf ( 'Found NO account type based on %d and "%s"' , $accountTypeId , $accountType ));
}
if ( null !== $result ) {
Log :: debug ( sprintf ( 'Found account type based on %d and "%s": "%s"' , $accountTypeId , $accountType , $result -> type ));
}
2018-02-21 14:06:59 -06:00
2018-03-24 12:55:02 -05:00
return $result ;
2018-02-21 14:06:59 -06:00
}
2019-06-16 06:15:32 -05:00
2018-03-05 12:35:58 -06:00
}