From cda20beb9e5e5d5c48758c871dd06387d55dca67 Mon Sep 17 00:00:00 2001 From: Gunadi Wirawan Date: Sun, 23 Oct 2022 18:34:45 +0800 Subject: [PATCH 1/3] sales return: update email template --- .../return-approval-request-single.blade.php | 222 +++++++++--------- .../return/return-approval-request.blade.php | 221 +++++++++-------- 2 files changed, 221 insertions(+), 222 deletions(-) diff --git a/resources/views/emails/sales/return/return-approval-request-single.blade.php b/resources/views/emails/sales/return/return-approval-request-single.blade.php index 846673e76..7a960ea4e 100644 --- a/resources/views/emails/sales/return/return-approval-request-single.blade.php +++ b/resources/views/emails/sales/return/return-approval-request-single.blade.php @@ -6,51 +6,35 @@ 'approver_id' => $approver->id, 'token' => $approver->token ]; - $urlApprovalQueries = array_merge($urlQueries, ['resource-type' => 'salesReturns']); + $urlApprovalQueries = array_merge($urlQueries, ['resource-type' => 'SalesReturn']); @endphp -
{{ $salesReturns[0]->form->cancellation_status ? 'Cancellation' : '' }} Approval Email
+
Request Approval All

Hello Mrs/Mr/Ms {{ $approver->getFullNameAttribute() }},
- You Have {{ $salesReturns[0]->form->cancellation_status ? 'a cancellation' : 'an' }} approval for Sales Return. we would like to details as follows: + You Have an approval for Sales Return. we would like to details as follows:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Form Number: {{ $salesReturns[0]->form->number ?: '-' }}
Form Date: {{ date('d F Y', strtotime($salesReturns[0]->form->date)) ?: '-' }}
Form Reference: {{ $salesReturns[0]->salesInvoice->form->number ?: '-' }}
Customer: {{ $salesReturns[0]->customer->name ?: '-' }}
Create at: {{ date('d F Y', strtotime($salesReturns[0]->form->date)) ?: '-' }}
Create by: {{ $salesReturns[0]->form->createdBy->getFullNameAttribute() ?: '-' }}
Notes: {{ $salesReturns[0]->form->notes ?: '-' }}
+ + + + + + + + + + + + + + + +
Form Number: {{ optional($form)->number }}
Form Date: {{ optional($form)->date }}
Create at: {{ optional($form)->created }}
- - - - - - + + + + + + + + + - @foreach($salesReturns[0]->items as $item) + @foreach($salesReturns as $salesReturn) + @php + $salesReturnForm = $salesReturn->form; + $urlApprovalQueries['ids'] = $salesReturn->id; + $urlApprovalQueries['crud-type'] = $salesReturn->action; + @endphp - - + + + - - - @endforeach - - - - - - - - - - - - - - - -
NoItem NameQuantity SalesQuantity ReturnPriceDiscountTotalForm DateForm NumberForm ReferenceCustomer + + + + + + +
ItemQuantity Return
+
NoteCreated ByCreated At
{{ $loop->iteration }} - {{ $item->item->name }} + {{ date('d M Y', strtotime($salesReturnForm->date)) }} - {{ $item->quantity_sales }} + + {{ $salesReturnForm->number }} + {{ ' ' }} + {{ + !is_null($salesReturnForm->close_status) + && in_array($salesReturnForm->close_status, [0, 1]) + ? ' - Closed' + : '' + }} - {{ $item->quantity }} + + {{ $salesReturn->salesInvoice->form->number }} + + {{ $salesReturn->customer->name }} + + + + @foreach($salesReturn->items as $item) + @php $borderBottom = !$loop->last ? 'border-bottom: 1px solid black' : ''; @endphp + + + + + + @endforeach + +
+ {{ $item->item->name }} + + {{ $item->quantity }} +
+
+ {{ $item->note }} - {{ number_format($item->price) }} + + {{ $salesReturnForm->createdBy->getFullNameAttribute() }} - {{ number_format($item->discount_value) }} + + {{ date('d M Y, H:i', strtotime($salesReturnForm->created_at)) }} - {{ number_format($item->quantity * ($item->price - $item->discount_value)) }} + +
- Sub Total - - {{ number_format($salesReturns[0]->amount - $salesReturns[0]->tax) }} -
- Taxbase - - {{ number_format($salesReturns[0]->amount - $salesReturns[0]->tax) }} -
- Tax - - {{ number_format($salesReturns[0]->tax) }} -
- Taxbase - - {{ number_format($salesReturns[0]->amount) }} -
- @if (@$url)
+ @php + unset($urlApprovalQueries['crud-type']); + $urlApprovalQueries['ids'] = implode(",", Illuminate\Support\Arr::pluck($salesReturns, 'id')); + @endphp - Check - - - Approve + Approve All - Reject + style="background-color: rgb(238, 238, 238); border: none; color: rgb(83, 83, 83); margin:8px 0; padding: 8px 16px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; "> + Reject All
- @else -

- Open your dashboard to check. -

- @endif
-@stop +@stop \ No newline at end of file diff --git a/resources/views/emails/sales/return/return-approval-request.blade.php b/resources/views/emails/sales/return/return-approval-request.blade.php index 862e811c3..993227362 100644 --- a/resources/views/emails/sales/return/return-approval-request.blade.php +++ b/resources/views/emails/sales/return/return-approval-request.blade.php @@ -6,35 +6,51 @@ 'approver_id' => $approver->id, 'token' => $approver->token ]; - $urlApprovalQueries = array_merge($urlQueries, ['resource-type' => 'SalesReturn']); + $urlApprovalQueries = array_merge($urlQueries, ['resource-type' => 'salesReturns']); @endphp -
Request Approval All
+
{{ $salesReturns[0]->form->cancellation_status ? 'Cancellation' : '' }} Approval Email

Hello Mrs/Mr/Ms {{ $approver->getFullNameAttribute() }},
- You Have an approval for Sales Return. we would like to details as follows: + You Have {{ $salesReturns[0]->form->cancellation_status ? 'a cancellation' : 'an' }} approval for Sales Return. we would like to details as follows:
- - - - - - - - - - - - - - - -
Form Number: {{ optional($form)->number }}
Form Date: {{ optional($form)->date }}
Create at: {{ optional($form)->created }}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Form Number: {{ $salesReturns[0]->form->number ?: '-' }}
Form Date: {{ date('d F Y', strtotime($salesReturns[0]->form->date)) ?: '-' }}
Form Reference: {{ $salesReturns[0]->salesInvoice->form->number ?: '-' }}
Customer: {{ $salesReturns[0]->customer->name ?: '-' }}
Create at: {{ date('d F Y', strtotime($salesReturns[0]->form->date)) ?: '-' }}
Create by: {{ $salesReturns[0]->form->createdBy->getFullNameAttribute() ?: '-' }}
Notes: {{ $salesReturns[0]->form->notes ?: '-' }}
- - - - - - - - - + + + + + + - @foreach($salesReturns as $salesReturn) - @php - $salesReturnForm = $salesReturn->form; - - $urlApprovalQueries['ids'] = $salesReturn->id; - $urlApprovalQueries['crud-type'] = $salesReturn->action; - @endphp + @foreach($salesReturns[0]->items as $item) - - - - - - - - @endforeach + + + + + + + + + + + + + + + +
NoForm DateForm NumberForm ReferenceCustomer - - - - - - -
ItemQuantity Return
-
NoteCreated ByCreated AtItem NameQuantity SalesQuantity ReturnPriceDiscountTotal
{{ $loop->iteration }} - {{ date('d M Y', strtotime($salesReturnForm->date)) }} + {{ $item->item->name }} - {{ $salesReturnForm->number }} - {{ ' ' }} - {{ - !is_null($salesReturnForm->close_status) - && in_array($salesReturnForm->close_status, [0, 1]) - ? ' - Closed' - : '' - }} + + {{ $item->quantity_sales }} - {{ $salesReturn->salesInvoice->form->number }} + + {{ $item->quantity }} - {{ $salesReturn->customer->name }} + + {{ number_format($item->price) }} - - - @foreach($salesReturn->items as $item) - @php $borderBottom = !$loop->last ? 'border-bottom: 1px solid black' : ''; @endphp - - - - - - @endforeach - -
- {{ $item->item->name }} - - {{ $item->quantity }} -
+
+ {{ number_format($item->discount_value) }} - {{ $item->note }} - - {{ $salesReturnForm->createdBy->getFullNameAttribute() }} - - {{ date('d M Y, H:i', strtotime($salesReturnForm->created_at)) }} - - + + {{ number_format($item->quantity * ($item->price - $item->discount_value)) }}
+ Sub Total + + {{ number_format($salesReturns[0]->amount - $salesReturns[0]->tax) }} +
+ Taxbase + + {{ number_format($salesReturns[0]->amount - $salesReturns[0]->tax) }} +
+ Tax + + {{ number_format($salesReturns[0]->tax) }} +
+ Taxbase + + {{ number_format($salesReturns[0]->amount) }} +
+ @if (@$url)
- @php - unset($urlApprovalQueries['crud-type']); - $urlApprovalQueries['ids'] = implode(",", Illuminate\Support\Arr::pluck($salesReturns, 'id')); - @endphp + Check + + - Approve All + Approve - Reject All + style="background-color: rgb(255, 0, 0); border: none; color: white; margin:8px 0; padding: 8px 16px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; "> + Reject
+ @else +

