Fixes for attempting to pass a negative value for a applied amount

This commit is contained in:
David Bomba 2024-03-20 17:17:23 +11:00
parent 73c73d1f5c
commit a871e319ea
7 changed files with 176 additions and 122 deletions

View File

@ -78,7 +78,6 @@ class StorePaymentRequest extends Request
foreach ($input['credits'] as $key => $value) {
if (array_key_exists('credit_id', $input['credits'][$key])) {
$input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']);
$credits_total += $value['amount'];
}
}

View File

@ -44,7 +44,8 @@ class UpdatePaymentRequest extends Request
$rules = [
'invoices' => ['array', new PaymentAppliedValidAmount($this->all()), new ValidCreditsPresentRule($this->all())],
'invoices.*.invoice_id' => 'distinct',
'invoices.*.invoice_id' => 'sometimes|distinct',
'invoices.*.amount' => 'sometimes|numeric|min:0',
];
if ($this->number) {
@ -85,7 +86,6 @@ class UpdatePaymentRequest extends Request
if (isset($input['invoices']) && is_array($input['invoices']) !== false) {
foreach ($input['invoices'] as $key => $value) {
if(isset($input['invoices'][$key]['invoice_id'])) {
// if (array_key_exists('invoice_id', $input['invoices'][$key])) {
$input['invoices'][$key]['invoice_id'] = $this->decodePrimaryKey($value['invoice_id']);
}
}
@ -93,7 +93,6 @@ class UpdatePaymentRequest extends Request
if (isset($input['credits']) && is_array($input['credits']) !== false) {
foreach ($input['credits'] as $key => $value) {
// if (array_key_exists('credits', $input['credits'][$key])) {
if (isset($input['credits'][$key]['credit_id'])) {
$input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']);
}

View File

@ -87,10 +87,6 @@ class PaymentAppliedValidAmount implements Rule
$inv = $inv_collection->firstWhere('id', $invoice['invoice_id']);
nlog($inv->status_id);
nlog($inv->amount);
nlog($invoice['amount']);
if($inv->status_id == Invoice::STATUS_DRAFT && $inv->amount >= $invoice['amount']) {
} elseif ($inv->balance < $invoice['amount']) {

View File

@ -49,11 +49,8 @@ class ValidCreditsPresentRule implements Rule
private function validCreditsPresent(): bool
{
//todo need to ensure the clients credits are here not random ones!
if (array_key_exists('credits', $this->input) && is_array($this->input['credits']) && count($this->input['credits']) > 0) {
$credit_collection = Credit::query()->whereIn('id', array_column($this->input['credits'], 'credit_id'))->count();
$credit_collection = Credit::query()->where('client_id', request()->input('client_id'))->whereIn('id', array_column($this->input['credits'], 'credit_id'))->count();
return $credit_collection == count($this->input['credits']);
}

View File

@ -62,6 +62,74 @@ class PaymentTest extends TestCase
);
}
public function testNegativeAppliedAmounts()
{
$p = Payment::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'status_id' => Payment::STATUS_COMPLETED,
'amount' => 100
]);
$i = Invoice::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'status_id' => Invoice::STATUS_SENT,
]);
$i->calc()->getInvoice()->service()->markSent()->save();
$this->assertGreaterThan(0, $i->balance);
$data = [
'amount' => 5,
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $this->invoice->hashed_id,
'amount' => 5,
],
],
'date' => '2020/12/11',
'idempotency_key' => \Illuminate\Support\Str::uuid()->toString()
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments/', $data);
$response->assertStatus(200);
$payment_id = $response->json()['data']['id'];
$payment = Payment::find($this->decodePrimaryKey($payment_id));
$this->assertNotNull($payment);
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $this->invoice->hashed_id,
'amount' => -5,
],
],
'date' => '2020/12/11',
'idempotency_key' => \Illuminate\Support\Str::uuid()->toString()
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$payment_id, $data);
$response->assertStatus(422);
}
public function testCompletedPaymentLogic()
{
@ -1395,8 +1463,9 @@ class PaymentTest extends TestCase
$invoice_calc = new InvoiceSum($invoice);
$invoice_calc->build();
$invoice = $invoice_calc->getInvoice();
$invoice->save();
$invoice = $invoice_calc->getInvoice()->service()->markSent()->save();
$this->assertEquals(10, $invoice->amount);
$this->assertEquals(10, $invoice->balance);
$credit = CreditFactory::create($this->company->id, $this->user->id);
$credit->client_id = $client->id;
@ -1410,8 +1479,10 @@ class PaymentTest extends TestCase
$credit_calc = new InvoiceSum($credit);
$credit_calc->build();
$credit = $credit_calc->getCredit();
$credit->save(); //$10 credit
$credit = $credit_calc->getCredit()->service()->markSent()->save(); //$10 credit
$this->assertEquals(10, $credit->amount);
$this->assertEquals(10, $credit->balance);
$data = [
'amount' => $invoice->amount,

View File

@ -163,18 +163,11 @@ class CreditPaymentTest extends TestCase
'date' => '2019/12/12',
];
$response = false;
try {
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/payments/', $data);
} catch (ValidationException $e) {
$message = json_decode($e->validator->getMessageBag(), 1);
nlog($e->validator->getMessageBag());
}
$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();

View File

@ -63,127 +63,126 @@ class RefundTest extends TestCase
public function testRefundAndAppliedAmounts()
{
$data = [
'amount' => 500,
'client_id' => $this->client->hashed_id,
'date' => '2020/12/12',
$data = [
'amount' => 500,
'client_id' => $this->client->hashed_id,
'date' => '2020/12/12',
];
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments', $data);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments', $data);
$response->assertStatus(200);
$response->assertStatus(200);
$arr = $response->json();
$arr = $response->json();
$payment_id = $arr['data']['id'];
$payment_id = $arr['data']['id'];
$item = new InvoiceItem;
$item->cost = 300;
$item->quantity = 1;
$item = new InvoiceItem;
$item->cost = 300;
$item->quantity = 1;
$i = Invoice::factory()
->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->client->id,
'line_items' => [$item],
'discount' => 0,
'tax_name1' => '',
'tax_name2' => '',
'tax_name3' => '',
'tax_rate1' => 0,
'tax_rate2' => 0,
'tax_rate3' => 0,
]);
$i = Invoice::factory()
->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->client->id,
'line_items' => [$item],
'discount' => 0,
'tax_name1' => '',
'tax_name2' => '',
'tax_name3' => '',
'tax_rate1' => 0,
'tax_rate2' => 0,
'tax_rate3' => 0,
]);
$i->calc()->getInvoice();
$i->service()->markSent()->save();
$i->calc()->getInvoice();
$i->service()->markSent()->save();
$this->assertEquals(300, $i->balance);
$this->assertEquals(300, $i->balance);
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 300
],
]
];
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 300
],
]
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$payment_id, $data);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$payment_id, $data);
$response->assertStatus(200);
$response->assertStatus(200);
$i = $i->fresh();
$i = $i->fresh();
$this->assertEquals(0, $i->balance);
$this->assertEquals(0, $i->balance);
$payment = Payment::find($this->decodePrimaryKey($payment_id));
$payment = Payment::find($this->decodePrimaryKey($payment_id));
$this->assertNotNull($payment);
$this->assertEquals(500, $payment->amount);
$this->assertEquals(300, $payment->applied);
$this->assertEquals(0, $payment->refunded);
$this->assertNotNull($payment);
$this->assertEquals(500, $payment->amount);
$this->assertEquals(300, $payment->applied);
$this->assertEquals(0, $payment->refunded);
$data = [
'id' => $this->encodePrimaryKey($payment->id),
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => $i->amount,
],
],
'date' => '2020/12/12',
];
$data = [
'id' => $this->encodePrimaryKey($payment->id),
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => $i->amount,
],
],
'date' => '2020/12/12',
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments/refund', $data);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments/refund', $data);
$response->assertStatus(200);
$response->assertStatus(200);
$payment = $payment->fresh();
$i = $i->fresh();
$payment = $payment->fresh();
$i = $i->fresh();
$this->assertEquals(300, $payment->refunded);
$this->assertEquals(300, $i->balance);
$this->assertEquals(2, $i->status_id);
$this->assertEquals(300, $payment->refunded);
$this->assertEquals(300, $i->balance);
$this->assertEquals(2, $i->status_id);
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 200
],
]
];
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 200
],
]
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$payment_id, $data);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$payment_id, $data);
$response->assertStatus(200);
$response->assertStatus(200);
$payment = $payment->fresh();
$i = $i->fresh();
$payment = $payment->fresh();
$i = $i->fresh();
$this->assertEquals(300, $payment->refunded);
$this->assertEquals(100, $i->balance);
$this->assertEquals(3, $i->status_id);
$this->assertEquals(500, $payment->applied);
$this->assertEquals(300, $payment->refunded);
$this->assertEquals(100, $i->balance);
$this->assertEquals(3, $i->status_id);
$this->assertEquals(500, $payment->applied);
}