Fixes for deletion of payments with unapplied amounts
This commit is contained in:
parent
866a5e0977
commit
22e1350a75
|
|
@ -139,10 +139,12 @@ class DeletePayment
|
||||||
|
|
||||||
// 2025-03-26 - If we are deleting a negative payment, then there is an edge case where the paid to date will be reduced further down.
|
// 2025-03-26 - If we are deleting a negative payment, then there is an edge case where the paid to date will be reduced further down.
|
||||||
// for this scenario, we skip the update to the client paid to date at this point.
|
// for this scenario, we skip the update to the client paid to date at this point.
|
||||||
|
|
||||||
|
//2025-08-19 - if there is an unapplied amount, we need to subtract it from the paid to date.
|
||||||
$this->payment
|
$this->payment
|
||||||
->client
|
->client
|
||||||
->service()
|
->service()
|
||||||
->updateBalanceAndPaidToDate($net_deletable, ($net_deletable * -1) > 0 ? 0 : ($net_deletable * -1)) // if negative, set to 0, the paid to date will be reduced further down.
|
->updateBalanceAndPaidToDate($net_deletable, ($net_deletable * -1) > 0 ? 0 : ($net_deletable * -1 - ($this->payment->amount - $this->payment->applied))) // if negative, set to 0, the paid to date will be reduced further down.
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
if (abs(floatval($paymentable_invoice->balance) - floatval($paymentable_invoice->amount)) < 0.005) {
|
if (abs(floatval($paymentable_invoice->balance) - floatval($paymentable_invoice->amount)) < 0.005) {
|
||||||
|
|
@ -172,6 +174,7 @@ class DeletePayment
|
||||||
|
|
||||||
$reduced_paid_to_date = $this->payment->amount < 0 ? $this->payment->amount * -1 : min(0, ($this->payment->amount - $this->payment->refunded - $this->_paid_to_date_deleted) * -1);
|
$reduced_paid_to_date = $this->payment->amount < 0 ? $this->payment->amount * -1 : min(0, ($this->payment->amount - $this->payment->refunded - $this->_paid_to_date_deleted) * -1);
|
||||||
|
|
||||||
|
nlog("reduced paid to date: {$reduced_paid_to_date}");
|
||||||
if($reduced_paid_to_date != 0) {
|
if($reduced_paid_to_date != 0) {
|
||||||
$this->payment
|
$this->payment
|
||||||
->client
|
->client
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,17 @@
|
||||||
|
|
||||||
namespace Tests\Feature;
|
namespace Tests\Feature;
|
||||||
|
|
||||||
use App\DataMapper\InvoiceItem;
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\ClientContact;
|
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Models\ClientContact;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use App\DataMapper\InvoiceItem;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|
||||||
use Illuminate\Support\Facades\Session;
|
|
||||||
use Tests\MockAccountData;
|
use Tests\MockAccountData;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Repositories\InvoiceRepository;
|
||||||
|
use App\Repositories\CreditRepository;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Facades\Session;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class CreditTest extends TestCase
|
class CreditTest extends TestCase
|
||||||
|
|
@ -43,6 +45,125 @@ class CreditTest extends TestCase
|
||||||
$this->makeTestData();
|
$this->makeTestData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testPartialAmountWithPartialCreditAndPaymentDeletedBalance()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
$c = Client::factory()->create([
|
||||||
|
'company_id' => $this->company->id,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'balance' => 0,
|
||||||
|
'paid_to_date' => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$ii = new InvoiceItem();
|
||||||
|
$ii->cost = 100;
|
||||||
|
$ii->quantity = 1;
|
||||||
|
$ii->product_key = 'xx';
|
||||||
|
$ii->notes = 'yy';
|
||||||
|
|
||||||
|
$i = \App\Models\Invoice::factory()->create([
|
||||||
|
'company_id' => $this->company->id,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'client_id' => $c->id,
|
||||||
|
'tax_name1' => '',
|
||||||
|
'tax_name2' => '',
|
||||||
|
'tax_name3' => '',
|
||||||
|
'tax_rate1' => 0,
|
||||||
|
'tax_rate2' => 0,
|
||||||
|
'tax_rate3' => 0,
|
||||||
|
'discount' => 0,
|
||||||
|
'line_items' => [
|
||||||
|
$ii
|
||||||
|
],
|
||||||
|
'status_id' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$repo = new InvoiceRepository();
|
||||||
|
$repo->save([], $i);
|
||||||
|
|
||||||
|
$i = $i->calc()->getInvoice();
|
||||||
|
$i = $i->service()->markSent()->save();
|
||||||
|
|
||||||
|
$this->assertEquals(100, $i->balance);
|
||||||
|
$this->assertEquals(100, $i->amount);
|
||||||
|
|
||||||
|
$cr = \App\Models\Credit::factory()->create([
|
||||||
|
'company_id' => $this->company->id,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'client_id' => $c->id,
|
||||||
|
'tax_name1' => '',
|
||||||
|
'tax_name2' => '',
|
||||||
|
'tax_name3' => '',
|
||||||
|
'tax_rate1' => 0,
|
||||||
|
'tax_rate2' => 0,
|
||||||
|
'tax_rate3' => 0,
|
||||||
|
'discount' => 0,
|
||||||
|
'line_items' => [
|
||||||
|
$ii
|
||||||
|
],
|
||||||
|
'status_id' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$repo = new CreditRepository();
|
||||||
|
$repo->save([], $cr);
|
||||||
|
|
||||||
|
$cr = $cr->calc()->getInvoice();
|
||||||
|
$cr = $cr->service()->markSent()->save();
|
||||||
|
|
||||||
|
$this->assertEquals(100, $cr->balance);
|
||||||
|
$this->assertEquals(100, $cr->amount);
|
||||||
|
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'date' => '2020/12/12',
|
||||||
|
'client_id' => $c->hashed_id,
|
||||||
|
'amount' => 10,
|
||||||
|
'invoices' => [
|
||||||
|
[
|
||||||
|
'invoice_id' => $i->hashed_id,
|
||||||
|
'amount' => 10
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'credits' => [
|
||||||
|
[
|
||||||
|
'credit_id' => $cr->hashed_id,
|
||||||
|
'amount' => 10
|
||||||
|
]
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->postJson('/api/v1/payments', $data);
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
|
|
||||||
|
$arr = $response->json();
|
||||||
|
|
||||||
|
$this->assertEquals(10, $arr['data']['amount']);
|
||||||
|
|
||||||
|
$this->assertEquals(20, $c->fresh()->paid_to_date);
|
||||||
|
$this->assertEquals(90, $i->fresh()->balance);
|
||||||
|
$this->assertEquals(90, $cr->fresh()->balance);
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->deleteJson('/api/v1/payments/'.$arr['data']['id']);
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
|
|
||||||
|
$this->assertEquals(100, $i->fresh()->balance);
|
||||||
|
$this->assertEquals(100, $cr->fresh()->balance);
|
||||||
|
$this->assertEquals(100, $c->fresh()->balance);
|
||||||
|
$this->assertEquals(0, $c->fresh()->paid_to_date);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function testCreditReversalScenarioInvoicePartiallyPaid()
|
public function testCreditReversalScenarioInvoicePartiallyPaid()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -117,6 +238,8 @@ class CreditTest extends TestCase
|
||||||
|
|
||||||
$this->assertEquals(0, $c->balance);
|
$this->assertEquals(0, $c->balance);
|
||||||
$this->assertEquals(6, $i->status_id);
|
$this->assertEquals(6, $i->status_id);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue