Test coverage for linking and unlinking expenses from transactions

This commit is contained in:
David Bomba 2023-04-05 16:13:42 +10:00
parent f780545b1b
commit 012d33c723
5 changed files with 196 additions and 11 deletions

View File

@ -47,7 +47,7 @@ class MatchBankTransactionRequest extends Request
public function prepareForValidation()
{
$inputs = $this->all();
nlog($inputs);
foreach ($inputs['transactions'] as $key => $input) {
if (array_key_exists('id', $inputs['transactions'][$key])) {
$inputs['transactions'][$key]['id'] = $this->decodePrimaryKey($input['id']);
@ -73,6 +73,7 @@ class MatchBankTransactionRequest extends Request
if (array_key_exists('expense_id', $inputs['transactions'][$key]) && strlen($inputs['transactions'][$key]['expense_id']) >= 1) {
$inputs['transactions'][$key]['expense_id'] = $this->decodePrimaryKey($inputs['transactions'][$key]['expense_id']);
$e = Expense::withTrashed()->where('company_id', auth()->user()->company()->id)->where('id', $inputs['transactions'][$key]['expense_id'])->first();
/*Ensure we don't relink an existing expense*/
@ -82,6 +83,8 @@ class MatchBankTransactionRequest extends Request
}
}
nlog($inputs);
$this->replace($inputs);
}
}

View File

