mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Fixes for attempting to pass a negative value for a applied amount
This commit is contained in:
parent
73c73d1f5c
commit
a871e319ea
@ -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'];
|
||||
}
|
||||
}
|
||||
|
@ -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']);
|
||||
}
|
||||
|
@ -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']) {
|
||||
|
@ -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']);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user