Fixes for payments (#3276)

* More tests for refunds

* Tests for refunds

* Improve test speeds

* Fixes for tests

* Adjust the way we update products

* Adjustments for payments

* Fixes for payments
This commit is contained in:
David Bomba 2020-02-02 07:45:23 +11:00 committed by GitHub
parent a3b9dd67a8
commit 79c57aa8da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 232 additions and 59 deletions

View File

@ -53,9 +53,9 @@ class RefundPaymentRequest extends Request
if(isset($input['credits']))
{
foreach($input['credits'] as $key => $credit)
$input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($credit['credit_id']);
unset($input['credits']);
// foreach($input['credits'] as $key => $credit)
// $input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($credit['credit_id']);
}

View File

@ -60,8 +60,12 @@ class StorePaymentRequest extends Request
if (isset($input['credits']) && is_array($input['credits']) !== false) {
foreach ($input['credits'] as $key => $value) {
$input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']);
$credits_total += $value['amount'];
if(array_key_exists('credit_id', $input['credits'][$key]))
{
$input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']);
$credits_total += $value['amount'];
}
}
}
@ -69,7 +73,7 @@ class StorePaymentRequest extends Request
$input['credits'] = null;
}
if(!isset($input['amount'])){
if(!isset($input['amount']) || $input['amount'] == 0){
$input['amount'] = $invoices_total - $credits_total;
}

View File

@ -63,19 +63,19 @@ class ValidRefundableRequest implements Rule
}
if($payment->credits()->exists())
{
foreach($payment->credits as $paymentable_credit)
$this->checkCredit($paymentable_credit, $request_credits);
}
// if($payment->credits()->exists())
// {
// foreach($payment->credits as $paymentable_credit)
// $this->checkCredit($paymentable_credit, $request_credits);
// }
foreach($request_invoices as $request_invoice)
$this->checkInvoiceIsPaymentable($request_invoice, $payment);
foreach($request_credits as $request_credit)
$this->checkCreditIsPaymentable($request_credit, $payment);
// foreach($request_credits as $request_credit)
// $this->checkCreditIsPaymentable($request_credit, $payment);
if(strlen($this->error_msg) > 0 )

View File

@ -14,6 +14,7 @@ namespace App\Http\ValidationRules;
use App\Libraries\MultiDB;
use App\Models\Credit;
use App\Models\User;
use App\Utils\Traits\MakesHash;
use Illuminate\Contracts\Validation\Rule;
/**
@ -22,6 +23,7 @@ use Illuminate\Contracts\Validation\Rule;
*/
class ValidCreditsPresentRule implements Rule
{
use MakesHash;
/**
* @param string $attribute
@ -38,7 +40,7 @@ class ValidCreditsPresentRule implements Rule
*/
public function message()
{
return 'Attempting to use one or more invalid credits';
return 'Insufficient balance on credit.';
}
@ -51,9 +53,9 @@ class ValidCreditsPresentRule implements Rule
{
foreach(request()->input('credits') as $credit)
{
$cred = Credit::find($credit['invoice_id']);
$cred = Credit::find($this->decodePrimaryKey($credit['credit_id']));
if($cred->balance >= $credit['amount'])
if($cred->balance == 0)
return false;
}
}

View File

@ -62,8 +62,8 @@ class UpdateOrCreateProduct implements ShouldQueue
$product->product_key = $item->product_key;
$product->notes = isset($item->notes) ? $item->notes : '';
$product->cost = isset($item->cost) ? $item->cost : 0;
$product->price = isset($item->price) ? $item->price : 0;
//$product->cost = isset($item->cost) ? $item->cost : 0; //this value shouldn't be updated.
$product->price = isset($item->price) ? $item->cost : 0;
$product->quantity = isset($item->quantity) ? $item->quantity : 0;
$product->tax_name1 = isset($item->tax_name1) ? $item->tax_name1 : '';
$product->tax_rate1 = isset($item->tax_rate1) ? $item->tax_rate1 : 0 ;

View File

@ -15,6 +15,7 @@ use App\Events\Payment\PaymentWasCreated;
use App\Factory\CreditFactory;
use App\Jobs\Client\UpdateClientPaidToDate;
use App\Jobs\Company\UpdateCompanyLedgerWithPayment;
use App\Jobs\Credit\ApplyCreditPayment;
use App\Jobs\Invoice\ApplyClientPayment;
use App\Jobs\Invoice\ApplyInvoicePayment;
use App\Jobs\Invoice\UpdateInvoicePayment;
@ -117,7 +118,7 @@ class PaymentRepository extends BaseRepository
$credit = Credit::whereId($paid_credit['credit_id'])->first();
if ($credit)
ApplyCreditPayment::dispatchNow($paid_credit, $payment, $paid_credit['amount'], $credit->company);
ApplyCreditPayment::dispatchNow($credit, $payment, $paid_credit['amount'], $credit->company);
}
}
@ -126,6 +127,8 @@ class PaymentRepository extends BaseRepository
$invoice_totals -= $credit_totals;
//$payment->amount = $invoice_totals; //creates problems when setting amount like this.
if ($invoice_totals == $payment->amount)
$payment->applied += $payment->amount;
elseif ($invoice_totals < $payment->amount)

View File

@ -41,6 +41,10 @@ class PaymentTest extends TestCase
parent::setUp();
$this->withoutMiddleware(
ThrottleRequests::class
);
Session::start();
$this->faker = \Faker\Factory::create();

View File

@ -5,6 +5,7 @@ namespace Tests\Feature;
use App\DataMapper\ClientSettings;
use App\DataMapper\CompanySettings;
use App\Factory\ClientFactory;
use App\Factory\CreditFactory;
use App\Factory\InvoiceFactory;
use App\Factory\PaymentFactory;
use App\Helpers\Invoice\InvoiceSum;
@ -18,6 +19,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Session;
use Illuminate\Validation\ValidationException;
@ -41,6 +43,10 @@ class RefundTest extends TestCase
parent::setUp();
$this->withoutMiddleware(
ThrottleRequests::class
);
Session::start();
$this->faker = \Faker\Factory::create();
@ -488,8 +494,135 @@ class RefundTest extends TestCase
}
/**
* Test refunds where payments include credits
*
* $10 invoice
* $10 credit
* $50 credit card payment
*
*
* result should be
*
* payment.applied = 10
* credit.balance = 0
*
*/
public function testRefundWhereCreditsArePresent()
{
$client = ClientFactory::create($this->company->id, $this->user->id);
$client->save();
$this->invoice = InvoiceFactory::create($this->company->id,$this->user->id);//stub the company and user_id
$this->invoice->client_id = $client->id;
$this->invoice->status_id = Invoice::STATUS_SENT;
$this->invoice->line_items = $this->buildLineItems();
$this->invoice->uses_inclusive_taxes = false;
$this->invoice->save();
$this->invoice_calc = new InvoiceSum($this->invoice);
$this->invoice_calc->build();
$this->invoice = $this->invoice_calc->getInvoice();
$this->invoice->save();
$this->credit = CreditFactory::create($this->company->id,$this->user->id);
$this->credit->client_id = $this->client->id;
$this->credit->line_items = $this->buildLineItems();
$this->credit->amount = 10;
$this->credit->balance = 10;
$this->credit->uses_inclusive_taxes = false;
$this->credit->save();
$data = [
'amount' => 50,
'client_id' => $client->hashed_id,
'invoices' => [
[
'invoice_id' => $this->invoice->hashed_id,
'amount' => $this->invoice->amount
],
],
'credits' => [
[
'credit_id' => $this->credit->hashed_id,
'amount' => $this->credit->amount
],
],
'date' => '2020/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);
\Log::error($message);
}
$arr = $response->json();
$response->assertStatus(200);
$payment_id = $arr['data']['id'];
$this->assertEquals(50, $arr['data']['amount']);
$payment = Payment::whereId($this->decodePrimaryKey($payment_id))->first();
$this->assertNotNull($payment);
$this->assertNotNull($payment->invoices());
$this->assertEquals(1, $payment->invoices()->count());
$data = [
'id' => $this->encodePrimaryKey($payment->id),
'amount' => 50,
'invoices' => [
[
'invoice_id' => $this->invoice->hashed_id,
'amount' => $this->invoice->amount
],
],
'date' => '2020/12/12',
];
$response = false;
try{
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/payments/refund', $data);
}catch(ValidationException $e)
{
$message = json_decode($e->validator->getMessageBag(),1);
\Log::error("refund message error");
\Log::error($message);
}
$response->assertStatus(200);
$arr = $response->json();
$payment = Payment::find($this->decodePrimaryKey($arr['data']['id']));
// \Log::error(print_r($payment->paymentables->toArray(),1));
}
/*Additional scenarios*/
/*Test refunds where payments include credits*/
}

View File