@ -152,7 +152,7 @@ class MatchBankTransactions implements ShouldQueue
{
$this->bt = BankTransaction::find($input['id']);
if (!$this->bt || $this->bt->status_id == BankTransaction::STATUS_CONVERTED) {
if (!$this->bt) {
return $this;
}
@ -176,9 +176,13 @@ class MatchBankTransactions implements ShouldQueue
private function coalesceExpenses($expense): string
{
nlog("BTExpense: " . $this->bt->expense_id);
if(!$this->bt->expense_id || strlen($this->bt->expense_id) < 1)
return $expense;
if (!$this->bt->expense_id || strlen($this->bt->expense_id) < 1) {
nlog("coalesceExpense: " . $expense);
return $expense;
}
nlog("coalesceExpenses: " . $this->bt->expense_id . "," . $expense);
return collect(explode(",", $this->bt->expense_id))->push($expense)->implode(",");
}
@ -259,7 +263,7 @@ class MatchBankTransactions implements ShouldQueue
$expense->should_be_invoiced = $this->company->mark_expenses_invoiceable;
$expense->save();
$this->bt->expense_id = $expense->hashed_id;
$this->bt->expense_id = $this->coalesceExpenses($expense->hashed_id);
if (array_key_exists('vendor_id', $input)) {
$this->bt->vendor_id = $input['vendor_id'];

View File

@ -259,4 +259,10 @@ class Expense extends BaseModel
{
return $this->belongsTo(Project::class);
}
public function transaction()
{
return $this->belongsTo(BankTransaction::class);
}
}

View File

@ -102,9 +102,19 @@ class ExpenseRepository extends BaseRepository
public function delete($expense) :Expense
{
if ($expense->transaction_id) {
$exp_ids = collect(explode(',', $expense->transaction->expense_id))->filter(function ($id) use ($expense) {
return $id != $expense->hashed_id;
})->implode(',');
$expense->transaction_id = null;
$expense->saveQuietly();
$expense->transaction->expense_id = $exp_ids;
$expense->transaction->saveQuietly();
}
parent::delete($expense);

View File

@ -12,15 +12,16 @@
namespace Tests\Feature\Bank;
use Tests\TestCase;
use App\Models\Expense;
use App\Models\Invoice;
use Tests\MockAccountData;
use App\Factory\InvoiceFactory;
use App\Models\BankTransaction;
use App\Factory\InvoiceItemFactory;
use App\Factory\BankIntegrationFactory;
use App\Factory\BankTransactionFactory;
use App\Factory\InvoiceFactory;
use App\Factory\InvoiceItemFactory;
use App\Models\BankTransaction;
use App\Models\Invoice;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\MockAccountData;
use Tests\TestCase;
class BankTransactionTest extends TestCase
{
@ -38,6 +39,167 @@ class BankTransactionTest extends TestCase
);
}
public function testLinkMultipleExpensesWithDeleteToTransaction()
{
$data = [];
$bi = BankIntegrationFactory::create($this->company->id, $this->user->id, $this->account->id);
$bi->save();
$bt = BankTransactionFactory::create($this->company->id, $this->user->id);
$bt->bank_integration_id = $bi->id;
$bt->status_id = BankTransaction::STATUS_UNMATCHED;
$bt->description = 'Fuel';
$bt->amount = 10;
$bt->currency_code = $this->client->currency()->code;
$bt->date = now()->format('Y-m-d');
$bt->transaction_id = 1234567890;
$bt->category_id = 10000003;
$bt->base_type = 'DEBIT';
$bt->save();
$this->expense->vendor_id = $this->vendor->id;
$this->expense->save();
$data = [];
$data['transactions'][] = [
'id' => $bt->hashed_id,
'expense_id' => $this->expense->hashed_id
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/bank_transactions/match', $data);
$response->assertStatus(200);
$this->assertEquals($this->expense->refresh()->transaction_id, $bt->id);
$this->assertEquals($this->expense->hashed_id, $bt->refresh()->expense_id);
$this->assertEquals($this->vendor->id, $bt->vendor_id);
$this->assertEquals(BankTransaction::STATUS_CONVERTED, $bt->status_id);
$e = Expense::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
]);
$data = [];
$data['transactions'][] = [
'id' => $bt->hashed_id,
'expense_id' => $e->hashed_id
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/bank_transactions/match', $data);
$response->assertStatus(200);
$this->assertEquals("{$this->expense->hashed_id},{$e->hashed_id}", $bt->fresh()->expense_id);
$e2 = Expense::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
]);
$data = [];
$data['transactions'][] = [
'id' => $bt->hashed_id,
'expense_id' => $e2->hashed_id
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/bank_transactions/match', $data);
$response->assertStatus(200);
$this->assertNotNull($e2->refresh()->transaction_id);
$this->assertEquals("{$this->expense->hashed_id},{$e->hashed_id},{$e2->hashed_id}", $bt->fresh()->expense_id);
$expense_repo = app('App\Repositories\ExpenseRepository');
$expense_repo->delete($e2);
$this->assertEquals("{$this->expense->hashed_id},{$e->hashed_id}", $bt->fresh()->expense_id);
}
public function testLinkMultipleExpensesToTransaction()
{
$data = [];
$bi = BankIntegrationFactory::create($this->company->id, $this->user->id, $this->account->id);
$bi->save();
$bt = BankTransactionFactory::create($this->company->id, $this->user->id);
$bt->bank_integration_id = $bi->id;
$bt->status_id = BankTransaction::STATUS_UNMATCHED;
$bt->description = 'Fuel';
$bt->amount = 10;
$bt->currency_code = $this->client->currency()->code;
$bt->date = now()->format('Y-m-d');
$bt->transaction_id = 1234567890;
$bt->category_id = 10000003;
$bt->base_type = 'DEBIT';
$bt->save();
$this->expense->vendor_id = $this->vendor->id;
$this->expense->save();
$data = [];
$data['transactions'][] = [
'id' => $bt->hashed_id,
'expense_id' => $this->expense->hashed_id
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/bank_transactions/match', $data);
$response->assertStatus(200);
$this->assertEquals($this->expense->refresh()->transaction_id, $bt->id);
$this->assertEquals($this->expense->hashed_id, $bt->refresh()->expense_id);
$this->assertEquals($this->vendor->id, $bt->vendor_id);
$this->assertEquals(BankTransaction::STATUS_CONVERTED, $bt->status_id);
$e = Expense::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
]);
$data = [];
$data['transactions'][] = [
'id' => $bt->hashed_id,
'expense_id' => $e->hashed_id
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/bank_transactions/match', $data);
$response->assertStatus(200);
$this->assertEquals("{$this->expense->hashed_id},{$e->hashed_id}", $bt->fresh()->expense_id);
}
public function testBankTransactionBulkActions()
{