+ Open your dashboard to check. +

+ @endif
@stop From a64fc30fb2b196a1b5e8123093dafe77772e9f0c Mon Sep 17 00:00:00 2001 From: Gunadi Wirawan Date: Sun, 23 Oct 2022 18:42:16 +0800 Subject: [PATCH 2/3] sales return: update email template --- .../return-approval-request-single.blade.php | 222 +++++++++-------- .../return/return-approval-request.blade.php | 224 ++++++++++-------- 2 files changed, 225 insertions(+), 221 deletions(-) diff --git a/resources/views/emails/sales/return/return-approval-request-single.blade.php b/resources/views/emails/sales/return/return-approval-request-single.blade.php index 7a960ea4e..993227362 100644 --- a/resources/views/emails/sales/return/return-approval-request-single.blade.php +++ b/resources/views/emails/sales/return/return-approval-request-single.blade.php @@ -6,35 +6,51 @@ 'approver_id' => $approver->id, 'token' => $approver->token ]; - $urlApprovalQueries = array_merge($urlQueries, ['resource-type' => 'SalesReturn']); + $urlApprovalQueries = array_merge($urlQueries, ['resource-type' => 'salesReturns']); @endphp -
Request Approval All
+
{{ $salesReturns[0]->form->cancellation_status ? 'Cancellation' : '' }} Approval Email

Hello Mrs/Mr/Ms {{ $approver->getFullNameAttribute() }},
- You Have an approval for Sales Return. we would like to details as follows: + You Have {{ $salesReturns[0]->form->cancellation_status ? 'a cancellation' : 'an' }} approval for Sales Return. we would like to details as follows:
- - - - - - - - - - - - - - - -
Form Number: {{ optional($form)->number }}
Form Date: {{ optional($form)->date }}
Create at: {{ optional($form)->created }}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Form Number: {{ $salesReturns[0]->form->number ?: '-' }}
Form Date: {{ date('d F Y', strtotime($salesReturns[0]->form->date)) ?: '-' }}
Form Reference: {{ $salesReturns[0]->salesInvoice->form->number ?: '-' }}
Customer: {{ $salesReturns[0]->customer->name ?: '-' }}
Create at: {{ date('d F Y', strtotime($salesReturns[0]->form->date)) ?: '-' }}
Create by: {{ $salesReturns[0]->form->createdBy->getFullNameAttribute() ?: '-' }}
Notes: {{ $salesReturns[0]->form->notes ?: '-' }}
- - - - - - - - - + + + + + + - @foreach($salesReturns as $salesReturn) - @php - $salesReturnForm = $salesReturn->form; - $urlApprovalQueries['ids'] = $salesReturn->id; - $urlApprovalQueries['crud-type'] = $salesReturn->action; - @endphp + @foreach($salesReturns[0]->items as $item) - - - - - - - - @endforeach + + + + + + + + + + + + + + + +
NoForm DateForm NumberForm ReferenceCustomer - - - - - - -
ItemQuantity Return
-
NoteCreated ByCreated AtItem NameQuantity SalesQuantity ReturnPriceDiscountTotal
{{ $loop->iteration }} - {{ date('d M Y', strtotime($salesReturnForm->date)) }} + {{ $item->item->name }} - {{ $salesReturnForm->number }} - {{ ' ' }} - {{ - !is_null($salesReturnForm->close_status) - && in_array($salesReturnForm->close_status, [0, 1]) - ? ' - Closed' - : '' - }} + + {{ $item->quantity_sales }} - {{ $salesReturn->salesInvoice->form->number }} - - {{ $salesReturn->customer->name }} - - - - @foreach($salesReturn->items as $item) - @php $borderBottom = !$loop->last ? 'border-bottom: 1px solid black' : ''; @endphp - - - - - - @endforeach - -
- {{ $item->item->name }} - - {{ $item->quantity }} -
-
- {{ $item->note }} + + {{ $item->quantity }} - {{ $salesReturnForm->createdBy->getFullNameAttribute() }} + + {{ number_format($item->price) }} - {{ date('d M Y, H:i', strtotime($salesReturnForm->created_at)) }} + + {{ number_format($item->discount_value) }} - + + {{ number_format($item->quantity * ($item->price - $item->discount_value)) }}
+ Sub Total + + {{ number_format($salesReturns[0]->amount - $salesReturns[0]->tax) }} +
+ Taxbase + + {{ number_format($salesReturns[0]->amount - $salesReturns[0]->tax) }} +
+ Tax + + {{ number_format($salesReturns[0]->tax) }} +
+ Taxbase + + {{ number_format($salesReturns[0]->amount) }} +
+ @if (@$url)
- @php - unset($urlApprovalQueries['crud-type']); - $urlApprovalQueries['ids'] = implode(",", Illuminate\Support\Arr::pluck($salesReturns, 'id')); - @endphp + Check + + - Approve All + Approve - Reject All + style="background-color: rgb(255, 0, 0); border: none; color: white; margin:8px 0; padding: 8px 16px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; "> + Reject
+ @else +

+ Open your dashboard to check. +

+ @endif
-@stop \ No newline at end of file +@stop diff --git a/resources/views/emails/sales/return/return-approval-request.blade.php b/resources/views/emails/sales/return/return-approval-request.blade.php index 993227362..5e427af0f 100644 --- a/resources/views/emails/sales/return/return-approval-request.blade.php +++ b/resources/views/emails/sales/return/return-approval-request.blade.php @@ -6,51 +6,35 @@ 'approver_id' => $approver->id, 'token' => $approver->token ]; - $urlApprovalQueries = array_merge($urlQueries, ['resource-type' => 'salesReturns']); + $urlApprovalQueries = array_merge($urlQueries, ['resource-type' => 'SalesReturn']); @endphp -
{{ $salesReturns[0]->form->cancellation_status ? 'Cancellation' : '' }} Approval Email
+
Request Approval All

