From fe5a97e17434beb49da1fbac7ee6e50404aef73b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 18 Nov 2019 21:46:01 +1100 Subject: [PATCH] Activity API fixes + Payments API (#3076) * Fixes for Store Payment Validation * Tests for Payments * Use custom validator to ensure payments are made ONLY to payable invoices * Working on custom payment validators * Update Client balance * fixes for client balance * Fixes for activity API --- app/Http/Controllers/ActivityController.php | 33 ++- app/Http/Controllers/PaymentController.php | 35 +++ .../Requests/Payment/StorePaymentRequest.php | 38 ++- .../ValidPayableInvoicesRule.php | 56 ++++ app/Jobs/Client/UpdateClientBalance.php | 51 ++++ app/Jobs/Invoice/UpdateInvoicePayment.php | 17 +- app/Models/Activity.php | 18 +- app/Models/GatewayType.php | 2 +- app/Models/Payment.php | 5 +- app/Repositories/PaymentRepository.php | 21 +- app/Transformers/ActivityTransformer.php | 16 +- app/Transformers/PaymentTransformer.php | 7 +- database/factories/PaymentFactory.php | 2 + tests/Feature/PaymentTest.php | 275 +++++++++++------- 14 files changed, 413 insertions(+), 163 deletions(-) create mode 100644 app/Http/ValidationRules/ValidPayableInvoicesRule.php create mode 100644 app/Jobs/Client/UpdateClientBalance.php diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php index ca24f947b11a..66ff2b2da76c 100644 --- a/app/Http/Controllers/ActivityController.php +++ b/app/Http/Controllers/ActivityController.php @@ -29,9 +29,38 @@ class ActivityController extends BaseController } /** - * Display a listing of the resource. + * @OA\Get( + * path="/api/v1/actvities", + * operationId="getActivities", + * tags={"actvities"}, + * summary="Gets a list of actvities", + * description="Lists all activities", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter(ref="#/components/parameters/index"), + * @OA\Response( + * response=200, + * description="A list of actvities", + * @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/Activity"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) * - * @return \Illuminate\Http\Response */ public function index() { diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index defd99cf4e52..e83d6204e8a8 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -185,6 +185,40 @@ class PaymentController extends BaseController * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\RequestBody( + * description="The payment request", + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * type="object", + * @OA\Property( + * property="amount", + * description="The payment amount", + * type="number", + * format="float", + * ), + * @OA\Property( + * property="payment_date", + * example="2019/12/1", + * description="The payment date", + * type="string", + * ), + * @OA\Property( + * property="transation_reference", + * example="sdfasdfs98776d6kbkfd", + * description="The transaction reference for the payment", + * type="string", + * ), + * @OA\Property( + * property="invoices", + * example="j7s76d,s8765afk,D8fj3Sfdj", + * description="A comma separated list of invoice hashed ids that this payment relates to", + * type="string", + * ) + * ) + * ) + * ), * @OA\Response( * response=200, * description="Returns the saved Payment object", @@ -449,6 +483,7 @@ class PaymentController extends BaseController public function destroy(DestroyPaymentRequest $request, Payment $payment) { + $payment->is_deleted = true; $payment->delete(); return response()->json([], 200); diff --git a/app/Http/Requests/Payment/StorePaymentRequest.php b/app/Http/Requests/Payment/StorePaymentRequest.php index dff715924dbb..10987a8bd671 100644 --- a/app/Http/Requests/Payment/StorePaymentRequest.php +++ b/app/Http/Requests/Payment/StorePaymentRequest.php @@ -12,12 +12,14 @@ namespace App\Http\Requests\Payment; use App\Http\Requests\Request; +use App\Http\ValidationRules\ValidPayableInvoicesRule; use App\Models\Payment; use App\Utils\Traits\MakesHash; class StorePaymentRequest extends Request { use MakesHash; + /** * Determine if the user is authorized to make this request. * @@ -26,41 +28,47 @@ class StorePaymentRequest extends Request public function authorize() : bool { + return auth()->user()->can('create', Payment::class); + } public function rules() { $this->sanitize(); - return [ - 'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx', - 'client_id' => 'integer|nullable', - 'payment_type_id' => 'integer|nullable', - 'amount' => 'numeric', + $rules = [ + 'amount' => 'numeric|required', 'payment_date' => 'required', + 'client_id' => 'required', + 'invoices' => 'required', + 'invoices' => new ValidPayableInvoicesRule(), ]; + + return $rules; + } public function sanitize() { - $input = $this->all(); - if(isset($input['invoices'])) - $input['invoices'] = $this->transformKeys(array_column($input['invoices']), 'id'); + if(isset($input['client_id'])) + $input['client_id'] = $this->decodePrimaryKey($input['client_id']); - $this->replace($input); + if(isset($input['invoices'])) + $input['invoices'] = $this->transformKeys(explode(",", $input['invoices'])); + + if(is_array($input['invoices']) === false) + $input['invoices'] = null; + + + $this->replace($input); return $this->all(); - } - - public function messages() - { } -} - +} \ No newline at end of file diff --git a/app/Http/ValidationRules/ValidPayableInvoicesRule.php b/app/Http/ValidationRules/ValidPayableInvoicesRule.php new file mode 100644 index 000000000000..8c8550d5e9ca --- /dev/null +++ b/app/Http/ValidationRules/ValidPayableInvoicesRule.php @@ -0,0 +1,56 @@ +transformKeys(explode(",",$value)))->get(); + + if(!$invoices || $invoices->count() == 0) + return false; + + foreach ($invoices as $invoice) { + + if(! $invoice->isPayable()) + return false; + } + + return true; + } + + /** + * @return string + */ + public function message() + { + return "One or more of these invoices have been paid"; + } + +} diff --git a/app/Jobs/Client/UpdateClientBalance.php b/app/Jobs/Client/UpdateClientBalance.php new file mode 100644 index 000000000000..31c75b4c2444 --- /dev/null +++ b/app/Jobs/Client/UpdateClientBalance.php @@ -0,0 +1,51 @@ +amount = $amount; + $this->client = $client; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + + $this->client->balance += $this->amount; + $this->client->paid_to_date += $this->amount; + $this->client->save(); + + } +} diff --git a/app/Jobs/Invoice/UpdateInvoicePayment.php b/app/Jobs/Invoice/UpdateInvoicePayment.php index e2f7b432febc..c489bf5e28fb 100644 --- a/app/Jobs/Invoice/UpdateInvoicePayment.php +++ b/app/Jobs/Invoice/UpdateInvoicePayment.php @@ -11,6 +11,7 @@ namespace App\Jobs\Invoice; +use App\Jobs\Client\UpdateClientBalance; use App\Jobs\Company\UpdateCompanyLedgerWithInvoice; use App\Jobs\Company\UpdateCompanyLedgerWithPayment; use App\Jobs\Util\SystemLogger; @@ -51,7 +52,7 @@ class UpdateInvoicePayment implements ShouldQueue $invoices_total = $invoices->sum('balance'); - /* Simplest scenario*/ + /* Simplest scenario - All invoices are paid in full*/ if(strval($invoices_total) === strval($this->payment->amount)) { $invoices->each(function ($invoice){ @@ -59,15 +60,18 @@ class UpdateInvoicePayment implements ShouldQueue UpdateCompanyLedgerWithPayment::dispatchNow($this->payment, ($invoice->balance*-1)); $invoice->clearPartial(); $invoice->updateBalance($invoice->balance*-1); - + + UpdateClientBalance::dispatchNow($this->payment->client, $invoice->balance*-1); + }); } + /*Combination of partials and full invoices are being paid*/ else { $total = 0; - + /* Calculate the grand total of the invoices*/ foreach($invoices as $invoice) { @@ -78,7 +82,7 @@ class UpdateInvoicePayment implements ShouldQueue } - /* test if there is a batch of partial invoices that have been paid */ + /*Test if there is a batch of partial invoices that have been paid */ if($this->payment->amount == $total) { @@ -91,6 +95,8 @@ class UpdateInvoicePayment implements ShouldQueue $invoice->clearPartial(); $invoice->setDueDate(); $invoice->setStatus(Invoice::STATUS_PARTIAL); + + UpdateClientBalance::dispatchNow($this->payment->client, $invoice->partial*-1); } else @@ -98,6 +104,9 @@ class UpdateInvoicePayment implements ShouldQueue UpdateCompanyLedgerWithPayment::dispatchNow($this->payment, ($invoice->balance*-1)); $invoice->clearPartial(); $invoice->updateBalance($invoice->balance*-1); + + UpdateClientBalance::dispatchNow($this->payment->client, $invoice->balance*-1); + } }); diff --git a/app/Models/Activity.php b/app/Models/Activity.php index b90a895760df..6259804c1d43 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -120,18 +120,18 @@ class Activity extends StaticModel return $this->belongsTo(Payment::class)->withTrashed(); } - public function task() - { - return $this->belongsTo(Task::class)->withTrashed(); - } + // public function task() + // { + // return $this->belongsTo(Task::class)->withTrashed(); + // } - public function expense() - { - return $this->belongsTo(Expense::class)->withTrashed(); - } + // public function expense() + // { + // return $this->belongsTo(Expense::class)->withTrashed(); + // } public function company() { - return $this->belongsTo(Company::class)->withTrashed(); + return $this->belongsTo(Company::class); } } diff --git a/app/Models/GatewayType.php b/app/Models/GatewayType.php index 49a4a4c646a3..a7c78ba04d01 100644 --- a/app/Models/GatewayType.php +++ b/app/Models/GatewayType.php @@ -22,7 +22,7 @@ class GatewayType extends StaticModel const CREDIT_CARD = 1; const BANK_TRANSFER = 2; const PAYPAL = 3; - const BITCOIN = 4; + const CRYPTO = 4; const DWOLLA = 5; const CUSTOM1 = 6; const ALIPAY = 7; diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 7f0013382bf1..dc83b320c28f 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -18,13 +18,15 @@ use App\Utils\Number; use App\Utils\Traits\MakesDates; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class Payment extends BaseModel { use MakesHash; use Filterable; use MakesDates; - + use SoftDeletes; + const STATUS_PENDING = 1; const STATUS_VOIDED = 2; const STATUS_FAILED = 3; @@ -147,6 +149,7 @@ class Payment extends BaseModel public function resolveRouteBinding($value) { return $this + ->withTrashed() ->where('id', $this->decodePrimaryKey($value))->firstOrFail(); } } diff --git a/app/Repositories/PaymentRepository.php b/app/Repositories/PaymentRepository.php index 88a8c72b55cf..6cc167c49c44 100644 --- a/app/Repositories/PaymentRepository.php +++ b/app/Repositories/PaymentRepository.php @@ -11,6 +11,10 @@ namespace App\Repositories; +use App\Events\Payment\PaymentWasCreated; +use App\Jobs\Company\UpdateCompanyLedgerWithPayment; +use App\Jobs\Invoice\UpdateInvoicePayment; +use App\Models\Invoice; use App\Models\Payment; use Illuminate\Http\Request; @@ -20,7 +24,6 @@ use Illuminate\Http\Request; class PaymentRepository extends BaseRepository { - public function getClassName() { return Payment::class; @@ -30,20 +33,24 @@ class PaymentRepository extends BaseRepository { $payment->fill($request->input()); + + $payment->save(); if($request->input('invoices')) { $invoices = Invoice::whereIn('id', $request->input('invoices'))->get(); - + + $payment->invoices()->saveMany($invoices); + } - //parse invoices[] and attach to paymentables - //parse invoices[] and apply payments and subfunctions - - $payment->save(); - + event(new PaymentWasCreated($payment)); + + UpdateInvoicePayment::dispatchNow($payment); + return $payment; + } } \ No newline at end of file diff --git a/app/Transformers/ActivityTransformer.php b/app/Transformers/ActivityTransformer.php index ea72b7528583..9a0eca98cec6 100644 --- a/app/Transformers/ActivityTransformer.php +++ b/app/Transformers/ActivityTransformer.php @@ -27,17 +27,17 @@ class ActivityTransformer extends EntityTransformer return [ 'id' => (string) $this->encodePrimaryKey($activity->id), 'activity_type_id' => (string) $activity->activity_type_id, - 'client_id' => $activity->client ? (string) $activity->client->id : '', - 'company_id' => $activity->company ? (string) $activity->company->id : '', + 'client_id' => $activity->client ? (string) $this->encodePrimaryKey($activity->client->id) : '', + 'company_id' => $activity->company ? (string) $this->encodePrimaryKey($activity->company->id) : '', 'user_id' => (string) $activity->user_id, - 'invoice_id' => $activity->invoice ? (string) $activity->invoice->id : '', - 'payment_id' => $activity->payment ? (string) $activity->payment->id : '', - 'credit_id' => $activity->credit ? (string) $activity->credit->id : '', + 'invoice_id' => $activity->invoice ? (string) $this->encodePrimaryKey($activity->invoice->id) : '', + 'payment_id' => $activity->payment ? (string) $this->encodePrimaryKey($activity->payment->id) : '', + 'credit_id' => $activity->credit ? (string) $this->encodePrimaryKey($activity->credit->id) : '', 'updated_at' => $activity->updated_at, - 'expense_id' => $activity->expense_id ? (string) $activity->expense->id : '', + 'expense_id' => $activity->expense_id ? (string) $this->encodePrimaryKey($activity->expense->id) : '', 'is_system' => (bool) $activity->is_system, - 'contact_id' => $activity->contact_id ? (string) $activity->contact->id : '', - 'task_id' => $activity->task_id ? (string) $activity->task->id : '', + 'contact_id' => $activity->contact_id ? (string) $this->encodePrimaryKey($activity->contact->id) : '', + 'task_id' => $activity->task_id ? (string) $this->encodePrimaryKey($activity->task->id) : '', 'notes' => $activity->notes ? (string) $activity->notes : '', 'ip' => (string) $activity->ip, diff --git a/app/Transformers/PaymentTransformer.php b/app/Transformers/PaymentTransformer.php index efc4ce624aec..567cd2ace879 100644 --- a/app/Transformers/PaymentTransformer.php +++ b/app/Transformers/PaymentTransformer.php @@ -27,7 +27,7 @@ class PaymentTransformer extends EntityTransformer protected $availableIncludes = [ 'client', - 'invoice', + 'invoices', ]; public function __construct($serializer = null) @@ -37,11 +37,11 @@ class PaymentTransformer extends EntityTransformer } - public function includeInvoice(Payment $payment) + public function includeInvoices(Payment $payment) { $transformer = new InvoiceTransformer($this->serializer); - return $this->includeItem($payment->invoice, $transformer, Invoice::class); + return $this->includeCollection($payment->invoices, $transformer, Invoice::class); } public function includeClient(Payment $payment) @@ -65,6 +65,7 @@ class PaymentTransformer extends EntityTransformer 'is_deleted' => (bool) $payment->is_deleted, 'payment_type_id' => (string) $payment->payment_type_id ?: '', 'invitation_id' => (string) $payment->invitation_id ?: '', + 'client_id' => (string) $this->encodePrimaryKey($payment->client_id), /* 'private_notes' => $payment->private_notes ?: '', 'exchange_rate' => (float) $payment->exchange_rate, diff --git a/database/factories/PaymentFactory.php b/database/factories/PaymentFactory.php index d42007047be2..32201adb5e56 100644 --- a/database/factories/PaymentFactory.php +++ b/database/factories/PaymentFactory.php @@ -6,6 +6,7 @@ use App\Models\Payment; use Faker\Generator as Faker; $factory->define(App\Models\Payment::class, function (Faker $faker) { + return [ 'is_deleted' => false, 'amount' => $faker->numberBetween(1,10), @@ -14,6 +15,7 @@ $factory->define(App\Models\Payment::class, function (Faker $faker) { 'payment_type_id' => Payment::TYPE_CREDIT_CARD, 'status_id' => Payment::STATUS_COMPLETED ]; + }); \ No newline at end of file diff --git a/tests/Feature/PaymentTest.php b/tests/Feature/PaymentTest.php index 2ab486d26994..6fd91d3e7b6a 100644 --- a/tests/Feature/PaymentTest.php +++ b/tests/Feature/PaymentTest.php @@ -4,8 +4,13 @@ namespace Tests\Feature; use App\DataMapper\ClientSettings; use App\DataMapper\CompanySettings; +use App\Factory\ClientFactory; +use App\Factory\InvoiceFactory; +use App\Factory\PaymentFactory; +use App\Helpers\Invoice\InvoiceSum; use App\Models\Account; use App\Models\Client; +use App\Models\Invoice; use App\Models\Payment; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; @@ -15,6 +20,8 @@ use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Session; +use Illuminate\Validation\ValidationException; +use Tests\MockAccountData; use Tests\TestCase; /** @@ -27,7 +34,7 @@ class PaymentTest extends TestCase use MakesHash; use DatabaseTransactions; - + use MockAccountData; public function setUp() :void { @@ -39,67 +46,40 @@ class PaymentTest extends TestCase Model::reguard(); + $this->makeTestData(); + $this->withoutExceptionHandling(); } public function testPaymentList() { - $data = [ - 'first_name' => $this->faker->firstName, - 'last_name' => $this->faker->lastName, - 'name' => $this->faker->company, - 'email' => $this->faker->unique()->safeEmail, - 'password' => 'ALongAndBrilliantPassword123', - '_token' => csrf_token(), - 'privacy_policy' => 1, - 'terms_of_service' => 1 - ]; - $response = $this->withHeaders([ - 'X-API-SECRET' => config('ninja.api_secret'), - ])->post('/api/v1/signup?include=account', $data); - - $acc = $response->json(); - - $account = Account::find($this->decodePrimaryKey($acc['data'][0]['account']['id'])); - - $company_token = $account->default_company->tokens()->first(); - $token = $company_token->token; - $company = $company_token->company; - - $user = $company_token->user; - - $this->assertNotNull($company_token); - $this->assertNotNull($token); - $this->assertNotNull($user); - $this->assertNotNull($company); - //$this->assertNotNull($user->token->company); - - factory(\App\Models\Client::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id])->each(function ($c) use ($user, $company){ + factory(\App\Models\Client::class, 1)->create(['user_id' => $this->user->id, 'company_id' => $this->company->id])->each(function ($c) { factory(\App\Models\ClientContact::class,1)->create([ - 'user_id' => $user->id, + 'user_id' => $this->user->id, 'client_id' => $c->id, - 'company_id' => $company->id, + 'company_id' => $this->company->id, 'is_primary' => 1 ]); factory(\App\Models\ClientContact::class,1)->create([ - 'user_id' => $user->id, + 'user_id' => $this->user->id, 'client_id' => $c->id, - 'company_id' => $company->id + 'company_id' => $this->company->id ]); }); + $client = Client::all()->first(); - factory(\App\Models\Payment::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id, 'client_id' => $client->id]); + factory(\App\Models\Payment::class, 1)->create(['user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $client->id]); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $token, + 'X-API-TOKEN' => $this->token, ])->get('/api/v1/payments'); $response->assertStatus(200); @@ -108,95 +88,164 @@ class PaymentTest extends TestCase public function testPaymentRESTEndPoints() { - $data = [ - 'first_name' => $this->faker->firstName, - 'last_name' => $this->faker->lastName, - 'name' => $this->faker->company, - 'email' => $this->faker->unique()->safeEmail, - 'password' => 'ALongAndBrilliantPassword123', - '_token' => csrf_token(), - 'privacy_policy' => 1, - 'terms_of_service' => 1 - ]; + factory(\App\Models\Payment::class, 1)->create(['user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id]); + + $Payment = Payment::all()->last(); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - ])->post('/api/v1/signup?include=account', $data); - - $acc = $response->json(); - - $account = Account::find($this->decodePrimaryKey($acc['data'][0]['account']['id'])); - - $company_token = $account->default_company->tokens()->first(); - $token = $company_token->token; - $company = $company_token->company; - - $user = $company_token->user; - - $this->assertNotNull($company_token); - $this->assertNotNull($token); - $this->assertNotNull($user); - $this->assertNotNull($company); - //$this->assertNotNull($user->token->company); - - factory(\App\Models\Client::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id])->each(function ($c) use ($user, $company){ - - factory(\App\Models\ClientContact::class,1)->create([ - 'user_id' => $user->id, - 'client_id' => $c->id, - 'company_id' => $company->id, - 'is_primary' => 1 - ]); - - factory(\App\Models\ClientContact::class,1)->create([ - 'user_id' => $user->id, - 'client_id' => $c->id, - 'company_id' => $company->id - ]); - - }); - $client = Client::all()->first(); - - factory(\App\Models\Payment::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id, 'client_id' => $client->id]); - - $Payment = Payment::all()->first(); - - $response = $this->withHeaders([ - 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $token, + 'X-API-TOKEN' => $this->token, ])->get('/api/v1/payments/'.$this->encodePrimaryKey($Payment->id)); $response->assertStatus(200); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $token, + 'X-API-TOKEN' => $this->token, ])->get('/api/v1/payments/'.$this->encodePrimaryKey($Payment->id).'/edit'); $response->assertStatus(200); - $Payment_update = [ - 'amount' => 10, - 'payment_date' => Carbon::now() - ]; - - $this->assertNotNull($Payment); - - - $response = $this->withHeaders([ - 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $token, - ])->put('/api/v1/payments/'.$this->encodePrimaryKey($Payment->id), $Payment_update) - ->assertStatus(200); - - $response = $this->withHeaders([ - 'X-API-SECRET' => config('ninja.api_secret'), - 'X-API-TOKEN' => $token, - ])->delete('/api/v1/payments/'.$this->encodePrimaryKey($Payment->id)); - - $response->assertStatus(200); - + } + + public function testStorePaymentWithoutClientId() + { + $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->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(); + + $data = [ + 'amount' => $this->invoice->amount, + 'invoices' => $this->invoice->hashed_id, + 'payment_date' => '2020/12/11', + + ]; + + 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); + + $this->assertTrue(array_key_exists('client_id', $message)); + + } + + + } + + public function testStorePaymentWithClientId() + { + $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(); + + $data = [ + 'amount' => $this->invoice->amount, + 'client_id' => $client->hashed_id, + 'invoices' => $this->invoice->hashed_id, + 'payment_date' => '2020/12/12', + + ]; + + + try { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/payments?include=invoices', $data); + + } + catch(ValidationException $e) { + \Log::error('in the validator'); + $message = json_decode($e->validator->getMessageBag(),1); + \Log::error($message); + $this->assertNotNull($message); + + } + + $arr = $response->json(); + \Log::error($arr); + $response->assertStatus(200); + + + } + + public function testStorePaymentWithNoInvoiecs() + { + $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(); + + $data = [ + 'amount' => $this->invoice->amount, + 'client_id' => $client->hashed_id, + 'invoices' => '', + 'payment_date' => '2020/12/12', + + ]; + + + try { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/payments?include=invoices', $data); + + } + catch(ValidationException $e) { + \Log::error('in the validator'); + $message = json_decode($e->validator->getMessageBag(),1); + \Log::error($message); + $this->assertNotNull($message); + + } + } }