From 376b728e68d25ceb4c8062c6f36747244446807a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 27 Aug 2024 10:38:16 +1000 Subject: [PATCH] Tests forbank processing rules --- app/Services/Bank/ProcessBankRules.php | 688 +++++++++--------- .../Feature/Bank/BankTransactionRuleTest.php | 475 +++++++++++- 2 files changed, 822 insertions(+), 341 deletions(-) diff --git a/app/Services/Bank/ProcessBankRules.php b/app/Services/Bank/ProcessBankRules.php index fa27416742..19787f2b91 100644 --- a/app/Services/Bank/ProcessBankRules.php +++ b/app/Services/Bank/ProcessBankRules.php @@ -20,13 +20,15 @@ use App\Models\Invoice; use App\Models\Payment; use App\Services\AbstractService; use App\Utils\Traits\GeneratesCounter; +use App\Utils\Traits\MakesHash; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Cache; class ProcessBankRules extends AbstractService { use GeneratesCounter; - + use MakesHash; + protected $credit_rules; protected $debit_rules; @@ -106,23 +108,23 @@ class ProcessBankRules extends AbstractService match($rule['search_key']) { '$payment.amount' => $results = [Payment::class, $this->searchPaymentResource('amount', $rule, $payments)], '$payment.transaction_reference' => $results = [Payment::class, $this->searchPaymentResource('transaction_reference', $rule, $payments)], - '$payment.custom1' => $results = [Payment::class, $this->searchPaymentResource('custom1', $rule, $payments)], - '$payment.custom2' => $results = [Payment::class, $this->searchPaymentResource('custom2', $rule, $payments)], - '$payment.custom3' => $results = [Payment::class, $this->searchPaymentResource('custom3', $rule, $payments)], - '$payment.custom4' => $results = [Payment::class, $this->searchPaymentResource('custom4', $rule, $payments)], + '$payment.custom1' => $results = [Payment::class, $this->searchPaymentResource('custom_value1', $rule, $payments)], + '$payment.custom2' => $results = [Payment::class, $this->searchPaymentResource('custom_value2', $rule, $payments)], + '$payment.custom3' => $results = [Payment::class, $this->searchPaymentResource('custom_value3', $rule, $payments)], + '$payment.custom4' => $results = [Payment::class, $this->searchPaymentResource('custom_value4', $rule, $payments)], '$invoice.amount' => $results = [Invoice::class, $this->searchInvoiceResource('amount', $rule, $invoices)], '$invoice.number' => $results = [Invoice::class, $this->searchInvoiceResource('number', $rule, $invoices)], '$invoice.po_number' => $results = [Invoice::class, $this->searchInvoiceResource('po_number', $rule, $invoices)], - '$invoice.custom1' => $results = [Invoice::class, $this->searchInvoiceResource('custom1', $rule, $invoices)], - '$invoice.custom2' => $results = [Invoice::class, $this->searchInvoiceResource('custom2', $rule, $invoices)], - '$invoice.custom3' => $results = [Invoice::class, $this->searchInvoiceResource('custom3', $rule, $invoices)], - '$invoice.custom4' => $results = [Invoice::class, $this->searchInvoiceResource('custom4', $rule, $invoices)], + '$invoice.custom1' => $results = [Invoice::class, $this->searchInvoiceResource('custom_value1', $rule, $invoices)], + '$invoice.custom2' => $results = [Invoice::class, $this->searchInvoiceResource('custom_value2', $rule, $invoices)], + '$invoice.custom3' => $results = [Invoice::class, $this->searchInvoiceResource('custom_value3', $rule, $invoices)], + '$invoice.custom4' => $results = [Invoice::class, $this->searchInvoiceResource('custom_value4', $rule, $invoices)], '$client.id_number' => $results = [Client::class, $this->searchClientResource('id_number', $rule, $invoices, $payments)], '$client.email' => $results = [Client::class, $this->searchClientResource('email', $rule, $invoices, $payments)], - '$client.custom1' => $results = [Client::class, $this->searchClientResource('custom1', $rule, $invoices, $payments)], - '$client.custom2' => $results = [Client::class, $this->searchClientResource('custom2', $rule, $invoices, $payments)], - '$client.custom3' => $results = [Client::class, $this->searchClientResource('custom3', $rule, $invoices, $payments)], - '$client.custom4' => $results = [Client::class, $this->searchClientResource('custom4', $rule, $invoices, $payments)], + '$client.custom1' => $results = [Client::class, $this->searchClientResource('custom_value1', $rule, $invoices, $payments)], + '$client.custom2' => $results = [Client::class, $this->searchClientResource('custom_value2', $rule, $invoices, $payments)], + '$client.custom3' => $results = [Client::class, $this->searchClientResource('custom_value3', $rule, $invoices, $payments)], + '$client.custom4' => $results = [Client::class, $this->searchClientResource('custom_value4', $rule, $invoices, $payments)], default => $results = [Client::class, [collect([]), Invoice::class]], }; @@ -147,14 +149,17 @@ class ProcessBankRules extends AbstractService $this->bank_transaction->status_id = BankTransaction::STATUS_MATCHED; $this->bank_transaction->bank_transaction_rule_id = $bank_transaction_rule->id; - $first_result = reset($match_set); if($first_result[0] == Payment::class) { $payment_id = $first_result[1][0]; $this->bank_transaction->payment_id = $payment_id; + } + elseif($first_result[0] == Invoice::class) { + $invoice_id = $first_result[1][0]; + $this->bank_transaction->invoice_ids = $this->encodePrimaryKey($invoice_id); } - + $this->bank_transaction->save(); //auto-convert @@ -245,7 +250,9 @@ class ProcessBankRules extends AbstractService { return $payments->when($column != 'amount', function ($q) use ($rule, $column) { return $q->filter(function ($record) use ($rule, $column) { - return $this->matchStringOperator($this->bank_transaction->description, $record->{$column}, $rule['operator']); + + $bool = $this->matchStringOperator($this->bank_transaction->description, $record->{$column}, $rule['operator']); + return $bool; }); }) ->when($column == 'amount', function ($q) use ($rule, $column) { @@ -303,325 +310,7 @@ class ProcessBankRules extends AbstractService return [Client::class, collect([])]; } - // $payment.amount => "Payment Amount", float - // $payment.transaction_reference => "Payment Transaction Reference", string - // $invoice.amount => "Invoice Amount", float - // $invoice.number => "Invoice Number", string - // $client.id_number => "Client ID Number", string - // $client.email => "Client Email", string - // $invoice.po_number => "Invoice Purchase Order Number", string - - - // private function matchCredit() - // { - // $this->invoices = Invoice::query()->where('company_id', $this->bank_transaction->company_id) - // ->whereIn('status_id', [1,2,3]) - // ->where('is_deleted', 0) - // ->get(); - - // $invoice = $this->invoices->first(function ($value, $key) { - // return str_contains($this->bank_transaction->description, $value->number) || str_contains(str_replace("\n", "", $this->bank_transaction->description), $value->number); - // }); - - // if ($invoice) { - // $this->bank_transaction->invoice_ids = $invoice->hashed_id; - // $this->bank_transaction->status_id = BankTransaction::STATUS_MATCHED; - // $this->bank_transaction->save(); - // return; - // } - - // $this->credit_rules = $this->bank_transaction->company->credit_rules(); - - // //stub for credit rules - // foreach ($this->credit_rules as $bank_transaction_rule) { - // $matches = 0; - - // if (!is_array($bank_transaction_rule['rules'])) { - // continue; - // } - - // foreach ($bank_transaction_rule['rules'] as $rule) { - // $rule_count = count($bank_transaction_rule['rules']); - - // $invoiceNumbers = false; - // $invoiceNumber = false; - // $invoiceAmounts = false; - // $paymentAmounts = false; - // $paymentReferences = false; - // $clientIdNumbers = false; - // $clientEmails = false; - // $invoicePONumbers = false; - - // if ($rule['search_key'] == '$invoice.number') { - - // $invoiceNumbers = Invoice::query()->where('company_id', $this->bank_transaction->company_id) - // ->whereIn('status_id', [1,2,3]) - // ->where('is_deleted', 0) - // ->get(); - - // $invoiceNumber = $invoiceNumbers->first(function ($value, $key) { - // return str_contains($this->bank_transaction->description, $value->number) || str_contains(str_replace("\n", "", $this->bank_transaction->description), $value->number); - // }); - - // if($invoiceNumber) - // $matches++; - - // } - - // if ($rule['search_key'] == '$invoice.po_number') { - - // $invoicePONumbers = Invoice::query()->where('company_id', $this->bank_transaction->company_id) - // ->whereIn('status_id', [1,2,3]) - // ->where('is_deleted', 0) - // ->where('po_number', $this->bank_transaction->description) - // ->get(); - - // if($invoicePONumbers->count() > 0) { - // $matches++; - // } - - // } - - // if ($rule['search_key'] == '$invoice.amount') { - - // $$invoiceAmounts = Invoice::query()->where('company_id', $this->bank_transaction->company_id) - // ->whereIn('status_id', [1,2,3]) - // ->where('is_deleted', 0) - // ->where('amount', $rule['operator'], $this->bank_transaction->amount) - // ->get(); - - // $invoiceAmounts = $this->invoices; - - // if($invoiceAmounts->count() > 0) { - // $matches++; - // } - - // } - - // if ($rule['search_key'] == '$payment.amount') { - - - // $paymentAmounts = Payment::query()->where('company_id', $this->bank_transaction->company_id) - // ->whereIn('status_id', [1,4]) - // ->where('is_deleted', 0) - // ->whereNull('transaction_id') - // ->where('amount', $rule['operator'], $this->bank_transaction->amount) - // ->get(); - - - - // if($paymentAmounts->count() > 0) { - // $matches++; - // } - - // } - - - // if ($rule['search_key'] == '$payment.transaction_reference') { - - // $ref_search = $this->bank_transaction->description; - - // switch ($rule['operator']) { - // case 'is': - // $operator = '='; - // break; - // case 'contains': - // $ref_search = "%".$ref_search."%"; - // $operator = 'LIKE'; - // break; - - // default: - // $operator = '='; - // break; - // } - - // $paymentReferences = Payment::query()->where('company_id', $this->bank_transaction->company_id) - // ->whereIn('status_id', [1,4]) - // ->where('is_deleted', 0) - // ->whereNull('transaction_id') - // ->where('transaction_reference', $operator, $ref_search) - // ->get(); - - - - // if($paymentReferences->count() > 0) { - // $matches++; - // } - - // } - - // if ($rule['search_key'] == '$client.id_number') { - - // $ref_search = $this->bank_transaction->description; - - // switch ($rule['operator']) { - // case 'is': - // $operator = '='; - // break; - // case 'contains': - // $ref_search = "%".$ref_search."%"; - // $operator = 'LIKE'; - // break; - - // default: - // $operator = '='; - // break; - // } - - // $clientIdNumbers = Client::query()->where('company_id', $this->bank_transaction->company_id) - // ->where('id_number', $operator, $ref_search) - // ->get(); - - // if($clientIdNumbers->count() > 0) { - // $matches++; - // } - - // } - - - // if ($rule['search_key'] == '$client.email') { - - // $clientEmails = Client::query() - // ->where('company_id', $this->bank_transaction->company_id) - // ->whereHas('contacts', function ($q){ - // $q->where('email', $this->bank_transaction->description); - // }) - // ->get(); - - - // if($clientEmails->count() > 0) { - // $matches++; - // } - - // if (($bank_transaction_rule['matches_on_all'] && ($matches == $rule_count)) || (!$bank_transaction_rule['matches_on_all'] && $matches > 0)) { - - // //determine which combination has succeeded, ie link a payment / or / invoice - // $invoice_ids = null; - // $payment_id = null; - - // if($invoiceNumber){ - // $invoice_ids = $invoiceNumber->hashed_id; - // } - - // if($invoicePONumbers && strlen($invoice_ids ?? '') == 0){ - - // if($clientEmails){ // @phpstan-ignore-line - - // $invoice_ids = $this->matchInvoiceAndClient($invoicePONumbers, $clientEmails); - - // } - - // if($clientIdNumbers && strlen($invoice_ids ?? '') == 0) - // { - - // $invoice_ids = $this->matchInvoiceAndClient($invoicePONumbers, $clientIdNumbers); - - // } - - // if(strlen($invoice_ids ?? '') == 0) - // { - // $invoice_ids = $invoicePONumbers->first()->hashed_id; - // } - - // } - - - // if($invoiceAmounts && strlen($invoice_ids ?? '') == 0) { - - // if($clientEmails) {// @phpstan-ignore-line - - // $invoice_ids = $this->matchInvoiceAndClient($invoiceAmounts, $clientEmails); - - // } - - // if($clientIdNumbers && strlen($invoice_ids ?? '') == 0) { - - // $invoice_ids = $this->matchInvoiceAndClient($invoiceAmounts, $clientIdNumbers); - - // } - - // if(strlen($invoice_ids ?? '') == 0) { - // $invoice_ids = $invoiceAmounts->first()->hashed_id; - // } - - // } - - - // if($paymentAmounts && strlen($invoice_ids ?? '') == 0 && is_null($payment_id)) { - - // if($clientEmails) {// @phpstan-ignore-line - - // $payment_id = $this->matchPaymentAndClient($paymentAmounts, $clientEmails); - - // } - - // if($clientIdNumbers && is_null($payment_id)) { - - - // $payment_id = $this->matchPaymentAndClient($paymentAmounts, $clientEmails); - - // } - - // if(is_null($payment_id)) { - // $payment_id = $paymentAmounts->first()->id; - // } - - // } - - // if(strlen($invoice_ids ?? '') > 1 || is_int($payment_id)) - // { - - // $this->bank_transaction->payment_id = $payment_id; - // $this->bank_transaction->invoice_ids = $invoice_ids; - // $this->bank_transaction->status_id = BankTransaction::STATUS_MATCHED; - // $this->bank_transaction->bank_transaction_rule_id = $bank_transaction_rule->id; - // $this->bank_transaction->save(); - - // } - - // } - - // } - - // } - - // } - - // } - - - // private function matchPaymentAndClient($payments, $clients): ?int - // { - // /** @var \Illuminate\Support\Collection $payments */ - // foreach($payments as $payment) { - // foreach($clients as $client) { - - // if($payment->client_id == $client->id) { - // return $payment->id; - - // } - // } - // } - - // return null; - // } - - // private function matchInvoiceAndClient($invoices, $clients): ?Invoice - // { - // /** @var \Illuminate\Support\Collection $invoices */ - // foreach($invoices as $invoice) { - // foreach($clients as $client) { - - // if($invoice->client_id == $client->id) { - // return $invoice->hashed_id; - - // } - // } - // } - - // return null; - // } - + private function matchDebit() { $this->debit_rules = $this->bank_transaction->company->debit_rules(); @@ -732,13 +421,336 @@ class ProcessBankRules extends AbstractService $bt_value = strtolower(str_replace(" ", "", $bt_value)); $rule_value = strtolower(str_replace(" ", "", $rule_value)); $rule_length = iconv_strlen($rule_value); - +// nlog($bt_value); +// nlog($rule_value); +// nlog($rule_length); return match ($operator) { 'is' => $bt_value == $rule_value, - 'contains' => stripos($bt_value, $rule_value) !== false, - 'starts_with' => substr($bt_value, 0, $rule_length) == $rule_value, + 'contains' => stripos($bt_value, $rule_value) !== false && strlen($rule_value) > 1, + 'starts_with' => substr($bt_value, 0, $rule_length) == $rule_value && strlen($rule_value) > 1, 'is_empty' => empty($bt_value), default => false, }; } } + + + +// $payment.amount => "Payment Amount", float +// $payment.transaction_reference => "Payment Transaction Reference", string +// $invoice.amount => "Invoice Amount", float +// $invoice.number => "Invoice Number", string +// $client.id_number => "Client ID Number", string +// $client.email => "Client Email", string +// $invoice.po_number => "Invoice Purchase Order Number", string + + +// private function matchCredit() +// { +// $this->invoices = Invoice::query()->where('company_id', $this->bank_transaction->company_id) +// ->whereIn('status_id', [1,2,3]) +// ->where('is_deleted', 0) +// ->get(); + +// $invoice = $this->invoices->first(function ($value, $key) { +// return str_contains($this->bank_transaction->description, $value->number) || str_contains(str_replace("\n", "", $this->bank_transaction->description), $value->number); +// }); + +// if ($invoice) { +// $this->bank_transaction->invoice_ids = $invoice->hashed_id; +// $this->bank_transaction->status_id = BankTransaction::STATUS_MATCHED; +// $this->bank_transaction->save(); +// return; +// } + +// $this->credit_rules = $this->bank_transaction->company->credit_rules(); + +// //stub for credit rules +// foreach ($this->credit_rules as $bank_transaction_rule) { +// $matches = 0; + +// if (!is_array($bank_transaction_rule['rules'])) { +// continue; +// } + +// foreach ($bank_transaction_rule['rules'] as $rule) { +// $rule_count = count($bank_transaction_rule['rules']); + +// $invoiceNumbers = false; +// $invoiceNumber = false; +// $invoiceAmounts = false; +// $paymentAmounts = false; +// $paymentReferences = false; +// $clientIdNumbers = false; +// $clientEmails = false; +// $invoicePONumbers = false; + +// if ($rule['search_key'] == '$invoice.number') { + +// $invoiceNumbers = Invoice::query()->where('company_id', $this->bank_transaction->company_id) +// ->whereIn('status_id', [1,2,3]) +// ->where('is_deleted', 0) +// ->get(); + +// $invoiceNumber = $invoiceNumbers->first(function ($value, $key) { +// return str_contains($this->bank_transaction->description, $value->number) || str_contains(str_replace("\n", "", $this->bank_transaction->description), $value->number); +// }); + +// if($invoiceNumber) +// $matches++; + +// } + +// if ($rule['search_key'] == '$invoice.po_number') { + +// $invoicePONumbers = Invoice::query()->where('company_id', $this->bank_transaction->company_id) +// ->whereIn('status_id', [1,2,3]) +// ->where('is_deleted', 0) +// ->where('po_number', $this->bank_transaction->description) +// ->get(); + +// if($invoicePONumbers->count() > 0) { +// $matches++; +// } + +// } + +// if ($rule['search_key'] == '$invoice.amount') { + +// $$invoiceAmounts = Invoice::query()->where('company_id', $this->bank_transaction->company_id) +// ->whereIn('status_id', [1,2,3]) +// ->where('is_deleted', 0) +// ->where('amount', $rule['operator'], $this->bank_transaction->amount) +// ->get(); + +// $invoiceAmounts = $this->invoices; + +// if($invoiceAmounts->count() > 0) { +// $matches++; +// } + +// } + +// if ($rule['search_key'] == '$payment.amount') { + + +// $paymentAmounts = Payment::query()->where('company_id', $this->bank_transaction->company_id) +// ->whereIn('status_id', [1,4]) +// ->where('is_deleted', 0) +// ->whereNull('transaction_id') +// ->where('amount', $rule['operator'], $this->bank_transaction->amount) +// ->get(); + + + +// if($paymentAmounts->count() > 0) { +// $matches++; +// } + +// } + + +// if ($rule['search_key'] == '$payment.transaction_reference') { + +// $ref_search = $this->bank_transaction->description; + +// switch ($rule['operator']) { +// case 'is': +// $operator = '='; +// break; +// case 'contains': +// $ref_search = "%".$ref_search."%"; +// $operator = 'LIKE'; +// break; + +// default: +// $operator = '='; +// break; +// } + +// $paymentReferences = Payment::query()->where('company_id', $this->bank_transaction->company_id) +// ->whereIn('status_id', [1,4]) +// ->where('is_deleted', 0) +// ->whereNull('transaction_id') +// ->where('transaction_reference', $operator, $ref_search) +// ->get(); + + + +// if($paymentReferences->count() > 0) { +// $matches++; +// } + +// } + +// if ($rule['search_key'] == '$client.id_number') { + +// $ref_search = $this->bank_transaction->description; + +// switch ($rule['operator']) { +// case 'is': +// $operator = '='; +// break; +// case 'contains': +// $ref_search = "%".$ref_search."%"; +// $operator = 'LIKE'; +// break; + +// default: +// $operator = '='; +// break; +// } + +// $clientIdNumbers = Client::query()->where('company_id', $this->bank_transaction->company_id) +// ->where('id_number', $operator, $ref_search) +// ->get(); + +// if($clientIdNumbers->count() > 0) { +// $matches++; +// } + +// } + + +// if ($rule['search_key'] == '$client.email') { + +// $clientEmails = Client::query() +// ->where('company_id', $this->bank_transaction->company_id) +// ->whereHas('contacts', function ($q){ +// $q->where('email', $this->bank_transaction->description); +// }) +// ->get(); + + +// if($clientEmails->count() > 0) { +// $matches++; +// } + +// if (($bank_transaction_rule['matches_on_all'] && ($matches == $rule_count)) || (!$bank_transaction_rule['matches_on_all'] && $matches > 0)) { + +// //determine which combination has succeeded, ie link a payment / or / invoice +// $invoice_ids = null; +// $payment_id = null; + +// if($invoiceNumber){ +// $invoice_ids = $invoiceNumber->hashed_id; +// } + +// if($invoicePONumbers && strlen($invoice_ids ?? '') == 0){ + +// if($clientEmails){ // @phpstan-ignore-line + +// $invoice_ids = $this->matchInvoiceAndClient($invoicePONumbers, $clientEmails); + +// } + +// if($clientIdNumbers && strlen($invoice_ids ?? '') == 0) +// { + +// $invoice_ids = $this->matchInvoiceAndClient($invoicePONumbers, $clientIdNumbers); + +// } + +// if(strlen($invoice_ids ?? '') == 0) +// { +// $invoice_ids = $invoicePONumbers->first()->hashed_id; +// } + +// } + + +// if($invoiceAmounts && strlen($invoice_ids ?? '') == 0) { + +// if($clientEmails) {// @phpstan-ignore-line + +// $invoice_ids = $this->matchInvoiceAndClient($invoiceAmounts, $clientEmails); + +// } + +// if($clientIdNumbers && strlen($invoice_ids ?? '') == 0) { + +// $invoice_ids = $this->matchInvoiceAndClient($invoiceAmounts, $clientIdNumbers); + +// } + +// if(strlen($invoice_ids ?? '') == 0) { +// $invoice_ids = $invoiceAmounts->first()->hashed_id; +// } + +// } + + +// if($paymentAmounts && strlen($invoice_ids ?? '') == 0 && is_null($payment_id)) { + +// if($clientEmails) {// @phpstan-ignore-line + +// $payment_id = $this->matchPaymentAndClient($paymentAmounts, $clientEmails); + +// } + +// if($clientIdNumbers && is_null($payment_id)) { + + +// $payment_id = $this->matchPaymentAndClient($paymentAmounts, $clientEmails); + +// } + +// if(is_null($payment_id)) { +// $payment_id = $paymentAmounts->first()->id; +// } + +// } + +// if(strlen($invoice_ids ?? '') > 1 || is_int($payment_id)) +// { + +// $this->bank_transaction->payment_id = $payment_id; +// $this->bank_transaction->invoice_ids = $invoice_ids; +// $this->bank_transaction->status_id = BankTransaction::STATUS_MATCHED; +// $this->bank_transaction->bank_transaction_rule_id = $bank_transaction_rule->id; +// $this->bank_transaction->save(); + +// } + +// } + +// } + +// } + +// } + +// } + + +// private function matchPaymentAndClient($payments, $clients): ?int +// { +// /** @var \Illuminate\Support\Collection $payments */ +// foreach($payments as $payment) { +// foreach($clients as $client) { + +// if($payment->client_id == $client->id) { +// return $payment->id; + +// } +// } +// } + +// return null; +// } + +// private function matchInvoiceAndClient($invoices, $clients): ?Invoice +// { +// /** @var \Illuminate\Support\Collection $invoices */ +// foreach($invoices as $invoice) { +// foreach($clients as $client) { + +// if($invoice->client_id == $client->id) { +// return $invoice->hashed_id; + +// } +// } +// } + +// return null; +// } diff --git a/tests/Feature/Bank/BankTransactionRuleTest.php b/tests/Feature/Bank/BankTransactionRuleTest.php index 21bb15734c..3b455b683e 100644 --- a/tests/Feature/Bank/BankTransactionRuleTest.php +++ b/tests/Feature/Bank/BankTransactionRuleTest.php @@ -18,10 +18,12 @@ use Tests\MockAccountData; use App\Models\BankIntegration; use App\Models\BankTransaction; use App\Models\BankTransactionRule; +use App\Models\Invoice; use App\Services\Bank\ProcessBankRules; use Illuminate\Validation\ValidationException; use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Foundation\Testing\DatabaseTransactions; +use Str; class BankTransactionRuleTest extends TestCase { @@ -41,7 +43,361 @@ class BankTransactionRuleTest extends TestCase $this->withoutExceptionHandling(); } - public function testNewCreditMatchingRules() + public function testNewCreditMatchingRulesInvoiceStartsWith() + { + + $bi = BankIntegration::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + ]); + + $hash = Str::random(32); + $rand_amount = rand(1000,10000000); + + $bt = BankTransaction::factory()->create([ + 'bank_integration_id' => $bi->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'description' => $hash, + 'base_type' => 'CREDIT', + 'amount' => $rand_amount + ]); + + $this->assertNull($bt->payment_id); + + $br = BankTransactionRule::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'matches_on_all' => false, + 'auto_convert' => false, + 'applies_to' => 'CREDIT', + 'rules' => [ + [ + 'search_key' => '$invoice.number', + 'operator' => 'starts_with', + ] + ] + ]); + + $i = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'amount' => $rand_amount, + 'balance' => $rand_amount, + 'number' => $hash, + 'status_id' => 2, + 'custom_value1' => substr($hash, 0, 8) + ]); + + $this->assertEquals(BankTransaction::STATUS_UNMATCHED, $bt->status_id); + + (new ProcessBankRules($bt))->run(); + + $bt->fresh(); + + $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id); + $this->assertNotNull($i->id); + $this->assertNotNull($bt->invoice_ids); + $this->assertEquals($i->hashed_id, $bt->invoice_ids); + } + + public function testNewCreditMatchingRulesInvoiceContains() + { + + $bi = BankIntegration::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + ]); + + $hash = Str::random(32); + $rand_amount = rand(1000,10000000); + + $bt = BankTransaction::factory()->create([ + 'bank_integration_id' => $bi->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'description' => $hash, + 'base_type' => 'CREDIT', + 'amount' => $rand_amount + ]); + + $this->assertNull($bt->payment_id); + + $br = BankTransactionRule::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'matches_on_all' => false, + 'auto_convert' => false, + 'applies_to' => 'CREDIT', + 'rules' => [ + [ + 'search_key' => '$invoice.number', + 'operator' => 'contains', + ] + ] + ]); + + $i = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'amount' => $rand_amount, + 'balance' => $rand_amount, + 'number' => $hash, + 'status_id' => 2, + 'custom_value1' => substr($hash, 0, 8) + ]); + + $this->assertEquals(BankTransaction::STATUS_UNMATCHED, $bt->status_id); + + (new ProcessBankRules($bt))->run(); + + $bt->fresh(); + + $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id); + $this->assertNotNull($i->id); + $this->assertNotNull($bt->invoice_ids); + $this->assertEquals($i->hashed_id, $bt->invoice_ids); + } + + public function testNewCreditMatchingRulesInvoiceNumber() + { + + $bi = BankIntegration::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + ]); + + $hash = Str::random(32); + $rand_amount = rand(1000,10000000); + + $bt = BankTransaction::factory()->create([ + 'bank_integration_id' => $bi->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'description' => $hash, + 'base_type' => 'CREDIT', + 'amount' => $rand_amount + ]); + + $this->assertNull($bt->payment_id); + + $br = BankTransactionRule::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'matches_on_all' => false, + 'auto_convert' => false, + 'applies_to' => 'CREDIT', + 'rules' => [ + [ + 'search_key' => '$invoice.number', + 'operator' => 'is', + ] + ] + ]); + + $i = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'amount' => $rand_amount, + 'balance' => $rand_amount, + 'number' => $hash, + 'status_id' => 2, + 'custom_value1' => substr($hash, 0, 8) + ]); + + $this->assertEquals(BankTransaction::STATUS_UNMATCHED, $bt->status_id); + + (new ProcessBankRules($bt))->run(); + + $bt->fresh(); + + $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id); + $this->assertNotNull($i->id); + $this->assertNotNull($bt->invoice_ids); + $this->assertEquals($i->hashed_id, $bt->invoice_ids); + } + + + public function testNewCreditMatchingRulesInvoiceAmount() + { + + $bi = BankIntegration::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + ]); + + $hash = Str::random(32); + $rand_amount = rand(1000,10000000); + + $bt = BankTransaction::factory()->create([ + 'bank_integration_id' => $bi->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'description' => $hash, + 'base_type' => 'CREDIT', + 'amount' => $rand_amount + ]); + + $this->assertNull($bt->payment_id); + + $br = BankTransactionRule::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'matches_on_all' => false, + 'auto_convert' => false, + 'applies_to' => 'CREDIT', + 'rules' => [ + [ + 'search_key' => '$invoice.amount', + 'operator' => '=', + ] + ] + ]); + + $i = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'amount' => $rand_amount, + 'balance' => $rand_amount, + 'status_id' => 2, + 'custom_value1' => substr($hash, 0, 8) + ]); + + $this->assertEquals(BankTransaction::STATUS_UNMATCHED, $bt->status_id); + + (new ProcessBankRules($bt))->run(); + + $bt->fresh(); + + $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id); + $this->assertNotNull($i->id); + $this->assertNotNull($bt->invoice_ids); + $this->assertEquals($i->hashed_id, $bt->invoice_ids); + } + + public function testNewCreditMatchingRulesPaymentCustomValue() + { + + $bi = BankIntegration::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + ]); + + $hash = Str::random(32); + $rand_amount = rand(1000,10000000); + + $bt = BankTransaction::factory()->create([ + 'bank_integration_id' => $bi->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'description' => $hash, + 'base_type' => 'CREDIT', + 'amount' => $rand_amount + ]); + + $this->assertNull($bt->payment_id); + + $br = BankTransactionRule::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'matches_on_all' => false, + 'auto_convert' => false, + 'applies_to' => 'CREDIT', + 'rules' => [ + [ + 'search_key' => '$payment.custom1', + 'operator' => 'starts_with', + ] + ] + ]); + + $p = Payment::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'amount' => $rand_amount, + 'custom_value1' => substr($hash, 0, 8) + ]); + + $this->assertEquals(BankTransaction::STATUS_UNMATCHED, $bt->status_id); + + (new ProcessBankRules($bt))->run(); + + $bt->fresh(); + + $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id); + $this->assertNotNull($p->id); + $this->assertNotNull($bt->payment_id); + $this->assertEquals($p->id, $bt->payment_id); + } + + public function testNewCreditMatchingRulesPaymentStartsWith() + { + + $bi = BankIntegration::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + ]); + + $hash = Str::random(32); + $rand_amount = rand(1000,10000000); + + $bt = BankTransaction::factory()->create([ + 'bank_integration_id' => $bi->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'description' => $hash, + 'base_type' => 'CREDIT', + 'amount' => $rand_amount + ]); + + $this->assertNull($bt->payment_id); + + $br = BankTransactionRule::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'matches_on_all' => false, + 'auto_convert' => false, + 'applies_to' => 'CREDIT', + 'rules' => [ + [ + 'search_key' => '$payment.transaction_reference', + 'operator' => 'starts_with', + ] + ] + ]); + + $p = Payment::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'amount' => $rand_amount, + 'transaction_reference' => substr($hash, 0, 8) + ]); + + $this->assertEquals(BankTransaction::STATUS_UNMATCHED, $bt->status_id); + + (new ProcessBankRules($bt))->run(); + + $bt->fresh(); + + $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id); + $this->assertNotNull($p->id); + $this->assertNotNull($bt->payment_id); + $this->assertEquals($p->id, $bt->payment_id); + } + + public function testNewCreditMatchingRulesPaymentAmount() { $bi = BankIntegration::factory()->create([ @@ -63,7 +419,7 @@ class BankTransactionRuleTest extends TestCase ]); $this->assertNull($bt->payment_id); - + $br = BankTransactionRule::factory()->create([ 'company_id' => $this->company->id, 'user_id' => $this->user->id, @@ -86,7 +442,62 @@ class BankTransactionRuleTest extends TestCase 'transaction_reference' => 'nein' ]); - nlog($p->id); + $this->assertEquals(BankTransaction::STATUS_UNMATCHED, $bt->status_id); + + (new ProcessBankRules($bt))->run(); + + $bt->fresh(); + + $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id); + $this->assertNotNull($p->id); + $this->assertNotNull($bt->payment_id); + $this->assertEquals($p->id, $bt->payment_id); + } + + public function testNewCreditMatchingRulesPaymentTransactionReferenceExactMatch() + { + + $bi = BankIntegration::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + ]); + + $hash = md5(time()); + $rand_amount = rand(1000,10000000); + + $bt = BankTransaction::factory()->create([ + 'bank_integration_id' => $bi->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'description' => $hash, + 'base_type' => 'CREDIT', + 'amount' => $rand_amount + ]); + + $this->assertNull($bt->payment_id); + + $br = BankTransactionRule::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'matches_on_all' => false, + 'auto_convert' => false, + 'applies_to' => 'CREDIT', + 'rules' => [ + [ + 'search_key' => '$payment.transaction_reference', + 'operator' => 'is', + ] + ] + ]); + + $p = Payment::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'amount' => $rand_amount, + 'transaction_reference' => $hash + ]); $this->assertEquals(BankTransaction::STATUS_UNMATCHED, $bt->status_id); @@ -100,6 +511,64 @@ class BankTransactionRuleTest extends TestCase $this->assertEquals($p->id, $bt->payment_id); } + public function testNewCreditMatchingRulesPaymentTransactionReferenceContains() + { + + $bi = BankIntegration::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + ]); + + $hash = Str::random(32); + $rand_amount = rand(1000,10000000); + + $bt = BankTransaction::factory()->create([ + 'bank_integration_id' => $bi->id, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'description' => $hash, + 'base_type' => 'CREDIT', + 'amount' => $rand_amount + ]); + + $this->assertNull($bt->payment_id); + + $br = BankTransactionRule::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'matches_on_all' => false, + 'auto_convert' => false, + 'applies_to' => 'CREDIT', + 'rules' => [ + [ + 'search_key' => '$payment.transaction_reference', + 'operator' => 'contains', + ] + ] + ]); + + $p = Payment::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'amount' => $rand_amount, + 'transaction_reference' => substr($hash, 3, 13) + ]); + + $this->assertEquals(BankTransaction::STATUS_UNMATCHED, $bt->status_id); + + (new ProcessBankRules($bt))->run(); + + $bt->fresh(); + + $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id); + $this->assertNotNull($p->id); + $this->assertNotNull($bt->payment_id); + $this->assertEquals($p->id, $bt->payment_id); + } + + public function testMatchCreditOnInvoiceNumber() {