Hello Mrs/Mr/Ms {{ $approver->getFullNameAttribute() }},
- You Have {{ $salesReturns[0]->form->cancellation_status ? 'a cancellation' : 'an' }} approval for Sales Return. we would like to details as follows: + You Have an approval for Sales Return. we would like to details as follows:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Form Number: {{ $salesReturns[0]->form->number ?: '-' }}
Form Date: {{ date('d F Y', strtotime($salesReturns[0]->form->date)) ?: '-' }}
Form Reference: {{ $salesReturns[0]->salesInvoice->form->number ?: '-' }}
Customer: {{ $salesReturns[0]->customer->name ?: '-' }}
Create at: {{ date('d F Y', strtotime($salesReturns[0]->form->date)) ?: '-' }}
Create by: {{ $salesReturns[0]->form->createdBy->getFullNameAttribute() ?: '-' }}
Notes: {{ $salesReturns[0]->form->notes ?: '-' }}
+ + + + + + + + + + + + + + + +
Form Number: {{ optional($form)->number }}
Form Date: {{ optional($form)->date }}
Create at: {{ optional($form)->created }}
- - + + + + + - - - + + + + - @foreach($salesReturns[0]->items as $item) + @foreach($salesReturns as $salesReturn) + @php + $salesReturnForm = $salesReturn->form; + + $urlApprovalQueries['ids'] = $salesReturn->id; + $urlApprovalQueries['crud-type'] = $salesReturn->action; + @endphp - - - - + + @foreach($salesReturn->items as $item) + + - + + + - + @php + ($first = true); + @endphp + @foreach($salesReturn->items as $item) + @if($first) + @php + ($first = false); + @endphp + @continue + @endif + + - + @endforeach @endforeach - - - - - - - - - - - - - - - -
NoItem NameQuantity SalesForm DateForm NumberForm ReferenceCustomerItem Quantity ReturnPriceDiscountTotalNoteCreated ByCreated At
+ {{ $loop->iteration }} - {{ $item->item->name }} + + {{ date('d M Y', strtotime($salesReturnForm->date)) }} - {{ $item->quantity_sales }} + + {{ $salesReturnForm->number }} + {{ ' ' }} + {{ + !is_null($salesReturnForm->close_status) + && in_array($salesReturnForm->close_status, [0, 1]) + ? ' - Closed' + : '' + }} + + {{ $salesReturn->salesInvoice->form->number }} + + {{ $salesReturn->customer->name }} + + {{ $item->item->name }} + {{ $item->quantity }} - {{ number_format($item->price) }} + @break + @endforeach + + {{ $salesReturnForm->notes }} + + {{ $salesReturnForm->createdBy->getFullNameAttribute() }} + + {{ date('d M Y, H:i', strtotime($salesReturnForm->created_at)) }} + + - {{ number_format($item->discount_value) }} +
+ {{ $item->item->name }} - {{ number_format($item->quantity * ($item->price - $item->discount_value)) }} + + {{ $item->quantity }}
- Sub Total - - {{ number_format($salesReturns[0]->amount - $salesReturns[0]->tax) }} -
- Taxbase - - {{ number_format($salesReturns[0]->amount - $salesReturns[0]->tax) }} -
- Tax - - {{ number_format($salesReturns[0]->tax) }} -
- Taxbase - - {{ number_format($salesReturns[0]->amount) }} -
- @if (@$url)
+ @php + unset($urlApprovalQueries['crud-type']); + $urlApprovalQueries['ids'] = implode(",", Illuminate\Support\Arr::pluck($salesReturns, 'id')); + @endphp - Check - - - Approve + Approve All - Reject + style="background-color: rgb(238, 238, 238); border: none; color: rgb(83, 83, 83); margin:8px 0; padding: 8px 16px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; "> + Reject All
- @else -

- Open your dashboard to check. -

