mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Refactor for bank transactions
This commit is contained in:
parent
d14df7ef2d
commit
3865d7193e
@ -132,7 +132,7 @@ class IncomeTransformer implements BankRevenueInterface
|
||||
|
||||
public function transformTransaction($transaction)
|
||||
{
|
||||
nlog($transaction);
|
||||
|
||||
return [
|
||||
'transaction_id' => $transaction->id,
|
||||
'amount' => $transaction->amount->amount,
|
||||
@ -143,7 +143,7 @@ class IncomeTransformer implements BankRevenueInterface
|
||||
'date' => $transaction->date,
|
||||
'bank_account_id' => $transaction->accountId,
|
||||
'description' => $transaction->description->original,
|
||||
'base_type' => $transaction->baseType,
|
||||
'base_type' => property_exists($transaction, 'baseType') ? $transaction->baseType : '',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ use App\Models\Payment;
|
||||
use App\Services\Bank\BankService;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
@ -39,7 +40,7 @@ use Illuminate\Support\Carbon;
|
||||
|
||||
class MatchBankTransactions implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, GeneratesCounter;
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, GeneratesCounter, MakesHash;
|
||||
|
||||
private int $company_id;
|
||||
|
||||
@ -54,6 +55,11 @@ class MatchBankTransactions implements ShouldQueue
|
||||
private BankTransaction $bt;
|
||||
|
||||
private $categories;
|
||||
|
||||
private float $available_balance = 0;
|
||||
|
||||
private array $attachable_invoices = [];
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
@ -75,7 +81,6 @@ class MatchBankTransactions implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
nlog("match bank transactions");
|
||||
|
||||
MultiDB::setDb($this->db);
|
||||
|
||||
@ -88,11 +93,9 @@ nlog("match bank transactions");
|
||||
if($_categories)
|
||||
$this->categories = collect($_categories->transactionCategory);
|
||||
|
||||
nlog($this->input);
|
||||
|
||||
foreach($this->input as $match)
|
||||
{
|
||||
if(array_key_exists('invoice_id', $match) && strlen($match['invoice_id']) > 1)
|
||||
if(array_key_exists('invoice_ids', $match) && strlen($match['invoice_ids']) > 1)
|
||||
$this->matchInvoicePayment($match);
|
||||
else
|
||||
$this->matchExpense($match);
|
||||
@ -100,24 +103,54 @@ nlog($this->input);
|
||||
|
||||
}
|
||||
|
||||
private function getInvoices(string $invoice_hashed_ids)
|
||||
{
|
||||
$collection = collect();
|
||||
|
||||
$invoices = explode(",", $invoice_hashed_ids);
|
||||
|
||||
if(count($invoices) >= 1)
|
||||
{
|
||||
|
||||
foreach($invoices as $invoice){
|
||||
|
||||
if(is_string($invoice) && strlen($invoice) > 1)
|
||||
$collection->push($this->decodePrimaryKey($invoice));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
private function checkPayable($invoices) :bool
|
||||
{
|
||||
|
||||
foreach($invoices as $invoice){
|
||||
|
||||
if(!$invoice->isPayable())
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private function matchInvoicePayment(array $match) :void
|
||||
{
|
||||
$this->bt = BankTransaction::find($match['id']);
|
||||
|
||||
nlog($this->bt->toArray());
|
||||
|
||||
$_invoice = Invoice::withTrashed()->find($match['invoice_id']);
|
||||
|
||||
nlog($_invoice->toArray());
|
||||
$_invoices = Invoice::withTrashed()->find($this->getInvoices($match['invoice_ids']));
|
||||
|
||||
if(array_key_exists('amount', $match) && $match['amount'] > 0)
|
||||
$amount = $match['amount'];
|
||||
else
|
||||
$amount = $this->bt->amount;
|
||||
|
||||
if($_invoice && $_invoice->isPayable()){
|
||||
if($_invoices && $this->checkPayable($_invoices)){
|
||||
|
||||
$this->createPayment($match['invoice_id'], $amount);
|
||||
$this->createPayment($_invoices, $amount);
|
||||
|
||||
}
|
||||
|
||||
@ -139,21 +172,41 @@ nlog($_invoice->toArray());
|
||||
|
||||
}
|
||||
|
||||
private function createPayment(int $invoice_id, float $amount) :void
|
||||
private function createPayment($invoices, float $amount) :void
|
||||
{
|
||||
nlog("creating payment");
|
||||
$this->available_balance = $amount;
|
||||
|
||||
\DB::connection(config('database.default'))->transaction(function () use($invoice_id, $amount) {
|
||||
\DB::connection(config('database.default'))->transaction(function () use($invoices) {
|
||||
|
||||
$this->invoice = Invoice::withTrashed()->where('id', $invoice_id)->lockForUpdate()->first();
|
||||
$invoices->each(function ($invoice) use ($invoices){
|
||||
|
||||
$this->invoice
|
||||
->service()
|
||||
->setExchangeRate()
|
||||
->updateBalance($amount * -1)
|
||||
->updatePaidToDate($amount)
|
||||
->setCalculatedStatus()
|
||||
->save();
|
||||
$this->invoice = Invoice::withTrashed()->where('id', $invoice->id)->lockForUpdate()->first();
|
||||
|
||||
if($invoices->count() == 1){
|
||||
$_amount = $this->available_balance;
|
||||
}
|
||||
elseif($invoices->count() > 1 && floatval($this->invoice->balance) < floatval($this->available_balance) && $this->available_balance > 0)
|
||||
{
|
||||
$_amount = $this->invoice->balance;
|
||||
$this->available_balance = $this->available_balance - $this->invoice->balance;
|
||||
}
|
||||
elseif($invoices->count() > 1 && floatval($this->invoice->balance) > floatval($this->available_balance) && $this->available_balance > 0)
|
||||
{
|
||||
$_amount = $this->available_balance;
|
||||
$this->available_balance = 0;
|
||||
}
|
||||
|
||||
$this->attachable_invoices[] = ['id' => $this->invoice->id, 'amount' => $_amount];
|
||||
|
||||
$this->invoice
|
||||
->service()
|
||||
->setExchangeRate()
|
||||
->updateBalance($_amount * -1)
|
||||
->updatePaidToDate($_amount)
|
||||
->setCalculatedStatus()
|
||||
->save();
|
||||
|
||||
});
|
||||
|
||||
}, 1);
|
||||
|
||||
@ -164,7 +217,7 @@ nlog("creating payment");
|
||||
$payment->applied = $amount;
|
||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||
$payment->client_id = $this->invoice->client_id;
|
||||
$payment->transaction_reference = $this->bt->transaction_id;
|
||||
$payment->transaction_reference = $this->bt->description;
|
||||
$payment->transaction_id = $this->bt->transaction_id;
|
||||
$payment->currency_id = $this->harvestCurrencyId();
|
||||
$payment->is_manual = false;
|
||||
@ -176,8 +229,6 @@ nlog("creating payment");
|
||||
|
||||
$payment->saveQuietly();
|
||||
|
||||
nlog($payment->toArray());
|
||||
|
||||
$payment->service()->applyNumber()->save();
|
||||
|
||||
if($payment->client->getSetting('send_email_on_mark_paid'))
|
||||
@ -186,9 +237,14 @@ nlog($payment->toArray());
|
||||
$this->setExchangeRate($payment);
|
||||
|
||||
/* Create a payment relationship to the invoice entity */
|
||||
$payment->invoices()->attach($this->invoice->id, [
|
||||
'amount' => $amount,
|
||||
]);
|
||||
foreach($this->attachable_invoices as $attachable_invoice)
|
||||
{
|
||||
|
||||
$payment->invoices()->attach($attachable_invoice['id'], [
|
||||
'amount' => $attachable_invoice['amount'],
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
event('eloquent.created: App\Models\Payment', $payment);
|
||||
|
||||
|
@ -33,6 +33,8 @@ class BankService implements ShouldQueue
|
||||
|
||||
private $invoices;
|
||||
|
||||
public $deleteWhenMissingModels = true;
|
||||
|
||||
public function __construct($company_id, $db)
|
||||
{
|
||||
$this->company_id = $company_id;
|
||||
@ -58,8 +60,7 @@ class BankService implements ShouldQueue
|
||||
{
|
||||
|
||||
BankTransaction::where('company_id', $this->company->id)
|
||||
->where('is_matched', false)
|
||||
->where('provisional_match', false)
|
||||
->where('status_id', BankTransaction::STATUS_UNMATCHED)
|
||||
->cursor()
|
||||
->each(function ($bt){
|
||||
|
||||
@ -71,8 +72,8 @@ class BankService implements ShouldQueue
|
||||
|
||||
if($invoice)
|
||||
{
|
||||
$bt->invoice_id = $invoice->id;
|
||||
$bt->provisional_match = true;
|
||||
$bt->invoice_ids = $invoice->hashed_id;
|
||||
$bt->status_id = BankTransaction::STATUS_MATCHED;
|
||||
$bt->save();
|
||||
}
|
||||
|
||||
|
@ -121,13 +121,13 @@ class YodleeApiTest extends TestCase
|
||||
$data = [
|
||||
[
|
||||
'id' => $bt->id,
|
||||
'invoice_id' => $invoice->id
|
||||
'invoice_ids' => $invoice->hashed_id
|
||||
]
|
||||
];
|
||||
|
||||
MatchBankTransactions::dispatchSync($this->company->id, $this->company->db, $data);
|
||||
|
||||
$payment = Payment::where('transaction_reference', '123456')->first();
|
||||
$payment = Payment::where('transaction_reference', $bt->description)->first();
|
||||
|
||||
$this->assertNotNull($payment);
|
||||
|
||||
@ -202,11 +202,11 @@ class YodleeApiTest extends TestCase
|
||||
|
||||
BankService::dispatchSync($this->company->id, $this->company->db);
|
||||
|
||||
$bt = BankTransaction::where('invoice_id', $this->invoice->id)->first();
|
||||
$bt = BankTransaction::where('invoice_ids', $this->invoice->hashed_id)->first();
|
||||
|
||||
$this->assertNotNull($bt);
|
||||
|
||||
$this->assertEquals(1, $bt->provisional_match);
|
||||
$this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id);
|
||||
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,7 @@ class YodleeBankTransactionTest extends TestCase
|
||||
$invoices = Invoice::where('company_id', $this->company->id)->get();
|
||||
|
||||
BankTransaction::where('company_id', $this->company->id)
|
||||
->where('is_matched', false)
|
||||
->where('provisional_match', false)
|
||||
->where('status_id', BankTransaction::STATUS_UNMATCHED)
|
||||
->cursor()
|
||||
->each(function ($bt) use($invoices){
|
||||
|
||||
@ -67,15 +66,15 @@ class YodleeBankTransactionTest extends TestCase
|
||||
|
||||
if($invoice)
|
||||
{
|
||||
$bt->invoice_id = $invoice->id;
|
||||
$bt->provisional_match = $invoice->id;
|
||||
$bt->invoice_ids = $invoice->hashed_id;
|
||||
$bt->status_id = BankTransaction::STATUS_MATCHED;
|
||||
$bt->save();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
$this->assertTrue(BankTransaction::where('invoice_id', $this->invoice->id)->exists());
|
||||
$this->assertTrue(BankTransaction::where('invoice_ids', $this->invoice->hashed_id)->exists());
|
||||
|
||||
}
|
||||
|
||||
@ -96,8 +95,7 @@ class YodleeBankTransactionTest extends TestCase
|
||||
$invoices = Invoice::where('company_id', $this->company->id)->get();
|
||||
|
||||
BankTransaction::where('company_id', $this->company->id)
|
||||
->where('is_matched', false)
|
||||
->where('provisional_match', false)
|
||||
->where('status_id', BankTransaction::STATUS_UNMATCHED)
|
||||
->cursor()
|
||||
->each(function ($bt) use($invoices){
|
||||
|
||||
@ -109,15 +107,15 @@ class YodleeBankTransactionTest extends TestCase
|
||||
|
||||
if($invoice)
|
||||
{
|
||||
$bt->invoice_id = $invoice->id;
|
||||
$bt->provisional_match = $invoice->id;
|
||||
$bt->invoice_ids = $invoice->hashed_id;
|
||||
$bt->status_id = BankTransaction::STATUS_MATCHED;
|
||||
$bt->save();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
$this->assertTrue(BankTransaction::where('invoice_id', $this->invoice->id)->exists());
|
||||
$this->assertTrue(BankTransaction::where('invoice_ids', $this->invoice->hashed_id)->exists());
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user