@ -15,6 +15,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Request;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use Tests\MockAccountData;
@ -34,6 +35,10 @@ class TemplateApiTest extends TestCase
{
parent::setUp();
$this->withoutMiddleware(
ThrottleRequests::class
);
$this->makeTestData();
Session::start();

View File

@ -36,6 +36,10 @@ class UserTest extends TestCase
{
parent::setUp();
$this->withoutMiddleware(
ThrottleRequests::class
);
Session::start();
$this->faker = \Faker\Factory::create();

View File

@ -17,6 +17,7 @@ use App\Models\User;
use Illuminate\Foundation\Testing\Concerns\InteractsWithDatabase;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Http\UploadedFile;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Facades\Log;
use Tests\MockAccountData;
use Tests\TestCase;
@ -35,6 +36,10 @@ class UploadFileTest extends TestCase
parent::setUp();
$this->makeTestData();
$this->withoutMiddleware(
ThrottleRequests::class
);
}

View File

@ -168,7 +168,7 @@ trait MockAccountData
$this->invoice->client_id = $this->client->id;
$this->invoice->line_items = $this->buildLineItems();
$this->invoice->uses_inclusive_Taxes = false;
$this->invoice->uses_inclusive_taxes = false;
$this->invoice->save();
@ -185,7 +185,10 @@ trait MockAccountData
$this->credit->client_id = $this->client->id;
$this->credit->line_items = $this->buildLineItems();
$this->credit->uses_inclusive_Taxes = false;
$this->credit->amount = 10;
$this->credit->balance = 10;
$this->credit->uses_inclusive_taxes = false;
$this->credit->save();

View File

@ -30,11 +30,21 @@ class ImportTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $migration_array;
public function setUp(): void
{
parent::setUp();
$this->makeTestData();
$migration_file = base_path() . '/tests/Unit/Migration/migration.json';
$handle = fopen($migration_file, "r");
$migration_file = fread($handle, filesize($migration_file));
fclose($handle);
$this->migration_array = json_decode($migration_file,1);
}
public function testImportClassExists()
@ -95,11 +105,11 @@ class ImportTest extends TestCase
$original_count = Invoice::count();
$migration_file = base_path() . '/tests/Unit/Migration/migration.json';
$migration_array = json_decode(file_get_contents($migration_file), 1);
Import::dispatchNow($migration_array, $this->company, $this->user);
//$this->migration_array = json_decode(file_get_contents($migration_file), 1);
Import::dispatchNow($this->migration_array, $this->company, $this->user);
$this->assertGreaterThan($original_count, Invoice::count());
}
@ -122,13 +132,13 @@ class ImportTest extends TestCase
public function testImportFileExists()
{
$migration_file = base_path() . '/tests/Unit/Migration/migration.json';
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
$this->assertTrue(file_exists($migration_file));
// $this->assertTrue(file_exists($migration_file));
$migration_array = json_decode(file_get_contents($migration_file), 1);
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
$this->assertGreaterThan(1, count($migration_array));
$this->assertGreaterThan(1, count($this->migration_array));
}
@ -139,11 +149,11 @@ class ImportTest extends TestCase
$this->invoice->forceDelete();
$migration_file = base_path() . '/tests/Unit/Migration/migration.json';
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
$migration_array = json_decode(file_get_contents($migration_file), 1);
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
Import::dispatchNow($migration_array, $this->company, $this->user);
Import::dispatchNow($this->migration_array, $this->company, $this->user);
$this->assertTrue(true);
}
@ -180,11 +190,11 @@ class ImportTest extends TestCase
$this->invoice->forceDelete();
$migration_file = base_path() . '/tests/Unit/Migration/migration.json';
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
$migration_array = json_decode(file_get_contents($migration_file), 1);
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
Import::dispatchNow($migration_array, $this->company, $this->user);
Import::dispatchNow($this->migration_array, $this->company, $this->user);
$this->assertGreaterThan($original_number, Invoice::count());
@ -198,9 +208,9 @@ class ImportTest extends TestCase
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
// $migration_array = json_decode(file_get_contents($migration_file), 1);
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
// Import::dispatchNow($migration_array, $this->company, $this->user);
// Import::dispatchNow($this->migration_array, $this->company, $this->user);
// $this->assertGreaterThan($original_number, Invoice::count());
@ -232,9 +242,9 @@ class ImportTest extends TestCase
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
// $migration_array = json_decode(file_get_contents($migration_file), 1);
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
// Import::dispatchNow($migration_array, $this->company, $this->user);
// Import::dispatchNow($this->migration_array, $this->company, $this->user);
// $this->assertGreaterThan($original_number, Invoice::count());
@ -254,11 +264,11 @@ class ImportTest extends TestCase
$this->invoice->forceDelete();
$migration_file = base_path() . '/tests/Unit/Migration/migration.json';
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
$migration_array = json_decode(file_get_contents($migration_file), 1);
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
Import::dispatchNow($migration_array, $this->company, $this->user);
Import::dispatchNow($this->migration_array, $this->company, $this->user);
$this->assertGreaterThan($original_count, Payment::count());
}
@ -285,11 +295,11 @@ class ImportTest extends TestCase
$this->invoice->forceDelete();
$migration_file = base_path() . '/tests/Unit/Migration/migration.json';
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
$migration_array = json_decode(file_get_contents($migration_file), 1);
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
Import::dispatchNow($migration_array, $this->company, $this->user);
Import::dispatchNow($this->migration_array, $this->company, $this->user);
$this->assertGreaterThan($original_count, Credit::count());
}
@ -319,16 +329,16 @@ class ImportTest extends TestCase
{
$this->invoice->forceDelete();
$migration_file = base_path() . '/tests/Unit/Migration/migration.json';
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
$migration_array = json_decode(file_get_contents($migration_file), 1);
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
Import::dispatchNow($migration_array, $this->company, $this->user);
Import::dispatchNow($this->migration_array, $this->company, $this->user);
$differences = [];
foreach ($migration_array['invoices'] as $key => $invoices) {
foreach ($this->migration_array['invoices'] as $key => $invoices) {
$record = Invoice::whereNumber($invoices['number'])
->whereAmount($invoices['amount'])
->whereBalance($invoices['balance'])
@ -339,7 +349,7 @@ class ImportTest extends TestCase
}
}
foreach ($migration_array['users'] as $key => $user) {
foreach ($this->migration_array['users'] as $key => $user) {
$record = User::whereEmail($user['email'])->first();
if (!$record) {
@ -347,7 +357,7 @@ class ImportTest extends TestCase
}
}
foreach ($migration_array['tax_rates'] as $key => $tax_rate) {
foreach ($this->migration_array['tax_rates'] as $key => $tax_rate) {
$record = TaxRate::whereName($tax_rate['name'])
->where('rate', $tax_rate['rate'])
->first();
@ -357,7 +367,7 @@ class ImportTest extends TestCase
}
}
foreach ($migration_array['clients'] as $key => $client) {
foreach ($this->migration_array['clients'] as $key => $client) {
$record = Client::whereName($client['name'])
->whereCity($client['city'])
// ->where('paid_to_date', $client['paid_to_date']) // TODO: Doesn't work. Need debugging.
@ -368,7 +378,7 @@ class ImportTest extends TestCase
}
}
foreach ($migration_array['products'] as $key => $product) {
foreach ($this->migration_array['products'] as $key => $product) {
$record = Product::where('product_key', $product['product_key'])
->first();
@ -377,7 +387,7 @@ class ImportTest extends TestCase
}
}
foreach ($migration_array['quotes'] as $key => $quote) {
foreach ($this->migration_array['quotes'] as $key => $quote) {
$record = Quote::whereNumber($quote['number'])
->whereIsAmountDiscount($quote['is_amount_discount'])
->whereDueDate($quote['due_date'])
@ -388,7 +398,7 @@ class ImportTest extends TestCase
}
}
foreach ($migration_array['payments'] as $key => $payment) {
foreach ($this->migration_array['payments'] as $key => $payment) {
$record = Payment::whereAmount($payment['amount'])
->whereApplied($payment['applied'])
->whereRefunded($payment['refunded'])
@ -399,7 +409,7 @@ class ImportTest extends TestCase
}
}
/*foreach ($migration_array['credits'] as $key => $credit) {
/*foreach ($this->migration_array['credits'] as $key => $credit) {
// The Import::processCredits() does insert the credit record with number: 0053,
// .. however this part of the code doesn't see it at all.
@ -421,11 +431,11 @@ class ImportTest extends TestCase
$original = ClientContact::count();
$migration_file = base_path() . '/tests/Unit/Migration/migration.json';
// $migration_file = base_path() . '/tests/Unit/Migration/migration.json';
$migration_array = json_decode(file_get_contents($migration_file), 1);
// $this->migration_array = json_decode(file_get_contents($migration_file), 1);
Import::dispatchNow($migration_array, $this->company, $this->user);
Import::dispatchNow($this->migration_array, $this->company, $this->user);
$this->assertGreaterThan($original, ClientContact::count());
}