2022-08-12 05:41:55 +02:00
< ? php
/**
* Credit Ninja ( https :// invoiceninja . com ) .
*
* @ link https :// github . com / invoiceninja / invoiceninja source repository
*
* @ copyright Copyright ( c ) 2022. Credit Ninja LLC ( https :// invoiceninja . com )
*
* @ license https :// www . elastic . co / licensing / elastic - license
*/
namespace App\Jobs\Bank ;
2023-12-01 14:30:33 +01:00
use App\Helpers\Bank\Nordigen\Nordigen ;
2022-08-12 07:25:18 +02:00
use App\Libraries\MultiDB ;
2023-12-01 14:30:33 +01:00
use App\Models\Account ;
2022-08-12 05:41:55 +02:00
use App\Models\BankIntegration ;
use App\Models\BankTransaction ;
2022-09-14 11:12:50 +02:00
use App\Models\Company ;
2023-12-11 09:15:41 +01:00
use App\Notifications\Ninja\GenericNinjaAdminNotification ;
2022-11-11 05:28:49 +01:00
use App\Services\Bank\BankMatchingService ;
2022-08-12 05:41:55 +02:00
use Illuminate\Bus\Queueable ;
use Illuminate\Contracts\Queue\ShouldQueue ;
use Illuminate\Foundation\Bus\Dispatchable ;
use Illuminate\Queue\InteractsWithQueue ;
use Illuminate\Queue\SerializesModels ;
2023-12-12 07:52:53 +01:00
use Log ;
2022-08-12 05:41:55 +02:00
2023-12-01 14:30:33 +01:00
class ProcessBankTransactionsNordigen implements ShouldQueue
2022-08-12 05:41:55 +02:00
{
use Dispatchable , InteractsWithQueue , Queueable , SerializesModels ;
private BankIntegration $bank_integration ;
2022-09-14 07:35:51 +02:00
private ? string $from_date ;
2022-08-12 05:41:55 +02:00
2022-09-14 11:12:50 +02:00
public Company $company ;
2023-12-11 09:15:41 +01:00
public Nordigen $nordigen ;
public $nordigen_account ;
2022-09-14 11:12:50 +02:00
2022-08-12 05:41:55 +02:00
/**
* Create a new job instance .
*/
2023-12-13 15:37:19 +01:00
public function __construct ( BankIntegration $bank_integration )
2022-08-12 05:41:55 +02:00
{
$this -> bank_integration = $bank_integration ;
2023-12-16 14:33:09 +01:00
$this -> from_date = $bank_integration -> from_date ? : now () -> subDays ( 90 );
2022-09-14 11:12:50 +02:00
$this -> company = $this -> bank_integration -> company ;
2023-12-12 07:08:40 +01:00
}
/**
* Execute the job .
*
*
* @ return void
*/
public function handle ()
{
2022-09-14 11:12:50 +02:00
2023-12-01 14:30:33 +01:00
if ( $this -> bank_integration -> integration_type != BankIntegration :: INTEGRATION_TYPE_NORDIGEN )
throw new \Exception ( " Invalid BankIntegration Type " );
2023-12-13 15:37:19 +01:00
if ( ! ( config ( 'ninja.nordigen.secret_id' ) && config ( 'ninja.nordigen.secret_key' )))
2023-12-13 15:38:37 +01:00
throw new \Exception ( " Missing credentials for bank_integration service nordigen " );
2023-12-11 09:15:41 +01:00
2023-12-13 15:37:19 +01:00
$this -> nordigen = new Nordigen ();
2022-09-14 01:33:49 +02:00
set_time_limit ( 0 );
2022-08-12 05:41:55 +02:00
2023-12-18 15:58:16 +01:00
nlog ( " Nordigen: Processing transactions for account: { $this -> bank_integration -> account -> key } " );
2023-12-11 09:15:41 +01:00
// UPDATE ACCOUNT
try {
$this -> updateAccount ();
} catch ( \Exception $e ) {
2023-12-18 15:58:16 +01:00
nlog ( " Nordigen: { $this -> bank_integration -> nordigen_account_id } - exited abnormally => " . $e -> getMessage ());
2023-12-11 09:15:41 +01:00
$content = [
2023-12-18 15:58:16 +01:00
" Processing transactions for account: { $this -> bank_integration -> nordigen_account_id } failed " ,
2023-12-11 09:15:41 +01:00
" Exception Details => " ,
$e -> getMessage (),
];
$this -> bank_integration -> company -> notification ( new GenericNinjaAdminNotification ( $content )) -> ninja ();
2023-12-13 16:18:18 +01:00
throw $e ;
2023-12-11 09:15:41 +01:00
}
if ( ! $this -> nordigen_account )
return ;
// UPDATE TRANSACTIONS
2023-12-16 14:33:09 +01:00
try {
$this -> processTransactions ();
} catch ( \Exception $e ) {
// reset from_date in case this was the error (self-heal) and perform a max sync of data we can fetch (next-time) @todo we should analyze the error for this
$this -> bank_integration -> from_date = now () -> subDays ( 90 );
$this -> bank_integration -> save ();
2023-12-11 09:15:41 +01:00
2023-12-18 15:58:16 +01:00
nlog ( " Nordigen: { $this -> bank_integration -> nordigen_account_id } - exited abnormally => " . $e -> getMessage ());
2023-12-11 09:15:41 +01:00
2023-12-16 14:33:09 +01:00
$content = [
2023-12-18 15:58:16 +01:00
" Processing transactions for account: { $this -> bank_integration -> nordigen_account_id } failed " ,
2023-12-16 14:33:09 +01:00
" Exception Details => " ,
$e -> getMessage (),
];
2023-12-13 16:18:18 +01:00
2023-12-16 14:33:09 +01:00
$this -> bank_integration -> company -> notification ( new GenericNinjaAdminNotification ( $content )) -> ninja ();
2022-09-14 01:33:49 +02:00
2023-12-16 14:33:09 +01:00
throw $e ;
2022-08-17 08:37:05 +02:00
}
2023-12-16 14:33:09 +01:00
// Perform Matching
2022-11-11 05:28:49 +01:00
BankMatchingService :: dispatch ( $this -> company -> id , $this -> company -> db );
2022-09-14 11:12:50 +02:00
2022-08-17 08:37:05 +02:00
}
2023-12-11 09:15:41 +01:00
private function updateAccount ()
2022-08-17 08:37:05 +02:00
{
2023-12-11 09:23:35 +01:00
if ( ! $this -> nordigen -> isAccountActive ( $this -> bank_integration -> nordigen_account_id )) {
2023-12-01 14:30:33 +01:00
$this -> bank_integration -> disabled_upstream = true ;
$this -> bank_integration -> save ();
$this -> stop_loop = false ;
2023-12-18 15:58:16 +01:00
Log :: info ( " Nordigen: account inactive: " . $this -> bank_integration -> nordigen_account_id );
2023-12-06 08:27:18 +01:00
// @turbo124 @todo send email for expired account
2023-12-01 14:30:33 +01:00
return ;
2022-11-04 02:55:17 +01:00
}
2023-12-11 09:23:35 +01:00
$this -> nordigen_account = $this -> nordigen -> getAccount ( $this -> bank_integration -> nordigen_account_id );
2023-12-11 09:15:41 +01:00
2023-12-12 07:52:53 +01:00
$this -> bank_integration -> disabled_upstream = false ;
2023-12-11 09:15:41 +01:00
$this -> bank_integration -> bank_account_status = $this -> nordigen_account [ 'account_status' ];
$this -> bank_integration -> balance = $this -> nordigen_account [ 'current_balance' ];
$this -> bank_integration -> save ();
}
private function processTransactions ()
{
2022-09-14 08:57:47 +02:00
//Get transaction count object
2023-12-11 09:23:35 +01:00
$transactions = $this -> nordigen -> getTransactions ( $this -> bank_integration -> nordigen_account_id , $this -> from_date );
2022-09-14 00:54:59 +02:00
2022-09-14 08:57:47 +02:00
//if no transactions, update the from_date and move on
2023-12-01 14:30:33 +01:00
if ( count ( $transactions ) == 0 ) {
2022-09-14 08:57:47 +02:00
2023-12-11 09:15:41 +01:00
$this -> bank_integration -> from_date = now () -> subDays ( 5 );
2022-11-04 02:55:17 +01:00
$this -> bank_integration -> disabled_upstream = false ;
2022-09-14 08:57:47 +02:00
$this -> bank_integration -> save ();
2023-12-16 14:33:09 +01:00
2022-09-14 07:52:54 +02:00
return ;
2022-09-14 08:57:47 +02:00
}
2022-09-14 07:52:54 +02:00
2022-09-14 08:57:47 +02:00
//Harvest the company
2022-09-14 01:33:49 +02:00
2022-09-14 11:14:00 +02:00
MultiDB :: setDb ( $this -> company -> db );
2022-09-14 01:33:49 +02:00
2022-09-14 08:57:47 +02:00
/*Get the user */
2022-09-14 11:14:00 +02:00
$user_id = $this -> company -> owner () -> id ;
2023-12-01 14:30:33 +01:00
2022-09-14 08:57:47 +02:00
/* Unguard the model to perform batch inserts */
2022-08-17 03:52:16 +02:00
BankTransaction :: unguard ();
2022-09-14 08:57:47 +02:00
$now = now ();
2022-08-12 05:41:55 +02:00
2023-12-01 14:30:33 +01:00
foreach ( $transactions as $transaction ) {
2023-12-13 16:18:18 +01:00
if ( BankTransaction :: where ( 'transaction_id' , $transaction [ 'transaction_id' ]) -> where ( 'company_id' , $this -> company -> id ) -> where ( 'bank_integration_id' , $this -> bank_integration -> id ) -> withTrashed () -> exists ())
2022-08-12 05:41:55 +02:00
continue ;
2022-08-17 05:43:16 +02:00
//this should be much faster to insert than using ::create()
2023-12-11 09:15:41 +01:00
\DB :: table ( 'bank_transactions' ) -> insert (
2023-12-01 14:30:33 +01:00
array_merge ( $transaction , [
2022-09-14 11:14:00 +02:00
'company_id' => $this -> company -> id ,
2022-08-17 03:52:16 +02:00
'user_id' => $user_id ,
'bank_integration_id' => $this -> bank_integration -> id ,
2022-09-14 08:57:47 +02:00
'created_at' => $now ,
'updated_at' => $now ,
2022-08-17 03:52:16 +02:00
])
2022-08-17 05:43:16 +02:00
);
2022-08-12 05:41:55 +02:00
}
2023-12-11 09:15:41 +01:00
$this -> bank_integration -> from_date = now () -> subDays ( 5 );
$this -> bank_integration -> save ();
2022-09-14 01:40:08 +02:00
2022-08-12 05:41:55 +02:00
}
2023-12-01 14:30:33 +01:00
}