- @endif
@stop From fce630a5f8f06e72c98c6d4fed82a6e43706c48e Mon Sep 17 00:00:00 2001 From: Gunadi Wirawan Date: Sat, 12 Nov 2022 18:37:40 +0800 Subject: [PATCH 3/3] purchase return: add tdd --- .../PurchaseReturnApprovalByEmailTest.php | 299 +++++++++ .../PurchaseReturnApprovalTest.php | 283 +++++++++ ...PurchaseReturnCancellationApprovalTest.php | 184 ++++++ .../PurchaseReturnHistoryTest.php | 167 +++++ .../PurchaseReturn/PurchaseReturnSetup.php | 431 +++++++++++++ .../PurchaseReturn/PurchaseReturnTest.php | 580 ++++++++++++++++++ 6 files changed, 1944 insertions(+) create mode 100644 tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnApprovalByEmailTest.php create mode 100644 tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnApprovalTest.php create mode 100644 tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnCancellationApprovalTest.php create mode 100644 tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnHistoryTest.php create mode 100644 tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnSetup.php create mode 100644 tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnTest.php diff --git a/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnApprovalByEmailTest.php b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnApprovalByEmailTest.php new file mode 100644 index 000000000..20942c4fc --- /dev/null +++ b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnApprovalByEmailTest.php @@ -0,0 +1,299 @@ +id)->first(); + if (!$approverToken) { + $approverToken = new Token(); + $approverToken->user_id = $tenantUser->id; + $approverToken->token = md5($tenantUser->email.''.now()); + $approverToken->save(); + } + + return $approverToken; + } + private function changeActingAs($tenantUser, $purchaseReturn) + { + $tenantUser->branches()->syncWithoutDetaching($purchaseReturn->form->branch_id); + foreach ($tenantUser->branches as $branch) { + $branch->pivot->is_default = true; + $branch->pivot->save(); + } + $tenantUser->warehouses()->syncWithoutDetaching($purchaseReturn->warehouse_id); + foreach ($tenantUser->warehouses as $warehouse) { + $warehouse->pivot->is_default = true; + $warehouse->pivot->save(); + } + $user = new User(); + $user->id = $tenantUser->id; + $user->name = $tenantUser->name; + $user->email = $tenantUser->email; + $user->save(); + $this->actingAs($user, 'api'); + } + + /** @test */ + public function success_create_purchase_return() + { + $this->setRole(); + + $data = $this->getDummyData(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(201); + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => 0, + 'done' => 0, + ], 'tenant'); + } + + /** @test */ + public function success_delete_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(200); + + $response = $this->json('DELETE', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(204); + $this->assertDatabaseHas('forms', [ + 'number' => $purchaseReturn->form->number, + 'request_cancellation_reason' => $data['reason'], + 'cancellation_status' => 0, + ], 'tenant'); + } + + /** @test */ + public function success_approve_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/approve', [], $this->headers); + $response->assertStatus(200); + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => 1 + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $response->json('data.form.number'), + 'table_id' => $response->json('data.id'), + 'table_type' => 'PurchaseReturn', + 'activity' => 'Approved' + ], 'tenant'); + } + + /** @test */ + public function success_approve_by_email_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $approver = $purchaseReturn->form->requestApprovalTo; + $approverToken = $this->findOrCreateToken($approver); + + $this->changeActingAs($approver, $purchaseReturn); + + $data = [ + 'action' => 'approve', + 'approver_id' => $purchaseReturn->form->request_approval_to, + 'token' => $approverToken->token, + 'resource-type' => 'PurchaseReturn', + 'ids' => [ + ['id' => $purchaseReturn->id] + ], + 'crud-type' => 'delete' + ]; + + $response = $this->json('POST', self::$path . '/approve', $data, $this->headers); + + $response->assertStatus(200); + $this->assertDatabaseHas('forms', [ + 'id' => $purchaseReturn->form->id, + 'number' => $purchaseReturn->form->number, + 'approval_status' => 1 + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $purchaseReturn->form->number, + 'table_id' => $purchaseReturn->id, + 'table_type' => 'PurchaseReturn', + 'activity' => 'Approved by Email' + ], 'tenant'); + $this->assertDatabaseHas('inventories', [ + 'form_id' => $purchaseReturn->form->id, + 'item_id' => $purchaseReturn->items()->first()->item_id, + 'quantity' => $purchaseReturn->items()->first()->quantity, + ], 'tenant'); + } + + /** @test */ + public function unauthorized_approve_by_email_purchase_return() + { + $this->success_create_purchase_return(); + + $this->unsetUserRole(); + + $response = $this->json('POST', self::$path . '/approve', [], $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `approve purchase return` for guard `api`." + ]); + } + + /** @test */ + public function success_approve_delete_by_email_purchase_return() + { + $this->success_delete_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $approver = $purchaseReturn->form->requestCancellationTo; + $approverToken = $this->findOrCreateToken($approver); + + $this->changeActingAs($approver, $purchaseReturn); + + $data = [ + 'action' => 'approve', + 'approver_id' => $purchaseReturn->form->request_cancellation_to, + 'token' => $approverToken->token, + 'resource-type' => 'PurchaseReturn', + 'ids' => [ + ['id' => $purchaseReturn->id] + ], + 'crud-type' => 'delete' + ]; + + $response = $this->json('POST', self::$path . '/approve', $data, $this->headers); + + $response->assertStatus(200); + $this->assertDatabaseHas('forms', [ + 'number' => $purchaseReturn->form->number, + 'cancellation_status' => 1, + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $purchaseReturn->form->number, + 'table_id' => $purchaseReturn->id, + 'table_type' => 'PurchaseReturn', + 'activity' => 'Cancellation Approved by Email' + ], 'tenant'); + } + + /** @test */ + public function unauthorized_reject_by_email_purchase_return() + { + $this->success_delete_purchase_return(); + + $this->unsetUserRole(); + + $response = $this->json('POST', self::$path . '/reject', [], $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `approve purchase return` for guard `api`." + ]); + } + + /** @test */ + public function success_reject_by_email_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $approver = $purchaseReturn->form->requestApprovalTo; + $approverToken = $this->findOrCreateToken($approver); + + $this->changeActingAs($approver, $purchaseReturn); + + $data = [ + 'action' => 'reject', + 'approver_id' => $purchaseReturn->form->request_approval_to, + 'token' => $approverToken->token, + 'resource-type' => 'PurchaseReturn', + 'ids' => [ + ['id' => $purchaseReturn->id] + ], + 'crud-type' => 'delete' + ]; + + $response = $this->json('POST', self::$path . '/reject', $data, $this->headers); + + $response->assertStatus(200); + $this->assertDatabaseHas('forms', [ + 'id' => $purchaseReturn->form->id, + 'number' => $purchaseReturn->form->number, + 'approval_status' => -1, + 'done' => 0, + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $purchaseReturn->form->number, + 'table_id' => $purchaseReturn->id, + 'table_type' => 'PurchaseReturn', + 'activity' => 'Rejected by Email' + ], 'tenant'); + } + + /** @test */ + public function success_reject_delete_by_email_purchase_return() + { + $this->success_delete_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $approver = $purchaseReturn->form->requestCancellationTo; + $approverToken = $this->findOrCreateToken($approver); + + $this->changeActingAs($approver, $purchaseReturn); + + $data = [ + 'action' => 'reject', + 'approver_id' => $purchaseReturn->form->request_cancellation_to, + 'token' => $approverToken->token, + 'resource-type' => 'PurchaseReturn', + 'ids' => [ + ['id' => $purchaseReturn->id] + ], + 'crud-type' => 'delete' + ]; + + $response = $this->json('POST', self::$path . '/reject', $data, $this->headers); + + $response->assertStatus(200); + $this->assertDatabaseHas('forms', [ + 'number' => $purchaseReturn->form->number, + 'cancellation_status' => -1, + 'done' => 0 + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $purchaseReturn->form->number, + 'table_id' => $purchaseReturn->id, + 'table_type' => 'PurchaseReturn', + 'activity' => 'Cancellation Rejected by Email' + ], 'tenant'); + } +} diff --git a/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnApprovalTest.php b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnApprovalTest.php new file mode 100644 index 000000000..2b2184062 --- /dev/null +++ b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnApprovalTest.php @@ -0,0 +1,283 @@ +getDummyData(); + + if($isFirstCreate) { + $this->setRole(); + $this->previousPurchaseReturnData = $data; + } + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(201); + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => 0, + 'done' => 0, + ], 'tenant'); + } + + /** @test */ + public function success_approve_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/approve', [], $this->headers); + $response->assertStatus(200); + $subTotal = $response->json('data.amount') - $response->json('data.tax'); + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => 1 + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $response->json('data.form.number'), + 'table_id' => $response->json('data.id'), + 'table_type' => 'PurchaseReturn', + 'activity' => 'Approved' + ], 'tenant'); + $this->assertDatabaseHas('journals', [ + 'form_id' => $response->json('data.form.id'), + 'chart_of_account_id' => $this->apCoa->id + ], 'tenant'); + $this->assertDatabaseHas('journals', [ + 'form_id' => $response->json('data.form.id'), + 'chart_of_account_id' => $this->taxCoa->id + ], 'tenant'); + } + + /** @test */ + public function error_form_already_approved_approve_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $purchaseReturn->form->approval_status = 1; + $purchaseReturn->form->save(); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/approve', [], $this->headers); + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Can't approve, form already approved!" + ]); + } + + /** @test */ + public function error_unauthorized_approve_purchase_return() + { + $this->success_create_purchase_return(); + + $this->unsetUserRole(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/approve', [], $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `approve purchase return` for guard `api`." + ]); + } + + /** @test */ + public function error_no_reason_reject_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/reject', [], $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid." + ]); + } + + /** @test */ + public function error_reason_more_than_255_character_reject_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(300); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/reject', [], $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Reason can\t more than 255 character!" + ]); + } + + /** @test */ + public function error_unauthorized_reject_purchase_return() + { + $this->success_create_purchase_return(); + + $this->unsetUserRole(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(200); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/reject', [], $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `approve purchase return` for guard `api`." + ]); + } + + /** @test */ + public function success_reject_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(200); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/reject', $data, $this->headers); + + $response->assertStatus(200); + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => -1, + 'done' => 0, + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $response->json('data.form.number'), + 'table_id' => $response->json('data.id'), + 'table_type' => 'PurchaseReturn', + 'activity' => 'Rejected' + ], 'tenant'); + } + + /** @test */ + public function read_all_purchase_return_approval() + { + + $this->success_create_purchase_return(); + $purchaseReturn = PurchaseReturn::whereHas('form', function($query){ + $query->whereApprovalStatus(0); + })->get(); + + $purchaseReturn = $purchaseReturn->sortByDesc(function($q){ + return $q->form->date; + }); + + $response = $this->json('GET', self::$path . '/approval', [ + 'limit' => '10', + 'page' => '1', + ], $this->headers); + + $data = []; + foreach ($purchaseReturn as $pReturn) { + $items = []; + foreach ($pReturn->items as $item) { + array_push($items, [ + "id" => $item->id, + "purchase_return_id" => $item->purchase_return_id, + "purchase_invoice_item_id" => $item->purchase_invoice_item_id, + "item_id" => $item->item_id, + "quantity" => $item->quantity, + "unit" => $item->unit, + "converter" => $item->converter, + ]); + } + array_push($data, [ + "id" => $pReturn->id, + "supplier_id" => $pReturn->supplier_id, + "supplier_name" => $pReturn->supplier_name, + "date" => $pReturn->form->date, + "number" => $pReturn->form->number, + "notes" => $pReturn->form->notes, + "items" => $items + ]); + }; + + $response->assertStatus(200) + ->assertJson([ + "data" => $data, + "links" => [ + "prev" => null, + "next" => null + ], + "meta" => [ + "total" => count($purchaseReturn) + ] + ]); + } + + /** @test */ + public function success_send_approval_purchase_return() + { + $this->success_create_purchase_return(); + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data = [ + "ids" => [ + "id" => $purchaseReturn->id, + ], + ]; + + $response = $this->json('POST', self::$path.'/approval/send', $data, $this->headers); + + $response->assertStatus(200) + ->assertJson([ + "input" => [ + "ids" => [ + "id" => $memoJournal->id, + ] + ] + ]); + } + + /** @test */ + public function error_default_branch_send_approval_purchase_return() + { + $this->success_create_purchase_return(); + $this->unsetBranch(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data = [ + "ids" => [ + "id" => $purchaseReturn->id, + ], + ]; + + $response = $this->json('POST', self::$path.'/approval/send', $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "please set default branch to create this form" + ]); + $this->setBranch(); + } +} \ No newline at end of file diff --git a/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnCancellationApprovalTest.php b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnCancellationApprovalTest.php new file mode 100644 index 000000000..9edde070f --- /dev/null +++ b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnCancellationApprovalTest.php @@ -0,0 +1,184 @@ +setRole(); + + $data = $this->getDummyData(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(201); + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => 0, + 'done' => 0, + ], 'tenant'); + } + + /** @test */ + public function success_delete_purchase_return() + { + $this->success_create_purchase_return(); + + $purchasesReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(200); + + $response = $this->json('DELETE', self::$path . '/' . $purchasesReturn->id, $data, $this->headers); + + $response->assertStatus(204); + $this->assertDatabaseHas('forms', [ + 'number' => $purchasesReturn->form->number, + 'request_cancellation_reason' => $data['reason'], + 'cancellation_status' => 0, + ], 'tenant'); + } + + /** @test */ + public function success_cancellation_approve_purchase_return() + { + $this->success_delete_purchase_return(); + + $purchasesReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('POST', self::$path . '/' . $purchasesReturn->id . '/cancellation-approve', [], $this->headers); + + $response->assertStatus(200); + $this->assertDatabaseHas('forms', [ + 'number' => $purchasesReturn->form->number, + 'cancellation_status' => 1, + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $response->json('data.form.number'), + 'table_id' => $response->json('data.id'), + 'table_type' => 'PurchaseReturn', + 'activity' => 'Cancel Approved' + ], 'tenant'); + } + + /** @test */ + public function error_already_approved_cancellation_approve_purchase_return() + { + $this->success_delete_purchase_return(); + + $purchasesReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $purchasesReturn->form->cancellation_status = 1; + $purchasesReturn->form->save(); + + $response = $this->json('POST', self::$path . '/' . $purchasesReturn->id . '/cancellation-approve', [], $this->headers); + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Can't approve, form already cancelled!" + ]); + } + + /** @test */ + public function success_reject_cancellation_purchase_return() + { + $this->success_delete_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(200); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/cancellation-reject', $data, $this->headers); + + $response->assertStatus(200); + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => -1, + 'done' => 0, + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $response->json('data.form.number'), + 'table_id' => $response->json('data.id'), + 'table_type' => 'PurchaseReturn', + 'activity' => 'Rejected' + ], 'tenant'); + } + + /** @test */ + public function error_no_reason_reject_purchase_return() + { + $this->success_delete_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/cancellation-reject', [], $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid." + ]); + } + + /** @test */ + public function error_reason_more_than_255_character_reject_purchase_return() + { + $this->success_delete_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(300); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/cancellation-reject', [], $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Reason can\t more than 255 character!" + ]); + } + + /** @test */ + public function error_unauthorized_approve_cancellation_purchase_return() + { + $this->success_delete_purchase_return(); + + $this->unsetUserRole(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/cancellation-approve', [], $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `approve purchase return` for guard `api`." + ]); + } + + /** @test */ + public function error_unauthorized_reject_cancellation_purchase_return() + { + $this->success_delete_purchase_return(); + + $this->unsetUserRole(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(200); + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/cancellation-reject', [], $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `approve purchase return` for guard `api`." + ]); + } +} diff --git a/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnHistoryTest.php b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnHistoryTest.php new file mode 100644 index 000000000..a2c42ae46 --- /dev/null +++ b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnHistoryTest.php @@ -0,0 +1,167 @@ +setRole(); + + $data = $this->getDummyData(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(201); + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => 0, + 'done' => 0, + ], 'tenant'); + } + + /** @test */ + public function success_update_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($purchaseReturn); + $data = data_set($data, 'id', $purchaseReturn->id, false); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(201); + $this->assertDatabaseHas('forms', [ 'edited_number' => $response->json('data.form.number') ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $response->json('data.form.number'), + 'table_id' => $response->json('data.id'), + 'table_type' => 'PurchaseReturn', + 'activity' => 'Update - 1' + ], 'tenant'); + } + + /** @test */ + public function read_purchase_return_histories() + { + $this->success_update_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $purchaseReturnUpdated = PurchaseReturn::orderBy('id', 'desc')->first(); + + $data = [ + 'sort_by' => '-user_activities.date', + 'includes' => 'user', + 'filter_like' => '{}', + 'or_filter_where_has_like[]' => '{"user":{}}', + 'limit' => 10, + 'page' => 1 + ]; + + $response = $this->json('GET', self::$path . '/' . $purchaseReturnUpdated->id . '/histories', $data, $this->headers); + + $response->assertStatus(200); + $this->assertDatabaseHas('user_activities', [ + 'number' => $purchaseReturn->form->edited_number, + 'table_id' => $purchaseReturn->id, + 'table_type' => $purchaseReturn::$morphName, + 'activity' => 'Created' + ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $purchaseReturnUpdated->form->number, + 'table_id' => $purchaseReturnUpdated->id, + 'table_type' => $purchaseReturnUpdated::$morphName, + 'activity' => 'Update - 1' + ], 'tenant'); + } + + /** @test */ + public function success_create_purchase_return_history() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data = [ + "id" => $purchaseReturn->id, + "activity" => "Printed" + ]; + + $response = $this->json('POST', self::$path . '/' . $purchaseReturn->id . '/histories', $data, $this->headers); + + $response->assertStatus(201); + $this->assertDatabaseHas('user_activities', [ + 'number' => $response->json('data.number'), + 'table_id' => $response->json('data.table_id'), + 'table_type' => $response->json('data.table_type'), + 'activity' => $response->json('data.activity') + ], 'tenant'); + } + + /** @test */ + public function unauthorized_read_purchase_return_history() + { + + $this->success_update_purchase_return(); + $this->unsetUserRole(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $purchaseReturnUpdated = PurchaseReturn::orderBy('id', 'desc')->first(); + + $data = [ + 'sort_by' => '-user_activities.date', + 'includes' => 'user', + 'filter_like' => '{}', + 'or_filter_where_has_like[]' => '{"user":{}}', + 'limit' => 10, + 'page' => 1 + ]; + + $response = $this->json('GET', self::$path . '/' . $purchaseReturnUpdated->id . '/histories', $data, $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `read purchase return` for guard `api`." + ]); + } + + /** @test */ + public function error_default_branch_read_purchase_return_history() + { + $this->success_create_purchase_return(); + $this->unsetBranch(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $purchaseReturnUpdated = PurchaseReturn::orderBy('id', 'desc')->first(); + + $data = [ + 'sort_by' => '-user_activities.date', + 'includes' => 'user', + 'filter_like' => '{}', + 'or_filter_where_has_like[]' => '{"user":{}}', + 'limit' => 10, + 'page' => 1 + ]; + + $response = $this->json('GET', self::$path . '/' . $purchaseReturnUpdated->id . '/histories', $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "please set default branch to read this form" + ]); + $this->setBranch(); + } +} \ No newline at end of file diff --git a/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnSetup.php b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnSetup.php new file mode 100644 index 000000000..16008f777 --- /dev/null +++ b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnSetup.php @@ -0,0 +1,431 @@ +signIn(); + $this->setProject(); + + $this->tenantUser = TenantUser::find($this->user->id); + $this->branchDefault = $this->tenantUser->branches() + ->where('is_default', true) + ->first(); + + $this->createSupplierUnitItem(); + $this->setUserWarehouse($this->branchDefault); + $this->setApprover(); + } + + private function setUserWarehouse($branch = null) + { + $warehouse = $this->createWarehouse($branch); + $this->tenantUser->warehouses()->syncWithoutDetaching($warehouse->id); + foreach ($this->tenantUser->warehouses as $warehouse) { + $warehouse->pivot->is_default = true; + $warehouse->pivot->save(); + + $this->warehouseSelected = $warehouse; + } + } + + protected function unsetUserRole() + { + $role = Role::createIfNotExists('super admin'); + + ModelHasRole::where('role_id', $role->id) + ->where('model_type', 'App\Model\Master\User') + ->where('model_id', $this->user->id) + ->delete(); + } + + private function unsetBranch() + { + foreach ($this->tenantUser->branches as $branch) { + $branch->pivot->is_default = false; + $branch->pivot->save(); + } + } + + private function setBranch() + { + foreach ($this->tenantUser->branches as $branch) { + $branch->pivot->is_default = true; + $branch->pivot->save(); + } + } + + private function createWarehouse($branch = null) + { + $warehouse = new Warehouse(); + $warehouse->name = 'Test warehouse'; + + if($branch) $warehouse->branch_id = $branch->id; + + $warehouse->save(); + + return $warehouse; + } + + private function createSupplierUnitItem() + { + $this->supplier = factory(Supplier::class)->create(); + $this->unit = factory(ItemUnit::class)->make(); + $this->item = factory(Item::class)->create(); + $this->item->units()->save($this->unit); + + $this->generateChartOfAccount(); + $this->item->chart_of_account_id = $this->coa->id; + $this->item->save(); + } + + private function setApprover() + { + $role = Role::createIfNotExists('super admin'); + $this->approver = factory(TenantUser::class)->create(); + $this->approver->assignRole($role); + } + + private function generateChartOfAccount() + { + $coa = ChartOfAccount::where('name', 'FINISHED GOOD INVENTORY')->first(); + if ($coa) { + $this->coa = $coa; + } else { + $type = new ChartOfAccountType; + $type->name = 'INVENTORY'; + $type->alias = 'PERSEDIAAN'; + $type->is_debit = 1; + $type->save(); + + $this->coa = new ChartOfAccount; + $this->coa->type_id = $type->id; + $this->coa->position = 'DEBIT'; + $this->coa->is_locked = 1; + $this->coa->number = 11601; + $this->coa->name = 'FINISHED GOOD INVENTORY'; + $this->coa->alias = 'PERSEDIAAN BARANG JADI '; + $this->coa->created_by = $this->user->id; + $this->coa->updated_by = $this->user->id; + $this->coa->save(); + error_log('haha'); + } + + $apCoaJournal = SettingJournal::where('feature', 'purchase')->where('name', 'account payable')->first(); + if ($apCoaJournal) { + $apCoa = ChartOfAccount::where('id', $apCoaJournal->chart_of_account_id)->first(); + $this->apCoa = $apCoa; + } else { + $type = new ChartOfAccountType; + $type->name = 'ACCOUNT PAYABLE'; + $type->alias = 'HUTANG USAHA'; + $type->is_debit = 0; + $type->save(); + + $this->apCoa = new ChartOfAccount; + $this->apCoa->type_id = $type->id; + $this->apCoa->position = 'CREDIT'; + $this->apCoa->is_locked = 1; + $this->apCoa->number = 21201; + $this->apCoa->name = 'ACCOUNT PAYABLE'; + $this->apCoa->alias = 'HUTANG DAGANG'; + $this->apCoa->created_by = $this->user->id; + $this->apCoa->updated_by = $this->user->id; + $this->apCoa->save(); + + $setting = new SettingJournal; + $setting->feature = 'purchase'; + $setting->name = 'account payable'; + $setting->chart_of_account_id = $this->apCoa->id; + $setting->save(); + } + + $taxCoaJournal = SettingJournal::where('feature', 'purchase')->where('name', 'income tax receivable')->first(); + if ($taxCoaJournal) { + $taxCoa = ChartOfAccount::where('id', $taxCoaJournal->chart_of_account_id)->first(); + $this->taxCoa = $taxCoa; + } else { + $type = new ChartOfAccountType; + $type->name = 'INCOME TAX RECEIVABLE'; + $type->alias = 'PPN MASUKAN'; + $type->is_debit = 1; + $type->save(); + + $this->taxCoa = new ChartOfAccount; + $this->taxCoa->type_id = $type->id; + $this->taxCoa->position = 'DEBIT'; + $this->taxCoa->is_locked = 1; + $this->taxCoa->number = 11707; + $this->taxCoa->name = 'INCOME TAX RECEIVABLE '; + $this->taxCoa->alias = 'PPN MASUKAN'; + $this->taxCoa->created_by = $this->user->id; + $this->taxCoa->updated_by = $this->user->id; + $this->taxCoa->save(); + + $setting = new SettingJournal; + $setting->feature = 'purchase'; + $setting->name = 'income tax receivable'; + $setting->chart_of_account_id = $this->taxCoa->id; + $setting->save(); + } + } + + private function getDummyData($purchaseReturn = null) + { + $inv = $purchaseReturn ?? $this->createPurchaseInvoice(); + + $invoice = $purchaseReturn ? $inv->purchaseInvoice : $inv; + $invoiceItem = $invoice->items()->first(); + + $quantityInvoice = $invoiceItem->quantity; + $quantityReturned = 0; + foreach ($invoiceItem->returnItem as $returnItem) { + $quantityReturned += $returnItem->quantity; + } + + $supplier = $invoice->supplier; + $approver = $invoice->form->requestApprovalTo; + + return [ + 'increment_group' => date('Ym'), + 'date' => date('Y-m-d H:i:s'), + 'purchase_invoice_id' => $invoice->id, + "warehouse_id" => $invoiceItem->purchaseReceive->warehouse_id, + 'supplier_id' => $supplier->id, + 'supplier_name' => $supplier->name, + 'supplier_address' => null, + 'supplier_phone' => null, + 'tax' => 1500, + 'amount' => 15000, + 'notes' => null, + 'items' => [ + [ + 'purchase_invoice_item_id' => $invoiceItem->id, + 'item_id' => $this->item->id, + 'item_name' => $this->item->name, + 'item_label' => "[{$this->item->code}] - {$this->item->name}", + 'unit' => $this->unit->label, + 'converter' => $invoiceItem->converter, + 'quantity' => 3, + 'price' => $invoiceItem->price, + 'discount_percent' => $invoiceItem->discount_percent, + 'discount_value' => $invoiceItem->discount_value, + 'notes' => null, + ], + ], + 'request_approval_to' => $approver->id, + 'approver_name' => $approver->name, + 'approver_email' => $approver->email, + ]; + } + + private function createPurchaseOrder() + { + $params = [ + 'increment_group' => date('Ym'), + 'date' => date('Y-m-d H:i:s'), + 'supplier_id' => $this->supplier->id, + 'supplier_name' => $this->supplier->name, + 'supplier_label' => $this->supplier->code, + 'supplier_address' => $this->supplier->address, + 'supplier_phone' => $this->supplier->phone, + 'supplier_email' => $this->supplier->phone, + 'need_down_payment' => 0, + 'cash_only' => false, + 'notes' => null, + 'discount_percent' => 0, + 'discount_value' => 0, + 'tax_base' => 1100000, + 'tax' => 110000, + 'type_of_tax' => 'exclude', + 'items' => [ + [ + 'purchase_request_item_id' => null, + 'item_id' => $this->item->id, + 'item_name' => $this->item->name, + 'more' => false, + 'unit' => $this->unit->label, + 'converter' => 1, + 'quantity' => '220', + 'price' => 5000, + 'discount_percent' => 0, + 'discount_value' => 0, + 'allocation_id' => null, + 'allocation_name' => '', + 'notes' => null, + 'item_label' => "[{$this->item->code}] - {$this->item->name}", + 'units' => [ + [ + 'id' => $this->unit->id, + 'label' => $this->unit->label, + 'name' => $this->unit->name, + 'converter' => 1, + 'disabled' => 0, + 'item_id' => $this->item->id, + 'created_by' => 1, + 'updated_by' => 1, + 'created_at' => '2022-05-13 10:38:42', + 'updated_at' => '2022-05-13 10:38:42', + 'prices' => [], + ], + ], + ], + ], + 'request_approval_to' => $this->approver->id, + 'approver_name' => $this->approver->getFullNameAttribute(), + 'approver_email' => $this->approver->email, + 'purchase_request_id' => null, + ]; + + $purchaseOrder = PurchaseOrder::create($params); + $purchaseOrder->form->approval_by = $this->approver->id; + $purchaseOrder->form->approval_at = now(); + $purchaseOrder->form->approval_status = 1; + $purchaseOrder->form->save(); + + return $purchaseOrder; + } + + private function createPurchaseReceive() + { + $order = $this->createPurchaseOrder(); + $orderItem = $order->items()->first(); + + $params = [ + 'increment_group' => date('Ym'), + 'purchase_order_id' => $order->id, + 'date' => date('Y-m-d H:i:s'), + 'warehouse_id' => $this->warehouseSelected->id, + 'warehouse_name' => $this->warehouseSelected->name, + 'supplier_id' => $this->supplier->id, + 'supplier_name' => $this->supplier->name, + 'supplier_label' => $this->supplier->code, + 'supplier_address' => $this->supplier->address, + 'supplier_phone' => $this->supplier->phone, + 'driver' => '-', + 'license_plate' => '-', + 'items' => [ + [ + 'id' => $orderItem->id, + 'purchase_order_id' => $order->id, + 'purchase_request_item_id' => null, + 'item_id' => $this->item->id, + 'item_name' => $this->item->name, + 'unit' => $this->unit->label, + 'converter' => 1, + 'quantity' => '220', + 'price' => 5000, + 'discount_percent' => 0, + 'discount_value' => 0, + 'allocation_id' => null, + 'notes' => null, + 'purchase_order_item_id' => $orderItem->id, + 'item_label' => "[{$this->item->code}] - {$this->item->name}", + 'quantity_pending' => '220', + 'warehouse_id' => $this->warehouseSelected->id, + 'warehouse_name' => $this->warehouseSelected->name, + ], + ], + 'request_approval_to' => $this->approver->id, + 'approver_name' => $this->approver->getFullNameAttribute(), + 'approver_email' => $this->approver->email, + 'purchase_request_id' => null, + ]; + + $purchaseReceive = PurchaseReceive::create($params); + $purchaseReceive->form->approval_by = $this->approver->id; + $purchaseReceive->form->approval_at = now(); + $purchaseReceive->form->approval_status = 1; + $purchaseReceive->form->save(); + + return $purchaseReceive; + } + + private function createPurchaseInvoice() + { + $receive = $this->createPurchaseReceive(); + $receiveItem = $receive->items()->first(); + + $params = [ + 'increment_group' => date('Ym'), + 'date' => date('Y-m-d H:i:s'), + 'due_date' => date('Y-m-d H:i:s'), + 'supplier_id' => $this->supplier->id, + 'supplier_name' => $this->supplier->name, + 'supplier_label' => $this->supplier->code, + 'supplier_address' => $this->supplier->address, + 'supplier_phone' => $this->supplier->phone, + 'supplier_email' => $this->supplier->phone, + 'need_down_payment' => 0, + 'cash_only' => false, + 'notes' => null, + 'discount_percent' => 0, + 'discount_value' => 0, + 'tax_base' => 1100000, + 'tax' => 110000, + 'type_of_tax' => 'exclude', + 'items' => [ + [ + 'purchase_receive_id' => $receive->id, + 'purchase_receive_item_id' => $receiveItem->id, + 'item_id' => $this->item->id, + 'item_name' => $this->item->name, + 'more' => false, + 'unit' => $this->unit->label, + 'converter' => 1, + 'quantity' => '220', + 'price' => 5000, + 'discount_percent' => 0, + 'discount_value' => 0, + 'allocation_id' => null, + 'total' => 1100000, + 'notes' => null, + 'item_label' => "[{$this->item->code}] - {$this->item->name}", + ], + ], + 'request_approval_to' => $this->approver->id, + 'approver_name' => $this->approver->getFullNameAttribute(), + 'approver_email' => $this->approver->email, + 'purchase_request_id' => null, + ]; + + $purchaseInvoice = PurchaseInvoice::create($params); + $purchaseInvoice->form->approval_by = $this->approver->id; + $purchaseInvoice->form->approval_at = now(); + $purchaseInvoice->form->approval_status = 1; + $purchaseInvoice->form->save(); + + return $purchaseInvoice; + } +} \ No newline at end of file diff --git a/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnTest.php b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnTest.php new file mode 100644 index 000000000..ca28ac9ae --- /dev/null +++ b/tests/Feature/Http/Purchase/PurchaseReturn/PurchaseReturnTest.php @@ -0,0 +1,580 @@ +setRole(); + + $data = $this->getDummyData(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(201); + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => 0, + 'done' => 0, + ], 'tenant'); + + $this->assertDatabaseHas('purchase_returns', [ + 'id' => $response->json('data.id'), + 'supplier_name' => $response->json('data.supplier_name'), + 'purchase_invoice_id' => $data->purchase_invoice_id, + ], 'tenant'); + + $this->assertDatabaseHas('purchase_return_items', [ + 'purchase_return_id' => $response->json('data.id'), + 'item_id' => $data->items[0]->item_id, + ], 'tenant'); + } + + /** @test */ + public function unauthorized_create_purchase_return() + { + $this->unsetUserRole(); + $data = $this->getDummyData(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `create purchase return` for guard `api`." + ]); + } + + /** @test */ + public function error_default_branch_create_purchase_return() + { + $this->setRole(); + + $data = $this->getDummyData(); + + $this->unsetBranch(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "please set default branch to create this form" + ]); + $this->setBranch(); + } + + /** @test */ + public function error_invalid_data_create_purchase_return() + { + $this->setRole(); + + $data = $this->getDummyData(); + $data = data_set($data, 'purchase_invoice_id', null); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid." + ]); + } + + /** @test */ + public function error_purchase_invoice_done_create_purchase_return() + { + $this->setRole(); + + $data = $this->getDummyData(); + $purchaseInvoice = PurchaseReturn::findOrFail($data->purchase_invoice_id); + $purchaseInvoice->form->done = 1; + $purchaseInvoice->form->save(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Invoice already done!" + ]); + } + + /** @test */ + public function error_note_more_than_255_character_create_purchase_return() + { + $this->setRole(); + + $data = $this->getDummyData(); + $data = data_set($data, 'notes', $this->faker->text(300)); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Notes can\t more than 255 character!" + ]); + } + + /** @test */ + public function error_note_contain_space_on_first_or_last_character_create_purchase_return() + { + $this->setRole(); + + $data = $this->getDummyData(); + $data = data_set($data, 'notes', ' notes '); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Notes can\t contain space on first or last character!" + ]); + } + + /** @test */ + public function error_overquantity_create_purchase_return() + { + $this->setRole(); + + $data = $this->getDummyData(); + $data = data_set($data, 'items.0.quantity', 300); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Purchase return item qty can't exceed purchase invoice qty" + ]); + } + + /** @test */ + public function error_invalid_total_create_purchase_return() + { + $this->setRole(); + + $data = $this->getDummyData(); + $data = data_set($data, 'amount', 180000); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Amount was invalid." + ]); + } + + /** @test */ + public function error_journal_not_set_create_purchase_return() + { + $this->setRole(); + + $data = $this->getDummyData(); + SettingJournal::where('feature', 'purchase')->where('name', 'account payable')->delete(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Journal purchase account - account payable not found" + ]); + + $this->generateChartOfAccount(); + } + + /** @test */ + public function success_read_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('GET', self::$path.'/'.$purchaseReturn->id, [ + 'includes' => 'items.item;items.allocation;;form.createdBy;form.requestApprovalTo;form.branch' + ], $this->headers); + + $response->assertStatus(200) + ->assertJson([ + "data" => [ + "id" => $purchaseReturn->id, + "form" => [ + "id" => $purchaseReturn->form->id, + "date" => $purchaseReturn->form->date, + "number" => $purchaseReturn->form->number, + "notes" => $purchaseReturn->form->notes, + ] + ] + ]); + } + + /** @test */ + public function unauthorized_read_purchase_return() + { + $this->success_create_purchase_return(); + $this->unsetUserRole(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('GET', self::$path.'/'.$purchaseReturn->id, [ + 'includes' => 'items.item;items.allocation;;form.createdBy;form.requestApprovalTo;form.branch' + ], $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `read purchase return` for guard `api`." + ]); + } + + /** @test */ + public function error_default_branch_read_purchase_return() + { + $this->success_create_purchase_return(); + $this->unsetBranch(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $response = $this->json('GET', self::$path.'/'.$purchaseReturn->id, [ + 'includes' => 'items.item;items.allocation;;form.createdBy;form.requestApprovalTo;form.branch' + ], $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "please set default branch to read this form" + ]); + $this->setBranch(); + } + + /** @test */ + public function success_update_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($purchaseReturn); + $data = data_set($data, 'items.0.quantity', 10); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(201); + $this->assertDatabaseHas('forms', [ 'edited_number' => $response->json('data.form.number') ], 'tenant'); + $this->assertDatabaseHas('user_activities', [ + 'number' => $response->json('data.form.number'), + 'table_id' => $response->json('data.id'), + 'table_type' => 'PurchaseReturn', + 'activity' => 'Update - 1' + ], 'tenant'); + + $this->assertDatabaseHas('forms', [ + 'id' => $response->json('data.form.id'), + 'number' => $response->json('data.form.number'), + 'approval_status' => 0, + 'done' => 0, + ], 'tenant'); + + $this->assertDatabaseHas('purchase_returns', [ + 'id' => $response->json('data.id'), + 'supplier_name' => $response->json('data.supplier_name'), + 'purchase_invoice_id' => $data->purchase_invoice_id, + ], 'tenant'); + + $this->assertDatabaseHas('purchase_return_items', [ + 'purchase_return_id' => $response->json('data.id'), + 'item_id' => $data->items[0]->item_id, + ], 'tenant'); + } + + /** @test */ + public function error_invalid_data_update_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData(); + $data = data_set($data, 'purchase_invoice_id', null); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid." + ]); + } + + /** @test */ + public function error_form_already_done_update_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $purchaseReturn->form->done = 1; + $purchaseReturn->form->save(); + + $data = $this->getDummyData(); + $data = data_set($data, 'purchase_invoice_id', null); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Can't update, form already done!" + ]); + } + + /** @test */ + public function error_note_more_than_255_character_update_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData(); + $data = data_set($data, 'notes', $this->faker->text(300)); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Notes can\t more than 255 character!" + ]); + } + + /** @test */ + public function error_note_contain_space_on_first_or_last_character_update_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData(); + $data = data_set($data, 'notes', ' notes '); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Notes can\t contain space on first or last character!" + ]); + } + + /** @test */ + public function error_overquantity_update_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData(); + $data = data_set($data, 'items.0.quantity', 300); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Purchase return item qty can't exceed purchase invoice qty" + ]); + } + + /** @test */ + public function error_invalid_total_amount_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData(); + $data = data_set($data, 'amount', 18000); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Amount was invalid." + ]); + } + + /** @test */ + public function error_journal_not_set_update_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData(); + SettingJournal::where('feature', 'purchase')->where('name', 'account payable')->delete(); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Journal purchase account - account payable not found" + ]); + + $this->generateChartOfAccount(); + } + + /** @test */ + public function unauthorized_edit_purchase_return() + { + $this->success_create_purchase_return(); + $this->unsetUserRole(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($purchaseReturn); + $data = data_set($data, 'items.0.quantity', 10); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `update purchase return` for guard `api`." + ]); + } + + /** @test */ + public function error_default_branch_update_purchase_return() + { + $this->success_create_purchase_return(); + $this->unsetBranch(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($purchaseReturn); + $data = data_set($data, 'items.0.quantity', 10); + + $response = $this->json('PATCH', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "please set default branch to update this form" + ]); + $this->setBranch(); + } + + /** @test */ + public function success_delete_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(200); + + $response = $this->json('DELETE', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(204); + $this->assertDatabaseHas('forms', [ + 'number' => $purchaseReturn->form->number, + 'request_cancellation_reason' => $data['reason'], + 'cancellation_status' => 0, + ], 'tenant'); + } + + /** @test */ + public function error_form_already_done_delete_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $purchaseReturn->form->done = 1; + $purchaseReturn->form->save(); + + $data['reason'] = $this->faker->text(200); + + $response = $this->json('DELETE', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Can't delete, form already done!" + ]); + } + + /** @test */ + public function error_no_reason_delete_purchase_return() + { + $this->success_create_purchase_return(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $purchaseReturn->form->done = 1; + $purchaseReturn->form->save(); + + $data['reason'] = null; + + $response = $this->json('DELETE', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid." + ]); + } + + /** @test */ + public function unauthorized_delete_purchase_return() + { + $this->success_create_purchase_return(); + $this->unsetUserRole(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(200); + + $response = $this->json('DELETE', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `delete purchase return` for guard `api`." + ]); + } + + /** @test */ + public function error_default_branch_delete_purchase_return() + { + $this->success_create_purchase_return(); + $this->unsetBranch(); + + $purchaseReturn = PurchaseReturn::orderBy('id', 'asc')->first(); + $data['reason'] = $this->faker->text(200); + + $response = $this->json('DELETE', self::$path . '/' . $purchaseReturn->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "please set default branch to delete this form" + ]); + $this->setBranch(); + } + +} \ No newline at end of file