From f4fb421da3d8c03c76d2779a2a1a7f27606eb68b Mon Sep 17 00:00:00 2001 From: addincendekia Date: Wed, 2 Nov 2022 01:59:05 +0700 Subject: [PATCH 01/16] inventory usage - export feature --- .../Inventory/InventoryUsageExport.php | 177 ++++++++++++++++++ .../InventoryUsageController.php | 38 ++++ routes/api/inventory.php | 1 + 3 files changed, 216 insertions(+) create mode 100755 app/Exports/Inventory/InventoryUsageExport.php diff --git a/app/Exports/Inventory/InventoryUsageExport.php b/app/Exports/Inventory/InventoryUsageExport.php new file mode 100755 index 000000000..23d8bee6f --- /dev/null +++ b/app/Exports/Inventory/InventoryUsageExport.php @@ -0,0 +1,177 @@ +tenantName = $tenantName; + $this->filters = $filters; + } + + /** + * @return \Illuminate\Database\Eloquent\Builder + */ + public function query() + { + $inventoryUsages = InventoryUsage::from(InventoryUsage::getTableName().' as '.InventoryUsage::$alias) + ->eloquentFilter($this->filters); + + $inventoryUsages = InventoryUsage::joins($inventoryUsages, $this->filters->get('join')); + + return $inventoryUsages; + } + + public function columnFormats(): array + { + return [ + 'I' => NumberFormat::FORMAT_NUMBER, + ]; + } + + /** + * @return array + */ + public function headings(): array + { + $dateExport = Carbon::now()->timezone(config()->get('project.timezone')); + $periodExport = $this->_getPeriodExport(); + + return [ + ['Date Export', ': ' . $dateExport->format('d M Y H:i')], + ['Period Export', ': ' . $periodExport], + [$this->tenantName], + ['Inventory Usage'], + [ + 'Date Form', + 'Form Number', + 'Warehouse', + 'Employee', + 'Account', + 'Item', + 'Production Number', + 'Expiry Date', + 'Quantity Usage', + 'Notes', + 'Allocation', + 'Notes', + 'Created By', + 'Approved By', + 'Approval Status', + 'Form Status', + 'Created At', + 'Updated At', + 'Deleted At' + ] + ]; + } + + /** + * @param mixed $row + * @return array + */ + public function map($row): array + { + $form = Form::where('formable_id', $row->inventory_usage_id) + ->with(['createdBy', 'approvalBy']) + ->where('formable_type', InventoryUsage::$morphName) + ->first(); + + $usageItem = InventoryUsageItem::where('id', $row->id) + ->with(['item', 'account', 'allocation']) + ->first(); + + return [ + date('d F Y', strtotime($form->date)), + $form->number, + $row->warehouse->name, + $row->employee->name, + $usageItem->account->name, + $usageItem->item->name, + $row->production_number, + $row->expiry_date, + round($row->quantity, 2) . ' ' . $row->unit, + $row->notes, + $usageItem->allocation->name, + $form->notes, + $form->createdBy->getFullNameAttribute(), + optional($form->approvalBy)->getFullNameAttribute(), + $form->approval_status, + $form->done, + date('d F Y', strtotime($form->created_at)), + date('d F Y', strtotime($form->updated_at)), + date('d F Y', strtotime($form->updated_at)), + ]; + } + + public function registerEvents(): array + { + return [ + AfterSheet::class => function(AfterSheet $event) { + $event->sheet->getDelegate()->getStyle('F6:F100') + ->getAlignment() + ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT); + $event->sheet->getColumnDimension('B') + ->setAutoSize(false) + ->setWidth(18); + $tenanNameColl = 'A3:M3'; // All headers + $event->sheet->mergeCells($tenanNameColl); + $event->sheet->getDelegate()->getStyle($tenanNameColl)->getFont()->setBold(true); + $event->sheet->getDelegate()->getStyle($tenanNameColl) + ->getAlignment() + ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); + $titleColl = 'A4:M4'; // All headers + $event->sheet->mergeCells($titleColl); + $event->sheet->getDelegate()->getStyle($titleColl)->getFont()->setBold(true); + $event->sheet->getDelegate()->getStyle($titleColl) + ->getAlignment() + ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); + }, + + ]; + } + + private function _getPeriodExport() + { + $dateMin = $this->filters->filter_date_min; + $dateMin = !is_null($dateMin) && !is_array($dateMin) + ? json_decode($dateMin, true) + : []; + + $dateMax = $this->filters->filter_date_max; + $dateMax = !is_null($dateMax) && !is_array($dateMax) + ? json_decode($dateMax, true) + : []; + + $periodExport = ''; + if (isset($dateMin['form.date'])) { + $periodExport .= Carbon::createFromFormat('Y-m-d H:i:s', $dateMin['form.date'])->format('d M Y'); + } + if (isset($dateMax['form.date'])) { + if($periodExport !== '') $periodExport .= ' - '; + $periodExport .= Carbon::createFromFormat('Y-m-d H:i:s', $dateMax['form.date'])->format('d M Y'); + } + + return $periodExport; + } +} diff --git a/app/Http/Controllers/Api/Inventory/InventoryUsage/InventoryUsageController.php b/app/Http/Controllers/Api/Inventory/InventoryUsage/InventoryUsageController.php index 6d2881c51..433fcc9a2 100644 --- a/app/Http/Controllers/Api/Inventory/InventoryUsage/InventoryUsageController.php +++ b/app/Http/Controllers/Api/Inventory/InventoryUsage/InventoryUsageController.php @@ -2,14 +2,20 @@ namespace App\Http\Controllers\Api\Inventory\InventoryUsage; +use App\Exports\Inventory\InventoryUsageExport; use App\Http\Controllers\Controller; use App\Http\Requests\Inventory\Usage\StoreRequest; use App\Http\Requests\Inventory\Usage\UpdateRequest; use App\Http\Resources\ApiCollection; use App\Http\Resources\ApiResource; +use App\Model\CloudStorage; use App\Model\Inventory\InventoryUsage\InventoryUsage; +use App\Model\Project\Project; +use Carbon\Carbon; use Illuminate\Http\Request; +use Illuminate\Support\Str; use Illuminate\Support\Facades\DB; +use Maatwebsite\Excel\Facades\Excel; class InventoryUsageController extends Controller { @@ -126,4 +132,36 @@ public function destroy(Request $request, $id) return response()->json([], 204); } + + public function export(Request $request) + { + try { + $tenant = strtolower($request->header('Tenant')); + $key = Str::random(16); + $fileName = strtoupper($tenant).' - Inventory Usage'; + $fileExt = 'xlsx'; + $path = 'tmp/'.$tenant.'/'.$key.'.'.$fileExt; + + Excel::store(new InventoryUsageExport($tenant, $request), $path, env('STORAGE_DISK')); + + $cloudStorage = new CloudStorage(); + $cloudStorage->file_name = $fileName; + $cloudStorage->file_ext = $fileExt; + $cloudStorage->feature = 'Inventory Usage Export'; + $cloudStorage->key = $key; + $cloudStorage->path = $path; + $cloudStorage->disk = env('STORAGE_DISK'); + $cloudStorage->project_id = Project::where('code', strtolower($tenant))->first()->id; + $cloudStorage->owner_id = auth()->user()->id; + $cloudStorage->expired_at = Carbon::now()->addDay(1); + $cloudStorage->download_url = env('API_URL').'/download?key='.$key; + $cloudStorage->save(); + + return response()->json([ + 'data' => [ 'url' => $cloudStorage->download_url ], + ], 200); + } catch (\Throwable $th) { + return response_error($th); + } + } } diff --git a/routes/api/inventory.php b/routes/api/inventory.php index 43fb283d7..1b07ee219 100644 --- a/routes/api/inventory.php +++ b/routes/api/inventory.php @@ -23,6 +23,7 @@ Route::get('usages/{id}/histories', 'InventoryUsageHistoryController@index'); + Route::get('usages/export', 'InventoryUsageController@export'); Route::apiResource('usages', 'InventoryUsageController'); }); }); From 74e3e5df12cbac72fc7b4e3e03a6b712ba89e0ff Mon Sep 17 00:00:00 2001 From: addincendekia Date: Wed, 2 Nov 2022 10:09:15 +0700 Subject: [PATCH 02/16] fix([inventory-usage] send receipt): change from object to replyTo --- app/Mail/CustomEmail.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/Mail/CustomEmail.php b/app/Mail/CustomEmail.php index 70ec19e64..4f7b59533 100644 --- a/app/Mail/CustomEmail.php +++ b/app/Mail/CustomEmail.php @@ -38,7 +38,7 @@ public function build() $user = $this->user; $request = $this->request; - $this->from($user->email, $user->getFullNameAttribute()); + $this->replyTo($user->email, $user->getFullNameAttribute()); $this->to($request->to); if (optional($request)->cc) { @@ -47,9 +47,6 @@ public function build() if (optional($request)->bcc) { $this->bcc($request->bcc); } - if (optional($request)->reply_to) { - $this->replyTo($request->reply_to, $request->reply_to_name); - } $this->subject($request->subject); $this->view('emails.custom-email', ['body' => $request->body]); From 14f8e335e10a019d877eaa9ea3a5f77dbf5cfe50 Mon Sep 17 00:00:00 2001 From: addincendekia Date: Wed, 9 Nov 2022 09:58:50 +0700 Subject: [PATCH 03/16] fix([inventory-usage] edit): bug backdate on edit form --- app/Http/Requests/Inventory/Usage/UpdateRequest.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/Http/Requests/Inventory/Usage/UpdateRequest.php b/app/Http/Requests/Inventory/Usage/UpdateRequest.php index 87d19049e..9fbd2b22a 100644 --- a/app/Http/Requests/Inventory/Usage/UpdateRequest.php +++ b/app/Http/Requests/Inventory/Usage/UpdateRequest.php @@ -3,6 +3,7 @@ namespace App\Http\Requests\Inventory\Usage; use App\Http\Requests\ValidationRule; +use App\Model\Inventory\InventoryUsage\InventoryUsage; use Illuminate\Foundation\Http\FormRequest; class UpdateRequest extends FormRequest @@ -24,7 +25,12 @@ public function authorize() */ public function rules() { - return [ + $inventoryUsage = InventoryUsage::find($this->id); + + $rulesForm = ValidationRule::form(); + $rulesForm['date'] = 'required|date|after_or_equal:'.$inventoryUsage->form->date; + + $rulesUpdate = [ 'warehouse_id' => 'required', 'request_approval_to' => 'required', @@ -34,5 +40,7 @@ public function rules() 'items.*.converter' => ValidationRule::converter(), 'items.*.chart_of_account_id' => 'required', ]; + + return array_merge($rulesForm, $rulesUpdate); } } From acb56c2922db551ebfda728335d78c7b62e6df29 Mon Sep 17 00:00:00 2001 From: addincw Date: Wed, 16 Nov 2022 20:34:56 +0700 Subject: [PATCH 04/16] inventory-usage: wip unit test feature update --- .../InventoryUsage/InventoryUsageSetup.php | 46 +++++++++++++------ .../InventoryUsage/InventoryUsageTest.php | 28 +++++------ 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php index a216db53b..ebce23994 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php @@ -137,27 +137,43 @@ private function changeActingAs($tenantUser, $inventoryUsage) $this->actingAs($user, 'api'); } - private function getDummyData($itemUnit = 'pcs') + private function getDummyData($inventoryUsage = null, $itemUnit = 'pcs') { $warehouse = $this->warehouseSelected; - - $allocation = factory(Allocation::class)->create(); - $employee = factory(Employee::class)->create(); - - $chartOfAccount = ChartOfAccount::whereHas('type', function ($query) { - return $query->whereIn('alias', ['BEBAN OPERASIONAL', 'BEBAN NON OPERASIONAL']); - })->first(); - $unit = new ItemUnit([ 'label' => $itemUnit, 'name' => $itemUnit, 'converter' => 1, ]); - $item = $this->createItemWithStocks($unit); + $quantity = 5; + + if ($inventoryUsage) { + $inventoryUsageItem = $inventoryUsage->items()->first(); + + $employee = $inventoryUsage->employee; + + $allocation = $inventoryUsageItem->allocation; + $chartOfAccount = $inventoryUsageItem->account; + $item = $inventoryUsageItem->item; + $unit = $inventoryUsageItem->item->unit; + $quantity = $inventoryUsageItem->quantity; + + $approver = $inventoryUsage->form->requestApprovalTo; + } else { + $allocation = factory(Allocation::class)->create(); + $employee = factory(Employee::class)->create(); + + $chartOfAccount = ChartOfAccount::whereHas('type', function ($query) { + return $query->whereIn('alias', ['BEBAN OPERASIONAL', 'BEBAN NON OPERASIONAL']); + })->first(); + + $item = $this->createItemWithStocks($unit); + + $role = Role::createIfNotExists('super admin'); + $approver = factory(TenantUser::class)->create(); + $approver->assignRole($role); + } - $role = Role::createIfNotExists('super admin'); - $approver = factory(TenantUser::class)->create(); - $approver->assignRole($role); return [ "increment_group" => date("Ym"), @@ -181,7 +197,7 @@ private function getDummyData($itemUnit = 'pcs') "require_production_number" => 0, "unit" => $unit->name, "converter" => $unit->converter, - "quantity" => 5, + "quantity" => $quantity, "allocation_id" => $allocation->id, "allocation_name" => $allocation->name, "notes" => null, @@ -190,4 +206,4 @@ private function getDummyData($itemUnit = 'pcs') ] ]; } -} \ No newline at end of file +} diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index 670ff38d8..1338503dc 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -61,7 +61,7 @@ public function invalid_unit_create_inventory_usage() { $this->setRole(); - $data = $this->getDummyData($itemUnit = 'box'); + $data = $this->getDummyData(null, $itemUnit = 'box'); $response = $this->json('POST', self::$path, $data, $this->headers); $response->assertStatus(422) @@ -148,23 +148,23 @@ public function read_inventory_usage() $response->assertStatus(200); } /** @test */ - // public function unauthorized_update_inventory_usage() - // { - // $this->success_create_inventory_usage(); + public function unauthorized_update_inventory_usage() + { + $this->success_create_inventory_usage(); - // $this->unsetUserRole(); + $this->unsetUserRole(); - // $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); - // $data = $this->getDummyData($inventoryUsage); + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + $data = $this->getDummyData($inventoryUsage); - // $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); - // $response->assertStatus(500) - // ->assertJson([ - // "code" => 0, - // "message" => "There is no permission named `update inventory usage` for guard `api`." - // ]); - // } + $response->assertStatus(500) + ->assertJson([ + "code" => 0, + "message" => "There is no permission named `update inventory usage` for guard `api`." + ]); + } /** @test */ // public function overquantity_update_inventory_usage() // { From bf2f69fc1acf7c9c4cdf804e62b5ae07d519fd70 Mon Sep 17 00:00:00 2001 From: addincw Date: Tue, 22 Nov 2022 11:42:00 +0700 Subject: [PATCH 05/16] [inventory-usage]: wip test feature update --- .../InventoryUsage/InventoryUsageSetup.php | 6 +- .../InventoryUsage/InventoryUsageTest.php | 72 ++++++++++--------- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php index ebce23994..9a5d67e55 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php @@ -155,7 +155,11 @@ private function getDummyData($inventoryUsage = null, $itemUnit = 'pcs') $allocation = $inventoryUsageItem->allocation; $chartOfAccount = $inventoryUsageItem->account; $item = $inventoryUsageItem->item; - $unit = $inventoryUsageItem->item->unit; + + if ($itemUnit !== 'pcs') { + $unit = ItemUnit::where('label', $inventoryUsageItem->unit)->first(); + } + $quantity = $inventoryUsageItem->quantity; $approver = $inventoryUsage->form->requestApprovalTo; diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index 1338503dc..ee9902b91 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -166,53 +166,55 @@ public function unauthorized_update_inventory_usage() ]); } /** @test */ - // public function overquantity_update_inventory_usage() - // { - // $this->success_create_inventory_usage(); + public function overquantity_update_inventory_usage() + { + $this->success_create_inventory_usage(); - // $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); - // $data = $this->getDummyData($inventoryUsage); - // $data = data_set($data, 'id', $inventoryUsage->id, false); - // $data = data_set($data, 'items.0.quantity', 2000); + $data = $this->getDummyData($inventoryUsage); + $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = data_set($data, 'items.0.quantity', 2000); - // $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); - // $response->assertStatus(422) - // ->assertJson([ - // "code" => 422, - // "message" => "Stock {$data['items'][0]['item_name']} not enough" - // ]); - // } + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Stock {$data['items'][0]['item_name']} not enough" + ]); + } /** @test */ - // public function invalid_update_inventory_usage() - // { - // $this->success_create_inventory_usage(); + public function invalid_update_inventory_usage() + { + $this->success_create_inventory_usage(); - // $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); - // $data = $this->getDummyData($inventoryUsage); - // $data = data_set($data, 'id', $inventoryUsage->id, false); - // $data = data_set($data, 'request_approval_to', null); + $data = $this->getDummyData($inventoryUsage); + $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = data_set($data, 'request_approval_to', null); - // $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); - // $response->assertStatus(422); - // } + $response->assertStatus(422); + } /** @test */ - // public function invalid_unit_update_inventory_usage() - // { - // $this->setRole(); + public function invalid_unit_update_inventory_usage() + { + $this->success_create_inventory_usage(); - // $data = $this->getDummyData($itemUnit = 'box'); + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($inventoryUsage, $itemUnit = 'box'); - // $response = $this->json('POST', self::$path, $data, $this->headers); - // $response->assertStatus(422) - // ->assertJson([ - // "code" => 422, - // "message" => "there are some item not in 'pcs' unit" - // ]); - // } + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "there are some item not in 'pcs' unit" + ]); + } /** @test */ // public function success_update_inventory_usage() // { From 3f1a32a357d7ca7d14fee923f1d8846330638dc2 Mon Sep 17 00:00:00 2001 From: addincw Date: Wed, 23 Nov 2022 10:18:30 +0700 Subject: [PATCH 06/16] inventory-usage: completing unit test feature update --- .../Inventory/Usage/UpdateRequest.php | 2 +- .../InventoryUsage/InventoryUsageSetup.php | 2 +- .../InventoryUsage/InventoryUsageTest.php | 39 ++++++++++--------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/app/Http/Requests/Inventory/Usage/UpdateRequest.php b/app/Http/Requests/Inventory/Usage/UpdateRequest.php index 9fbd2b22a..068444cea 100644 --- a/app/Http/Requests/Inventory/Usage/UpdateRequest.php +++ b/app/Http/Requests/Inventory/Usage/UpdateRequest.php @@ -28,7 +28,7 @@ public function rules() $inventoryUsage = InventoryUsage::find($this->id); $rulesForm = ValidationRule::form(); - $rulesForm['date'] = 'required|date|after_or_equal:'.$inventoryUsage->form->date; + $rulesForm['date'] = 'required|date|after_or_equal:'.optional($inventoryUsage->form)->date; $rulesUpdate = [ 'warehouse_id' => 'required', diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php index 9a5d67e55..a979a7417 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php @@ -156,7 +156,7 @@ private function getDummyData($inventoryUsage = null, $itemUnit = 'pcs') $chartOfAccount = $inventoryUsageItem->account; $item = $inventoryUsageItem->item; - if ($itemUnit !== 'pcs') { + if ($itemUnit === 'pcs') { $unit = ItemUnit::where('label', $inventoryUsageItem->unit)->first(); } diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index ee9902b91..5f24f6cc5 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -205,8 +205,9 @@ public function invalid_unit_update_inventory_usage() $this->success_create_inventory_usage(); $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); - + $data = $this->getDummyData($inventoryUsage, $itemUnit = 'box'); + $data = data_set($data, 'id', $inventoryUsage->id, false); $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); $response->assertStatus(422) @@ -216,26 +217,26 @@ public function invalid_unit_update_inventory_usage() ]); } /** @test */ - // public function success_update_inventory_usage() - // { - // $this->success_create_inventory_usage(); + public function success_update_inventory_usage() + { + $this->success_create_inventory_usage(); - // $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); - // $data = $this->getDummyData($inventoryUsage); - // $data = data_set($data, 'id', $inventoryUsage->id, false); - - // $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->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' => 'InventoryUsage', - // 'activity' => 'Update - 1' - // ], 'tenant'); - // } + $data = $this->getDummyData($inventoryUsage); + $data = data_set($data, 'id', $inventoryUsage->id, false); + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->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' => 'InventoryUsage', + 'activity' => 'Update - 1' + ], 'tenant'); + } /** @test */ // public function unauthorized_delete_delivery_order() // { From 374912502e176fe592d9999b3cf339ed69c07c9c Mon Sep 17 00:00:00 2001 From: addincw Date: Sun, 4 Dec 2022 07:38:53 +0700 Subject: [PATCH 07/16] inventory-usage: add more unit test, asserting json on unit test --- .../InventoryUsage/InventoryUsageSetup.php | 23 ++- .../InventoryUsage/InventoryUsageTest.php | 171 ++++++++++++++++-- tests/TestCase.php | 8 +- 3 files changed, 185 insertions(+), 17 deletions(-) diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php index a979a7417..b36d704c1 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php @@ -16,6 +16,7 @@ use App\Model\SettingJournal; use App\Model\Accounting\ChartOfAccount; use App\Model\HumanResource\Employee\Employee; +use App\Model\Master\Branch; use App\User; trait InventoryUsageSetup { @@ -61,7 +62,16 @@ protected function unsetUserRole() ->delete(); } - private function createWarehouse($branch = null) + protected function createBranch() + { + $branch = new Branch(); + $branch->name = 'Test branch'; + $branch->save(); + + return $branch; + } + + protected function createWarehouse($branch = null) { $warehouse = new Warehouse(); $warehouse->name = 'Test warehouse'; @@ -117,6 +127,17 @@ private function createItemWithStocks($unit) return $item; } + private function changeUserDefaultBranch($newBranch = null) + { + $this->tenantUser->branches()->syncWithoutDetaching($newBranch); + foreach ($this->tenantUser->branches as $branch) { + if ($newBranch->id === $branch->id) { + $branch->pivot->is_default = true; + $branch->pivot->save(); + } + } + } + private function changeActingAs($tenantUser, $inventoryUsage) { $tenantUser->branches()->syncWithoutDetaching($inventoryUsage->form->branch_id); diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index 5f24f6cc5..ba9e58162 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -4,11 +4,7 @@ use Tests\TestCase; -use App\Model\Form; use App\Model\Inventory\InventoryUsage\InventoryUsage; -use App\Model\Sales\DeliveryOrder\DeliveryOrder; -use App\Model\Sales\DeliveryNote\DeliveryNote; -use App\Model\Sales\DeliveryNote\DeliveryNoteItem; class InventoryUsageTest extends TestCase { @@ -16,6 +12,47 @@ class InventoryUsageTest extends TestCase public static $path = '/api/v1/inventory/usages'; + /** @test */ + public function unauthorized_branch_create_inventory_usage() + { + $this->setRole('inventory'); + $this->setPermission('create inventory usage'); + + $this->branchDefault = null; + foreach ($this->tenantUser->branches as $branch) { + $branch->pivot->is_default = false; + $branch->pivot->save(); + } + + $data = $this->getDummyData(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "please set default branch to create this form" + ]); + } + /** @test */ + public function unauthorized_warehouse_create_inventory_usage() + { + $this->setRole('inventory'); + $this->setPermission('create inventory usage'); + + // make warehouse request difference with use default warehouse + $this->warehouseSelected = $this->createWarehouse($this->branchDefault); + + $data = $this->getDummyData(); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Warehouse Test warehouse not set as default" + ]); + } /** @test */ public function unauthorized_create_inventory_usage() { @@ -54,7 +91,11 @@ public function invalid_create_inventory_usage() $response = $this->json('POST', self::$path, $data, $this->headers); - $response->assertStatus(422); + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid.", + ]); } /** @test */ public function invalid_unit_create_inventory_usage() @@ -110,7 +151,7 @@ public function success_approve_inventory_usage() /** @test */ public function read_all_inventory_usage() { - $this->setRole(); + $this->success_create_inventory_usage(); $data = [ 'join' => 'form,warehouse,items,item', @@ -122,13 +163,42 @@ public function read_all_inventory_usage() 'filter_date_min' => '{"form.date":"' . date('Y-m-01') . ' 00:00:00"}', 'filter_date_max' => '{"form.date":"' . date('Y-m-30') . ' 23:59:59"}', 'limit' => 10, - 'includes' => 'form', + 'includes' => 'form;warehouse;items;items.item', 'page' => 1 ]; $response = $this->json('GET', self::$path, $data, $this->headers); - - $response->assertStatus(200); + + $response->assertStatus(200) + ->assertJsonStructure([ + "data" => [ + [ + "id", + "form" => [ + "approval_status", + "date", + "done", + "notes", + "number", + ], + "items" => [ + [ + "expiry_date", + "id", + "item" => [ + "id", + "name" + ], + "item_id", + "notes", + "production_number", + "quantity", + "unit", + ] + ] + ], + ] + ]); } /** @test */ public function read_inventory_usage() @@ -140,12 +210,78 @@ public function read_inventory_usage() $data = [ 'with_archives' => 'true', 'with_origin' => 'true', - 'includes' => 'form' + 'includes' => 'warehouse;items.account;items.item;items.allocation;form.createdBy;form.requestApprovalTo;form.requestCancellationTo;employee' ]; $response = $this->json('GET', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); - $response->assertStatus(200); + $response->assertStatus(200) + ->assertJsonStructure([ + "data" => [ + "employee" => [ + "id", + "name", + ], + "employee_id", + "form" => [ + "approval_at", + "approval_status", + "created_by" => [ + "first_name", + "full_name", + "id", + "last_name", + ], + "date", + "done", + "id", + "notes", + "number", + "request_approval_at", + "request_approval_to" => [ + "email", + "first_name", + "full_name", + "id", + "last_name", + ], + ], + "id", + "items" => [ + [ + "account" => [ + "id", + "alias", + "label", + "number" + ], + "allocation" => [ + "id", + "name", + ], + "allocation_id", + "expiry_date", + "id", + "item" => [ + "code", + "id", + "label", + "name" + ], + "item_id", + "notes", + "production_number", + "quantity", + "unit", + ] + ], + "warehouse" => [ + "id", + "name", + ], + "warehouse_id" + ], + ]); } /** @test */ public function unauthorized_update_inventory_usage() @@ -154,6 +290,13 @@ public function unauthorized_update_inventory_usage() $this->unsetUserRole(); + // $this->setRole('inventory'); + // $this->setPermission('create inventory usage'); + + // $unauthorizedBranch = $this->createBranch(); + // $this->changeUserDefaultBranch($unauthorizedBranch); + + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); $data = $this->getDummyData($inventoryUsage); @@ -197,7 +340,11 @@ public function invalid_update_inventory_usage() $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); - $response->assertStatus(422); + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid.", + ]); } /** @test */ public function invalid_unit_update_inventory_usage() diff --git a/tests/TestCase.php b/tests/TestCase.php index 3abc80670..1a871071c 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -143,9 +143,9 @@ protected function createSampleChartAccount($chartOfAccountType) $this->account = $chartOfAccount; } - protected function setRole() + protected function setRole($roleName = 'super admin') { - $role = \App\Model\Auth\Role::createIfNotExists('super admin'); + $role = \App\Model\Auth\Role::createIfNotExists($roleName); $hasRole = new \App\Model\Auth\ModelHasRole(); $hasRole->role_id = $role->id; $hasRole->model_type = 'App\Model\Master\User'; @@ -153,9 +153,9 @@ protected function setRole() $hasRole->save(); } - protected function setPermission() + protected function setPermission($permissionName = 'read pin point sales visitation form') { - $permission = \App\Model\Auth\Permission::createIfNotExists('read pin point sales visitation form'); + $permission = \App\Model\Auth\Permission::createIfNotExists($permissionName); $hasPermission = new \App\Model\Auth\ModelHasPermission(); $hasPermission->permission_id = $permission->id; $hasPermission->model_type = 'App\Model\Master\User'; From 749513e2f7f36a5a958f9a6a575ddfe47a11cf4c Mon Sep 17 00:00:00 2001 From: addincw Date: Sun, 4 Dec 2022 15:08:00 +0700 Subject: [PATCH 08/16] inventory-usage: wip unit test item dna --- .../InventoryUsage/InventoryUsageSetup.php | 84 +++++++++++++------ .../InventoryUsage/InventoryUsageTest.php | 67 +++++++++++++-- 2 files changed, 120 insertions(+), 31 deletions(-) diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php index b36d704c1..f08ff0b3c 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php @@ -114,19 +114,40 @@ private function createItemWithStocks($unit) $options['quantity_reference'] = $item->quantity; $options['unit_reference'] = $unit->label; $options['converter_reference'] = $unit->converter; - - if ($item->require_expiry_date) { - $options['expiry_date'] = $item->expiry_date; - } - if ($item->require_production_number) { - $options['production_number'] = $item->production_number; - } + $options['expiry_date'] = null; + $options['production_number'] = null; InventoryHelper::increase($form, $this->warehouseSelected, $item, 500, $unit->label, 1, $options); return $item; } + private function createItemDnaWithStocks($unit) + { + $item = factory(Item::class)->create([ + "require_expiry_date" => true, + "require_production_number" => true + ]); + $item->units()->save($unit); + + $form = new Form; + $form->date = now()->toDateTimeString(); + $form->created_by = $this->tenantUser->id; + $form->updated_by = $this->tenantUser->id; + $form->save(); + + $options = []; + $options['quantity_reference'] = $item->quantity; + $options['unit_reference'] = $unit->label; + $options['converter_reference'] = $unit->converter; + $options['expiry_date'] = date('Y-m-31 23:59:59'); + $options['production_number'] = 'TEST001'; + + InventoryHelper::increase($form, $this->warehouseSelected, $item, 500, $unit->label, 1, $options); + + return [$item, $options]; + } + private function changeUserDefaultBranch($newBranch = null) { $this->tenantUser->branches()->syncWithoutDetaching($newBranch); @@ -158,7 +179,7 @@ private function changeActingAs($tenantUser, $inventoryUsage) $this->actingAs($user, 'api'); } - private function getDummyData($inventoryUsage = null, $itemUnit = 'pcs') + private function getDummyData($inventoryUsage = null, $itemUnit = 'pcs', $isItemDna = false) { $warehouse = $this->warehouseSelected; $unit = new ItemUnit([ @@ -192,27 +213,25 @@ private function getDummyData($inventoryUsage = null, $itemUnit = 'pcs') return $query->whereIn('alias', ['BEBAN OPERASIONAL', 'BEBAN NON OPERASIONAL']); })->first(); - $item = $this->createItemWithStocks($unit); + if ($isItemDna) { + $createdItemDna = $this->createItemDnaWithStocks($unit); + $item = $createdItemDna[0]; + $itemDna = [ + "quantity" => $quantity, + "expiry_date" => convert_to_server_timezone($createdItemDna[1]["expiry_date"], 'UTC', 'asia/jakarta'), + "production_number" => $createdItemDna[1]["production_number"], + ]; + + } else { + $item = $this->createItemWithStocks($unit); + } $role = Role::createIfNotExists('super admin'); $approver = factory(TenantUser::class)->create(); $approver->assignRole($role); } - - return [ - "increment_group" => date("Ym"), - "date" => date("Y-m-d H:i:s"), - "warehouse_id" => $warehouse->id, - "warehouse_name" => $warehouse->name, - "employee_id" => $employee->id, - "employee_name" => $employee->name, - "request_approval_to" => $approver->id, - "approver_name" => $approver->name, - "approver_email" => $approver->email, - "notes" => null, - "items" => [ - [ + $usageItem = [ "item_id" => $item->id, "item_name" => $item->name, "item_label" => "[{$item->code}] - {$item->name}", @@ -227,8 +246,23 @@ private function getDummyData($inventoryUsage = null, $itemUnit = 'pcs') "allocation_name" => $allocation->name, "notes" => null, "more" => false, - ] - ] + ]; + if ($isItemDna) { + $usageItem['dna'] = [$itemDna]; + } + + return [ + "increment_group" => date("Ym"), + "date" => date("Y-m-d H:i:s"), + "warehouse_id" => $warehouse->id, + "warehouse_name" => $warehouse->name, + "employee_id" => $employee->id, + "employee_name" => $employee->name, + "request_approval_to" => $approver->id, + "approver_name" => $approver->name, + "approver_email" => $approver->email, + "notes" => null, + "items" => [$usageItem] ]; } } diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index ba9e58162..805931d66 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -112,6 +112,21 @@ public function invalid_unit_create_inventory_usage() ]); } /** @test */ + public function invalid_dna_create_inventory_usage() + { + $this->setRole(); + + $data = $this->getDummyData(null, $itemUnit = 'pcs', $isItemDna = true); + + $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "there are some item not in 'pcs' unit" + ]); + } + /** @test */ public function success_create_inventory_usage() { $this->setRole(); @@ -284,18 +299,58 @@ public function read_inventory_usage() ]); } /** @test */ - public function unauthorized_update_inventory_usage() + public function unauthorized_branch_update_inventory_usage() { $this->success_create_inventory_usage(); - $this->unsetUserRole(); + $this->setRole('inventory'); + $this->setPermission('update inventory usage'); - // $this->setRole('inventory'); - // $this->setPermission('create inventory usage'); + $this->branchDefault = null; + foreach ($this->tenantUser->branches as $branch) { + $branch->pivot->is_default = false; + $branch->pivot->save(); + } - // $unauthorizedBranch = $this->createBranch(); - // $this->changeUserDefaultBranch($unauthorizedBranch); + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + $data = $this->getDummyData($inventoryUsage); + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "please set default branch to update this form" + ]); + } + /** @test */ + public function unauthorized_warehouse_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $this->setRole('inventory'); + $this->setPermission('update inventory usage'); + + // make warehouse request difference with use default warehouse + $this->warehouseSelected = $this->createWarehouse($this->branchDefault); + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + $data = $this->getDummyData($inventoryUsage); + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Warehouse Test warehouse not set as default" + ]); + } + /** @test */ + public function unauthorized_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $this->unsetUserRole(); $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); $data = $this->getDummyData($inventoryUsage); From 4899507740274d39b0c7de5b90acdce0f6e470b9 Mon Sep 17 00:00:00 2001 From: addincw Date: Tue, 13 Dec 2022 06:47:41 +0700 Subject: [PATCH 09/16] [inventory-usage]: wip unit test feature update --- .../Inventory/Usage/UpdateRequest.php | 6 +- .../InventoryUsageApprovalTest.php | 78 +++++++-- .../InventoryUsage/InventoryUsageTest.php | 155 +++++++++++++++--- 3 files changed, 200 insertions(+), 39 deletions(-) diff --git a/app/Http/Requests/Inventory/Usage/UpdateRequest.php b/app/Http/Requests/Inventory/Usage/UpdateRequest.php index 068444cea..79f90180f 100644 --- a/app/Http/Requests/Inventory/Usage/UpdateRequest.php +++ b/app/Http/Requests/Inventory/Usage/UpdateRequest.php @@ -31,14 +31,14 @@ public function rules() $rulesForm['date'] = 'required|date|after_or_equal:'.optional($inventoryUsage->form)->date; $rulesUpdate = [ - 'warehouse_id' => 'required', + 'warehouse_id' => ValidationRule::foreignKey('warehouses'), 'request_approval_to' => 'required', - + 'notes' => 'nullable|string|max:255', 'items.*.item_id' => ValidationRule::foreignKey('items'), 'items.*.quantity' => ValidationRule::quantity(), 'items.*.unit' => ValidationRule::unit(), 'items.*.converter' => ValidationRule::converter(), - 'items.*.chart_of_account_id' => 'required', + 'items.*.chart_of_account_id' => ValidationRule::foreignKey('chart_of_accounts'), ]; return array_merge($rulesForm, $rulesUpdate); diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php index 781f57474..e21bfc821 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php @@ -4,6 +4,8 @@ use Tests\TestCase; +use App\Model\SettingJournal; +use App\Model\Master\Item; use App\Model\Inventory\InventoryUsage\InventoryUsage; class InventoryUsageApprovalTest extends TestCase @@ -36,7 +38,7 @@ public function success_create_inventory_usage($isFirstCreate = true) } /** @test */ - public function unauthorized_approve_inventory_usage() + public function iu_af1_unauthorized_approve_inventory_usage() { $this->success_create_inventory_usage(); @@ -51,12 +53,38 @@ public function unauthorized_approve_inventory_usage() ]); } + /** @test */ + public function iu_ef13_invalid_journal_approve_inventory_usage() + { + $this->success_create_inventory_usage(); + + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + + $approver = $inventoryUsage->form->requestApprovalTo; + $this->changeActingAs($approver, $inventoryUsage); + + SettingJournal::where('feature', 'inventory usage') + ->where('name', 'difference stock expense') + ->update([ + "chart_of_account_id" => null, + ]); + + $response = $this->json('POST', self::$path . '/' . $inventoryUsage->id . '/approve', [], $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Journal inventory usage account - difference stock expense not found" + ]); + } + /** @test */ public function success_approve_inventory_usage() { $this->success_create_inventory_usage(); $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + $inventoryUsageItem = $inventoryUsage->items()->first(); $approver = $inventoryUsage->form->requestApprovalTo; $this->changeActingAs($approver, $inventoryUsage); @@ -64,6 +92,13 @@ public function success_approve_inventory_usage() $response = $this->json('POST', self::$path . '/' . $inventoryUsage->id . '/approve', [], $this->headers); $response->assertStatus(200); + + $this->assertDatabaseHas('journals', [ + 'form_id' => $inventoryUsage->form->id, + 'journalable_type' => Item::$morphName, + 'journalable_id' => $inventoryUsageItem->item_id, + 'chart_of_account_id' => $inventoryUsageItem->chart_of_account_id, + ], 'tenant'); $this->assertDatabaseHas('forms', [ 'id' => $response->json('data.form.id'), 'number' => $response->json('data.form.number'), @@ -79,7 +114,7 @@ public function success_approve_inventory_usage() } /** @test */ - public function not_found_form_approve_inventory_usage() + public function iu_af2_not_found_form_approve_inventory_usage() { $this->success_approve_inventory_usage(); @@ -95,36 +130,45 @@ public function not_found_form_approve_inventory_usage() } /** @test */ - public function unauthorized_reject_inventory_usage() + public function iu_rf1_invalid_reject_inventory_usage() { $this->success_create_inventory_usage(); $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); - $data['reason'] = $this->faker->text(200); - - $response = $this->json('POST', self::$path . '/' . $inventoryUsage->id . '/reject', $data, $this->headers); + $approver = $inventoryUsage->form->requestApprovalTo; + $this->changeActingAs($approver, $inventoryUsage); + $response = $this->json('POST', self::$path . '/' . $inventoryUsage->id . '/reject', [], $this->headers); + $response->assertStatus(422) ->assertJson([ "code" => 422, - "message" => "Unauthorized" + "message" => "The given data was invalid.", + "errors" => [ + "reason" => [ + "The reason field is required." + ] + ] ]); } /** @test */ - public function invalid_reject_inventory_usage() + public function iu_rf2_unauthorized_reject_inventory_usage() { $this->success_create_inventory_usage(); $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); - $approver = $inventoryUsage->form->requestApprovalTo; - $this->changeActingAs($approver, $inventoryUsage); + $data['reason'] = $this->faker->text(200); - $response = $this->json('POST', self::$path . '/' . $inventoryUsage->id . '/reject', [], $this->headers); + $response = $this->json('POST', self::$path . '/' . $inventoryUsage->id . '/reject', $data, $this->headers); - $response->assertStatus(422); + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Unauthorized" + ]); } /** @test */ @@ -133,6 +177,7 @@ public function success_reject_inventory_usage() $this->success_create_inventory_usage(); $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + $inventoryUsageItem = $inventoryUsage->items()->first(); $approver = $inventoryUsage->form->requestApprovalTo; $this->changeActingAs($approver, $inventoryUsage); @@ -142,6 +187,13 @@ public function success_reject_inventory_usage() $response = $this->json('POST', self::$path . '/' . $inventoryUsage->id . '/reject', $data, $this->headers); $response->assertStatus(200); + + $this->assertDatabaseMissing('journals', [ + 'form_id' => $inventoryUsage->form->id, + 'journalable_type' => Item::$morphName, + 'journalable_id' => $inventoryUsageItem->item_id, + 'chart_of_account_id' => $inventoryUsageItem->chart_of_account_id, + ], 'tenant'); $this->assertDatabaseHas('forms', [ 'id' => $response->json('data.form.id'), 'number' => $response->json('data.form.number'), @@ -157,7 +209,7 @@ public function success_reject_inventory_usage() } /** @test */ - public function not_found_form_reject_inventory_usage() + public function iu_rf3_not_found_form_reject_inventory_usage() { $this->success_reject_inventory_usage(); diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index 805931d66..d916c3e50 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -2,9 +2,12 @@ namespace Tests\Feature\Http\Inventory\InventoryUsage; +use Illuminate\Support\Facades\Mail; use Tests\TestCase; +use App\Mail\Inventory\InventoryUsageApprovalMail; use App\Model\Inventory\InventoryUsage\InventoryUsage; +use App\Model\Master\Item; class InventoryUsageTest extends TestCase { @@ -112,21 +115,6 @@ public function invalid_unit_create_inventory_usage() ]); } /** @test */ - public function invalid_dna_create_inventory_usage() - { - $this->setRole(); - - $data = $this->getDummyData(null, $itemUnit = 'pcs', $isItemDna = true); - - $response = $this->json('POST', self::$path, $data, $this->headers); - - $response->assertStatus(422) - ->assertJson([ - "code" => 422, - "message" => "there are some item not in 'pcs' unit" - ]); - } - /** @test */ public function success_create_inventory_usage() { $this->setRole(); @@ -299,7 +287,7 @@ public function read_inventory_usage() ]); } /** @test */ - public function unauthorized_branch_update_inventory_usage() + public function iu_ef1_unauthorized_branch_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -324,7 +312,7 @@ public function unauthorized_branch_update_inventory_usage() ]); } /** @test */ - public function unauthorized_warehouse_update_inventory_usage() + public function iu_ef2_unauthorized_warehouse_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -346,7 +334,7 @@ public function unauthorized_warehouse_update_inventory_usage() ]); } /** @test */ - public function unauthorized_update_inventory_usage() + public function iu_ef5_unauthorized_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -364,7 +352,7 @@ public function unauthorized_update_inventory_usage() ]); } /** @test */ - public function overquantity_update_inventory_usage() + public function iu_ef6_invalid_date_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -372,18 +360,21 @@ public function overquantity_update_inventory_usage() $data = $this->getDummyData($inventoryUsage); $data = data_set($data, 'id', $inventoryUsage->id, false); - $data = data_set($data, 'items.0.quantity', 2000); + $data = data_set($data, 'date', '1970-01-01', true); // date less than create $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); $response->assertStatus(422) ->assertJson([ "code" => 422, - "message" => "Stock {$data['items'][0]['item_name']} not enough" + "message" => "The given data was invalid.", + "errors" => [ + "date" => ["The date must be a date after or equal to {$inventoryUsage->form->date}."], + ] ]); } /** @test */ - public function invalid_update_inventory_usage() + public function iu_ef7_invalid_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -402,7 +393,26 @@ public function invalid_update_inventory_usage() ]); } /** @test */ - public function invalid_unit_update_inventory_usage() + public function iu_ef9_overquantity_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($inventoryUsage); + $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = data_set($data, 'items.0.quantity', 2000); + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Stock {$data['items'][0]['item_name']} not enough" + ]); + } + /** @test */ + public function iu_ef10_invalid_unit_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -419,6 +429,89 @@ public function invalid_unit_update_inventory_usage() ]); } /** @test */ + public function iu_ef16_invalid_notes_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($inventoryUsage); + $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = data_set($data, 'notes', str_pad('', 500, 'X', STR_PAD_LEFT), true); // over maximum length of notes + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid.", + "errors" => [ + "notes" => ["The notes may not be greater than 255 characters."], + ] + ]); + } + /** @test */ + public function iu_ef17_invalid_warehouse_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($inventoryUsage); + $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = data_set($data, 'warehouse_id', 99, true); // random warehouse_id + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Warehouse Test warehouse not set as default" + ]); + } + /** @test */ + public function iu_ef18_invalid_item_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($inventoryUsage); + $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = data_set($data, 'items.0.item_id', 99, true); // random item_id + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid.", + "errors" => [ + "items.0.item_id" => ["The selected items.0.item_id is invalid."], + ] + ]); + } + /** @test */ + public function iu_ef19_invalid_account_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($inventoryUsage); + $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = data_set($data, 'items.0.chart_of_account_id', 99, true); // random item_id + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "The given data was invalid.", + "errors" => [ + "items.0.chart_of_account_id" => ["The selected items.0.chart_of_account_id is invalid."], + ] + ]); + } + /** @test */ public function success_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -428,9 +521,16 @@ public function success_update_inventory_usage() $data = $this->getDummyData($inventoryUsage); $data = data_set($data, 'id', $inventoryUsage->id, false); + Mail::fake(); + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); $response->assertStatus(201); + + $this->assertDatabaseHas('forms', [ + 'number' => $response->json('data.form.number'), + 'approval_status' => 0, + ], 'tenant'); $this->assertDatabaseHas('forms', [ 'edited_number' => $response->json('data.form.number') ], 'tenant'); $this->assertDatabaseHas('user_activities', [ 'number' => $response->json('data.form.number'), @@ -438,6 +538,15 @@ public function success_update_inventory_usage() 'table_type' => 'InventoryUsage', 'activity' => 'Update - 1' ], 'tenant'); + + $this->assertDatabaseMissing('journals', [ + 'form_id' => $response->json('data.form.id'), + 'journalable_type' => Item::$morphName, + 'journalable_id' => $response->json('data.items.0.item_id'), + 'chart_of_account_id' => $response->json('data.items.0.chart_of_account_id'), + ], 'tenant'); + + Mail::assertQueued(InventoryUsageApprovalMail::class); } /** @test */ // public function unauthorized_delete_delivery_order() From ee14a8f4b185c29bd6e0b21612d4f854d80e8bf8 Mon Sep 17 00:00:00 2001 From: addincw Date: Tue, 13 Dec 2022 14:03:42 +0700 Subject: [PATCH 10/16] [inventory-usage]: wip unit test feature update --- .../InventoryUsage/InventoryUsage.php | 10 +++ .../InventoryUsageApprovalTest.php | 62 ++++++++++++++++--- .../InventoryUsage/InventoryUsageSetup.php | 55 +++++++++++++++- .../InventoryUsage/InventoryUsageTest.php | 46 ++++++++++++++ 4 files changed, 161 insertions(+), 12 deletions(-) diff --git a/app/Model/Inventory/InventoryUsage/InventoryUsage.php b/app/Model/Inventory/InventoryUsage/InventoryUsage.php index a98fa811e..0e9ae1e0e 100644 --- a/app/Model/Inventory/InventoryUsage/InventoryUsage.php +++ b/app/Model/Inventory/InventoryUsage/InventoryUsage.php @@ -4,6 +4,8 @@ use Exception; use App\Exceptions\StockNotEnoughException; +use App\Exceptions\ExpiryDateNotFoundException; +use App\Exceptions\ProductionNumberNotFoundException; use App\Helpers\Inventory\InventoryHelper; use App\Mail\Inventory\InventoryUsageApprovalMail; use App\Model\TransactionModel; @@ -174,6 +176,14 @@ private static function mapItems($items, $inventoryUsage) if ($itemModel->require_production_number || $itemModel->require_expiry_date) { if ($item['dna']) { foreach ($item['dna'] as $dna) { + if ($itemModel->require_production_number && !isset($dna['production_number'])) { + throw new ProductionNumberNotFoundException($itemModel); + } + + if ($itemModel->require_expiry_date && !isset($dna['expiry_date'])) { + throw new ExpiryDateNotFoundException($itemModel); + } + if ($dna['quantity'] > 0) { $options = [ 'expiry_date' => $dna['expiry_date'], diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php index e21bfc821..31c037f01 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php @@ -83,22 +83,33 @@ public function success_approve_inventory_usage() { $this->success_create_inventory_usage(); - $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); - $inventoryUsageItem = $inventoryUsage->items()->first(); + $usage = InventoryUsage::orderBy('id', 'asc')->first(); + $usageItem = $usage->items()->first(); + $usageItemAmount = $usageItem->item->cogs($usageItem->item_id) * $usageItem->quantity; - $approver = $inventoryUsage->form->requestApprovalTo; - $this->changeActingAs($approver, $inventoryUsage); - - $response = $this->json('POST', self::$path . '/' . $inventoryUsage->id . '/approve', [], $this->headers); + $approver = $usage->form->requestApprovalTo; + $this->changeActingAs($approver, $usage); + $response = $this->json('POST', self::$path . '/' . $usage->id . '/approve', [], $this->headers); $response->assertStatus(200); + // check balance and match amount $this->assertDatabaseHas('journals', [ - 'form_id' => $inventoryUsage->form->id, + 'form_id' => $usage->form->id, 'journalable_type' => Item::$morphName, - 'journalable_id' => $inventoryUsageItem->item_id, - 'chart_of_account_id' => $inventoryUsageItem->chart_of_account_id, + 'journalable_id' => $usageItem->item_id, + 'chart_of_account_id' => $usageItem->chart_of_account_id, + 'debit' => $usageItemAmount, ], 'tenant'); + $this->assertDatabaseHas('journals', [ + 'form_id' => $usage->form->id, + 'journalable_type' => Item::$morphName, + 'journalable_id' => $usageItem->item_id, + 'chart_of_account_id' => get_setting_journal('inventory usage', 'difference stock expense'), + 'credit' => $usageItemAmount, + ], 'tenant'); + + // change form status changed and logged $this->assertDatabaseHas('forms', [ 'id' => $response->json('data.form.id'), 'number' => $response->json('data.form.number'), @@ -111,6 +122,23 @@ public function success_approve_inventory_usage() 'table_type' => 'InventoryUsage', 'activity' => 'Approved' ], 'tenant'); + + $responseRecap = $this->json('GET', '/api/v1/inventory/inventory-recapitulations', [ + 'includes' => 'account', + 'sort_by' => 'code;name', + 'limit' => 10, + 'page' => 1, + 'date_from' => date('Y-m-01') . ' 00:00:00', + 'filter_to' => date('Y-m-31') . ' 23:59:59', + 'filter_like' => '{}', + ], $this->headers); + $responseRecap->assertStatus(200) + ->assertJsonFragment([ + "name" => $usageItem->item->name, + "stock_in" => number_format((float) $this->initialItemQuantity, 30, '.', ''), + "stock_out" => number_format((float) $this->initialUsageItemQuantity * -1, 30, '.', ''), + "ending_balance" => number_format((float) $this->initialItemQuantity + ($this->initialUsageItemQuantity * -1), 30, '.', '') + ]); } /** @test */ @@ -194,6 +222,7 @@ public function success_reject_inventory_usage() 'journalable_id' => $inventoryUsageItem->item_id, 'chart_of_account_id' => $inventoryUsageItem->chart_of_account_id, ], 'tenant'); + $this->assertDatabaseHas('forms', [ 'id' => $response->json('data.form.id'), 'number' => $response->json('data.form.number'), @@ -206,6 +235,21 @@ public function success_reject_inventory_usage() 'table_type' => 'InventoryUsage', 'activity' => 'Rejected' ], 'tenant'); + + $responseRecap = $this->json('GET', '/api/v1/inventory/inventory-recapitulations', [ + 'includes' => 'account', + 'sort_by' => 'code;name', + 'limit' => 10, + 'page' => 1, + 'date_from' => date('Y-m-01') . ' 00:00:00', + 'filter_to' => date('Y-m-31') . ' 23:59:59', + 'filter_like' => '{}', + ], $this->headers); + $responseRecap->assertStatus(200) + ->assertJsonMissing([ + "stock_out" => number_format((float) $this->initialUsageItemQuantity * -1, 30, '.', ''), + "ending_balance" => number_format((float) $this->initialItemQuantity + ($this->initialUsageItemQuantity * -1), 30, '.', '') + ]); } /** @test */ diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php index f08ff0b3c..2414d8618 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageSetup.php @@ -24,6 +24,9 @@ trait InventoryUsageSetup { private $branchDefault; private $warehouseSelected; + private $initialItemQuantity = 500; + private $initialUsageItemQuantity = 5; + public function setUp(): void { parent::setUp(); @@ -117,7 +120,7 @@ private function createItemWithStocks($unit) $options['expiry_date'] = null; $options['production_number'] = null; - InventoryHelper::increase($form, $this->warehouseSelected, $item, 500, $unit->label, 1, $options); + InventoryHelper::increase($form, $this->warehouseSelected, $item, $this->initialItemQuantity, $unit->label, 1, $options); return $item; } @@ -143,7 +146,7 @@ private function createItemDnaWithStocks($unit) $options['expiry_date'] = date('Y-m-31 23:59:59'); $options['production_number'] = 'TEST001'; - InventoryHelper::increase($form, $this->warehouseSelected, $item, 500, $unit->label, 1, $options); + InventoryHelper::increase($form, $this->warehouseSelected, $item, $this->initialItemQuantity, $unit->label, 1, $options); return [$item, $options]; } @@ -178,6 +181,52 @@ private function changeActingAs($tenantUser, $inventoryUsage) $user->save(); $this->actingAs($user, 'api'); } + + private function getDummyDataItem($isItemDna = false) + { + $allocation = factory(Allocation::class)->create(); + $chartOfAccount = ChartOfAccount::whereHas('type', function ($query) { + return $query->whereIn('alias', ['BEBAN OPERASIONAL', 'BEBAN NON OPERASIONAL']); + })->first(); + $unit = new ItemUnit(['label' => 'pcs', 'name' => 'pcs', 'converter' => 1]); + + $quantity = $this->initialItemQuantity; + + if ($isItemDna) { + $createdItemDna = $this->createItemDnaWithStocks($unit); + $item = $createdItemDna[0]; + $itemDna = [ + "quantity" => $quantity, + "expiry_date" => convert_to_server_timezone($createdItemDna[1]["expiry_date"], 'UTC', 'asia/jakarta'), + "production_number" => $createdItemDna[1]["production_number"], + ]; + } else { + $item = $this->createItemWithStocks($unit); + } + + $usageItem = [ + "item_id" => $item->id, + "item_name" => $item->name, + "item_label" => "[{$item->code}] - {$item->name}", + "chart_of_account_id" => $chartOfAccount->id, + "chart_of_account_name" => $chartOfAccount->alias, + "require_expiry_date" => 0, + "require_production_number" => 0, + "unit" => $unit->name, + "converter" => $unit->converter, + "quantity" => $quantity, + "allocation_id" => $allocation->id, + "allocation_name" => $allocation->name, + "notes" => null, + "more" => false, + ]; + + if ($isItemDna) { + $usageItem['dna'] = [$itemDna]; + } + + return $usageItem; + } private function getDummyData($inventoryUsage = null, $itemUnit = 'pcs', $isItemDna = false) { @@ -187,7 +236,7 @@ private function getDummyData($inventoryUsage = null, $itemUnit = 'pcs', $isItem 'name' => $itemUnit, 'converter' => 1, ]); - $quantity = 5; + $quantity = $this->initialUsageItemQuantity; if ($inventoryUsage) { $inventoryUsageItem = $inventoryUsage->items()->first(); diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index d916c3e50..cda2eb247 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -429,6 +429,52 @@ public function iu_ef10_invalid_unit_update_inventory_usage() ]); } /** @test */ + public function iu_ef11_invalid_productionnumber_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($inventoryUsage); + + $dataUsageItem = $this->getDummyDataItem($isItemDna = true); + $dataUsageItem = data_set($dataUsageItem, 'dna.0.production_number', null, true); + + $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = data_set($data, 'items.1', $dataUsageItem, false); // item dna without production number + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => 'Production Number for Item '.$dataUsageItem['item_name'].' not found' + ]); + } + /** @test */ + public function iu_ef12_invalid_expirydate_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + + $data = $this->getDummyData($inventoryUsage); + + $dataUsageItem = $this->getDummyDataItem($isItemDna = true); + $dataUsageItem = data_set($dataUsageItem, 'dna.0.expiry_date', null, true); + + $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = data_set($data, 'items.1', $dataUsageItem, false); // item dna without expry date + + $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => "Expiry Date for Item -{$dataUsageItem['item_name']} not found" + ]); + } + /** @test */ public function iu_ef16_invalid_notes_update_inventory_usage() { $this->success_create_inventory_usage(); From 4583f99d3e30cc8bfc4477b98d72fdf248dbc1b4 Mon Sep 17 00:00:00 2001 From: addincw Date: Tue, 13 Dec 2022 21:24:53 +0700 Subject: [PATCH 11/16] [inventory-usage]: completing unit test feature update --- .../InputBackDateForbiddenException.php | 6 +- app/Helpers/Inventory/InventoryHelper.php | 2 +- .../InventoryUsageApprovalTest.php | 88 +++++++++++++++++++ .../InventoryUsage/InventoryUsageTest.php | 12 +-- 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/app/Exceptions/InputBackDateForbiddenException.php b/app/Exceptions/InputBackDateForbiddenException.php index d2a4092a1..33f825a57 100644 --- a/app/Exceptions/InputBackDateForbiddenException.php +++ b/app/Exceptions/InputBackDateForbiddenException.php @@ -2,14 +2,16 @@ namespace App\Exceptions; +use App\Model\Inventory\InventoryAudit\InventoryAudit; use Exception; class InputBackDateForbiddenException extends Exception { public function __construct($audit, $item) { + $form = $audit->form ?? InventoryAudit::find($audit->id)->form; parent::__construct('Input error because'. - $item->label.' already audited in '.$audit->form->number.' on '. - date('d F Y H:i', strtotime($audit->form->date)), 422); + $item->label.' already audited in '.$form->number.' on '. + date('d F Y H:i', strtotime($form->date)), 422); } } diff --git a/app/Helpers/Inventory/InventoryHelper.php b/app/Helpers/Inventory/InventoryHelper.php index 204122938..a3f771c20 100644 --- a/app/Helpers/Inventory/InventoryHelper.php +++ b/app/Helpers/Inventory/InventoryHelper.php @@ -177,7 +177,7 @@ public static function auditExists($item, $date, $warehouse, $options) $inventoryExist = InventoryAuditItem::join(InventoryAudit::getTableName(), InventoryAudit::getTableName('id'), '=', InventoryAuditItem::getTableName('inventory_audit_id')) ->join(Form::getTableName(), function ($query) { $query->on(Form::getTableName('formable_id'), '=', InventoryAudit::getTableName('id')) - ->where(Form::getTableName('formable_type'), '=', InventoryAudit::class); + ->where(Form::getTableName('formable_type'), '=', InventoryAudit::$morphName); }) ->where(Form::getTableName('date'), '>=', $date) // check if form is not canceled diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php index 31c037f01..289a28721 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php @@ -6,7 +6,11 @@ use App\Model\SettingJournal; use App\Model\Master\Item; +use App\Model\Master\ItemUnit; +use App\Model\Accounting\ChartOfAccount; +use App\Model\Inventory\InventoryAudit\InventoryAudit; use App\Model\Inventory\InventoryUsage\InventoryUsage; +use Carbon\Carbon; class InventoryUsageApprovalTest extends TestCase { @@ -16,6 +20,66 @@ class InventoryUsageApprovalTest extends TestCase private $previousInventoryUsageData; + /** @test */ + public function success_create_inventory_audit() + { + $chartOfAccount = ChartOfAccount::where('name', 'FACTORY DIFFERENCE STOCK EXPENSE')->first(); + $settingJournal = SettingJournal::where('feature', 'inventory audit')->where('name', 'difference stock expense')->first(); + $settingJournal->chart_of_account_id = $chartOfAccount->id; + $settingJournal->save(); + + $quantity = $this->initialItemQuantity; + + $usage = InventoryUsage::first(); + $usageItem = $usage->items()->first(); + + $warehouse = $usage->warehouse; + + $form = $usage->form; + $approver = $form->requestApprovalTo; + + $item = $usageItem->item; + $item->chart_of_account_id = $usageItem->chart_of_account_id; + $item->save(); + + $unit = ItemUnit::where('label', $usageItem->unit)->first(); + + $allocation = $usageItem->allocation; + $chartOfAccount = $usageItem->account; + + $data = [ + "increment_group" => date("Ym"), + "date" => Carbon::now()->addDays(1)->format("Y-m-d H:i:s"), + "warehouse_id" => $warehouse->id, + "request_approval_to" => $approver->id, + "approver_name" => $approver->name, + "approver_email" => $approver->email, + "notes" => null, + "items" => [ + [ + "item_id" => $item->id, + "item_name" => $item->name, + "item_label" => "[{$item->code}] - {$item->name}", + "chart_of_account_id" => $chartOfAccount->id, + "chart_of_account_name" => $chartOfAccount->alias, + "require_expiry_date" => 0, + "require_production_number" => 0, + "unit" => $unit->name, + "converter" => $unit->converter, + "quantity" => $quantity, + "allocation_id" => $allocation->id, + "allocation_name" => $allocation->name, + "notes" => null, + "more" => false + ] + ] + ]; + + $response = $this->json('POST', '/api/v1/inventory/audits', $data, $this->headers); + + $response->assertStatus(201); + } + /** @test */ public function success_create_inventory_usage($isFirstCreate = true) { @@ -53,6 +117,30 @@ public function iu_af1_unauthorized_approve_inventory_usage() ]); } + /** @test */ + public function iu_ef3_has_audit_update_inventory_usage() + { + $this->success_create_inventory_usage(); + + $this->success_create_inventory_audit(); + + $audit = InventoryAudit::first(); + + $usage = InventoryUsage::orderBy('id', 'asc')->first(); + $usageItem = $usage->items()->first(); + + $approver = $usage->form->requestApprovalTo; + $this->changeActingAs($approver, $usage); + + $response = $this->json('POST', self::$path . '/' . $usage->id . '/approve', [], $this->headers); + + $response->assertStatus(422) + ->assertJson([ + "code" => 422, + "message" => 'Input error because'. $usageItem->item->label.' already audited in '.$audit->form->number.' on '. date('d F Y H:i', strtotime($audit->form->date)) + ]); + } + /** @test */ public function iu_ef13_invalid_journal_approve_inventory_usage() { diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index cda2eb247..9725f5fbb 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -63,10 +63,10 @@ public function unauthorized_create_inventory_usage() $response = $this->json('POST', self::$path, $data, $this->headers); - $response->assertStatus(500) + $response->assertStatus(422) ->assertJson([ - "code" => 0, - "message" => "There is no permission named `create inventory usage` for guard `api`." + "code" => 422, + "message" => "Unauthorized" ]); } /** @test */ @@ -345,10 +345,10 @@ public function iu_ef5_unauthorized_update_inventory_usage() $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); - $response->assertStatus(500) + $response->assertStatus(422) ->assertJson([ - "code" => 0, - "message" => "There is no permission named `update inventory usage` for guard `api`." + "code" => 422, + "message" => "Unauthorized" ]); } /** @test */ From 3c1cd737b84144e29f4af623eaa00727b8ec8f17 Mon Sep 17 00:00:00 2001 From: addincw Date: Tue, 13 Dec 2022 21:41:58 +0700 Subject: [PATCH 12/16] [inventory-usage]: whitelist create inv audit from single unit test --- .../Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php index 289a28721..8050cf7d4 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php @@ -20,7 +20,6 @@ class InventoryUsageApprovalTest extends TestCase private $previousInventoryUsageData; - /** @test */ public function success_create_inventory_audit() { $chartOfAccount = ChartOfAccount::where('name', 'FACTORY DIFFERENCE STOCK EXPENSE')->first(); From 323953f845f7c3fb3d778a230b02fb9434113d59 Mon Sep 17 00:00:00 2001 From: addincw Date: Tue, 13 Dec 2022 22:28:43 +0700 Subject: [PATCH 13/16] [invetory-usage]: fix assertion on unauthorized case --- .../Inventory/InventoryUsage/InventoryUsageTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index 9725f5fbb..cda2eb247 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -63,10 +63,10 @@ public function unauthorized_create_inventory_usage() $response = $this->json('POST', self::$path, $data, $this->headers); - $response->assertStatus(422) + $response->assertStatus(500) ->assertJson([ - "code" => 422, - "message" => "Unauthorized" + "code" => 0, + "message" => "There is no permission named `create inventory usage` for guard `api`." ]); } /** @test */ @@ -345,10 +345,10 @@ public function iu_ef5_unauthorized_update_inventory_usage() $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); - $response->assertStatus(422) + $response->assertStatus(500) ->assertJson([ - "code" => 422, - "message" => "Unauthorized" + "code" => 0, + "message" => "There is no permission named `update inventory usage` for guard `api`." ]); } /** @test */ From bf7abb6c6e023504ac1d31129ccac761023f4090 Mon Sep 17 00:00:00 2001 From: addincw Date: Tue, 20 Dec 2022 07:37:03 +0700 Subject: [PATCH 14/16] [inventory usage] tdd - change function name --- .../InventoryUsageApprovalTest.php | 15 +++-- .../InventoryUsageHistoryTest.php | 1 - .../InventoryUsage/InventoryUsageTest.php | 59 ++++++++++++++----- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php index 8050cf7d4..3745bddaa 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php @@ -79,7 +79,6 @@ public function success_create_inventory_audit() $response->assertStatus(201); } - /** @test */ public function success_create_inventory_usage($isFirstCreate = true) { $data = $this->getDummyData(); @@ -101,7 +100,7 @@ public function success_create_inventory_usage($isFirstCreate = true) } /** @test */ - public function iu_af1_unauthorized_approve_inventory_usage() + public function unauthorized_approve_inventory_usage() { $this->success_create_inventory_usage(); @@ -117,7 +116,7 @@ public function iu_af1_unauthorized_approve_inventory_usage() } /** @test */ - public function iu_ef3_has_audit_update_inventory_usage() + public function has_audit_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -141,7 +140,7 @@ public function iu_ef3_has_audit_update_inventory_usage() } /** @test */ - public function iu_ef13_invalid_journal_approve_inventory_usage() + public function invalid_journal_approve_inventory_usage() { $this->success_create_inventory_usage(); @@ -229,7 +228,7 @@ public function success_approve_inventory_usage() } /** @test */ - public function iu_af2_not_found_form_approve_inventory_usage() + public function not_found_form_approve_inventory_usage() { $this->success_approve_inventory_usage(); @@ -245,7 +244,7 @@ public function iu_af2_not_found_form_approve_inventory_usage() } /** @test */ - public function iu_rf1_invalid_reject_inventory_usage() + public function invalid_reject_inventory_usage() { $this->success_create_inventory_usage(); @@ -269,7 +268,7 @@ public function iu_rf1_invalid_reject_inventory_usage() } /** @test */ - public function iu_rf2_unauthorized_reject_inventory_usage() + public function unauthorized_reject_inventory_usage() { $this->success_create_inventory_usage(); @@ -340,7 +339,7 @@ public function success_reject_inventory_usage() } /** @test */ - public function iu_rf3_not_found_form_reject_inventory_usage() + public function not_found_form_reject_inventory_usage() { $this->success_reject_inventory_usage(); diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageHistoryTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageHistoryTest.php index 8167feb66..d9f2045c8 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageHistoryTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageHistoryTest.php @@ -12,7 +12,6 @@ class InventoryUsageHistoryTest extends TestCase public static $path = '/api/v1/inventory/usages'; - /** @test */ public function success_create_inventory_usage() { $this->setRole(); diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index cda2eb247..9f4f10fb0 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -122,8 +122,39 @@ public function success_create_inventory_usage() $data = $this->getDummyData(); $response = $this->json('POST', self::$path, $data, $this->headers); + + $response->assertStatus(201) + ->assertJsonStructure([ + "data" => [ + "id", + "warehouse_id", + "employee_id", + "form" => [ + "id", + "branch_id", + "approval_status", + "date", + "done", + "notes", + "number", + "request_approval_to", + ], + "items" => [ + [ + "expiry_date", + "id", + "chart_of_account_id", + "item_id", + "allocation_id", + "notes", + "production_number", + "quantity", + "unit", + ] + ] + ], + ]); - $response->assertStatus(201); $this->assertDatabaseHas('forms', [ 'id' => $response->json('data.form.id'), 'number' => $response->json('data.form.number'), @@ -287,7 +318,7 @@ public function read_inventory_usage() ]); } /** @test */ - public function iu_ef1_unauthorized_branch_update_inventory_usage() + public function unauthorized_branch_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -312,7 +343,7 @@ public function iu_ef1_unauthorized_branch_update_inventory_usage() ]); } /** @test */ - public function iu_ef2_unauthorized_warehouse_update_inventory_usage() + public function unauthorized_warehouse_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -334,7 +365,7 @@ public function iu_ef2_unauthorized_warehouse_update_inventory_usage() ]); } /** @test */ - public function iu_ef5_unauthorized_update_inventory_usage() + public function unauthorized_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -352,7 +383,7 @@ public function iu_ef5_unauthorized_update_inventory_usage() ]); } /** @test */ - public function iu_ef6_invalid_date_update_inventory_usage() + public function invalid_date_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -374,7 +405,7 @@ public function iu_ef6_invalid_date_update_inventory_usage() ]); } /** @test */ - public function iu_ef7_invalid_update_inventory_usage() + public function invalid_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -393,7 +424,7 @@ public function iu_ef7_invalid_update_inventory_usage() ]); } /** @test */ - public function iu_ef9_overquantity_update_inventory_usage() + public function overquantity_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -412,7 +443,7 @@ public function iu_ef9_overquantity_update_inventory_usage() ]); } /** @test */ - public function iu_ef10_invalid_unit_update_inventory_usage() + public function _invalid_unit_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -429,7 +460,7 @@ public function iu_ef10_invalid_unit_update_inventory_usage() ]); } /** @test */ - public function iu_ef11_invalid_productionnumber_update_inventory_usage() + public function _invalid_productionnumber_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -452,7 +483,7 @@ public function iu_ef11_invalid_productionnumber_update_inventory_usage() ]); } /** @test */ - public function iu_ef12_invalid_expirydate_update_inventory_usage() + public function _invalid_expirydate_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -475,7 +506,7 @@ public function iu_ef12_invalid_expirydate_update_inventory_usage() ]); } /** @test */ - public function iu_ef16_invalid_notes_update_inventory_usage() + public function _invalid_notes_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -497,7 +528,7 @@ public function iu_ef16_invalid_notes_update_inventory_usage() ]); } /** @test */ - public function iu_ef17_invalid_warehouse_update_inventory_usage() + public function _invalid_warehouse_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -516,7 +547,7 @@ public function iu_ef17_invalid_warehouse_update_inventory_usage() ]); } /** @test */ - public function iu_ef18_invalid_item_update_inventory_usage() + public function _invalid_item_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -537,7 +568,7 @@ public function iu_ef18_invalid_item_update_inventory_usage() ]); } /** @test */ - public function iu_ef19_invalid_account_update_inventory_usage() + public function _invalid_account_update_inventory_usage() { $this->success_create_inventory_usage(); From 4241b1311ff07f1f9bccc2ad8a790fc6a55ea59c Mon Sep 17 00:00:00 2001 From: addincw Date: Mon, 26 Dec 2022 03:30:24 +0700 Subject: [PATCH 15/16] [inventory-usage]: tdd feedbacks --- .../Inventory/Usage/UpdateRequest.php | 2 + .../InventoryUsageApprovalTest.php | 63 +++++++++- .../InventoryUsage/InventoryUsageTest.php | 114 +++++++++++++++--- 3 files changed, 162 insertions(+), 17 deletions(-) diff --git a/app/Http/Requests/Inventory/Usage/UpdateRequest.php b/app/Http/Requests/Inventory/Usage/UpdateRequest.php index 79f90180f..0c46f93f4 100644 --- a/app/Http/Requests/Inventory/Usage/UpdateRequest.php +++ b/app/Http/Requests/Inventory/Usage/UpdateRequest.php @@ -32,6 +32,7 @@ public function rules() $rulesUpdate = [ 'warehouse_id' => ValidationRule::foreignKey('warehouses'), + 'employee_id' => ValidationRule::foreignKey('employees'), 'request_approval_to' => 'required', 'notes' => 'nullable|string|max:255', 'items.*.item_id' => ValidationRule::foreignKey('items'), @@ -39,6 +40,7 @@ public function rules() 'items.*.unit' => ValidationRule::unit(), 'items.*.converter' => ValidationRule::converter(), 'items.*.chart_of_account_id' => ValidationRule::foreignKey('chart_of_accounts'), + 'items.*.allocation_id' => ValidationRule::foreignKey('allocations'), ]; return array_merge($rulesForm, $rulesUpdate); diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php index 3745bddaa..77ab05dbf 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageApprovalTest.php @@ -177,7 +177,39 @@ public function success_approve_inventory_usage() $this->changeActingAs($approver, $usage); $response = $this->json('POST', self::$path . '/' . $usage->id . '/approve', [], $this->headers); - $response->assertStatus(200); + + $response->assertStatus(200) + ->assertJsonStructure([ + "data" => [ + "id", + "warehouse_id", + "employee_id", + "form" => [ + "id", + "branch_id", + "approval_status", + "date", + "done", + "notes", + "number", + "request_approval_to", + "updated_by", + ], + "items" => [ + [ + "expiry_date", + "id", + "chart_of_account_id", + "item_id", + "allocation_id", + "notes", + "production_number", + "quantity", + "unit", + ] + ] + ], + ]); // check balance and match amount $this->assertDatabaseHas('journals', [ @@ -292,6 +324,7 @@ public function success_reject_inventory_usage() $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); $inventoryUsageItem = $inventoryUsage->items()->first(); + $usageItemAmount = $inventoryUsageItem->item->cogs($inventoryUsageItem->item_id) * $inventoryUsageItem->quantity; $approver = $inventoryUsage->form->requestApprovalTo; $this->changeActingAs($approver, $inventoryUsage); @@ -300,13 +333,39 @@ public function success_reject_inventory_usage() $response = $this->json('POST', self::$path . '/' . $inventoryUsage->id . '/reject', $data, $this->headers); - $response->assertStatus(200); + $response->assertStatus(200) + ->assertJsonStructure([ + "data" => [ + "id", + "warehouse_id", + "employee_id", + "form" => [ + "id", + "branch_id", + "approval_status", + "date", + "done", + "notes", + "number", + "request_approval_to", + "updated_by", + ], + ], + ]); $this->assertDatabaseMissing('journals', [ 'form_id' => $inventoryUsage->form->id, 'journalable_type' => Item::$morphName, 'journalable_id' => $inventoryUsageItem->item_id, 'chart_of_account_id' => $inventoryUsageItem->chart_of_account_id, + 'debit' => $usageItemAmount, + ], 'tenant'); + $this->assertDatabaseMissing('journals', [ + 'form_id' => $inventoryUsage->form->id, + 'journalable_type' => Item::$morphName, + 'journalable_id' => $inventoryUsageItem->item_id, + 'chart_of_account_id' => get_setting_journal('inventory usage', 'difference stock expense'), + 'credit' => $usageItemAmount, ], 'tenant'); $this->assertDatabaseHas('forms', [ diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index 9f4f10fb0..6ef9bec1a 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -85,12 +85,17 @@ public function overquantity_create_inventory_usage() ]); } /** @test */ - public function invalid_create_inventory_usage() + public function invalid_required_create_inventory_usage() { $this->setRole(); $data = $this->getDummyData(); - $data = data_set($data, 'items.0.chart_of_account_id', null); + $data = data_set($data, 'employee_id', null, true); + $data = data_set($data, 'request_approval_to', null, true); + $data = data_set($data, 'items.0.item_id', null, true); + $data = data_set($data, 'items.0.unit', null, true); + $data = data_set($data, 'items.0.chart_of_account_id', null, true); + $data = data_set($data, 'items.0.allocation_id', null, true); $response = $this->json('POST', self::$path, $data, $this->headers); @@ -98,6 +103,26 @@ public function invalid_create_inventory_usage() ->assertJson([ "code" => 422, "message" => "The given data was invalid.", + "errors" => [ + "employee_id" => [ + "The employee id field is required." + ], + "request_approval_to" => [ + "The request approval to field is required." + ], + "items.0.item_id" => [ + "The items.0.item_id field is required." + ], + "items.0.unit" => [ + "The items.0.unit field is required." + ], + "items.0.chart_of_account_id" => [ + "The items.0.chart_of_account_id field is required." + ], + "items.0.allocation_id" => [ + "The items.0.allocation_id field is required." + ] + ] ]); } /** @test */ @@ -443,7 +468,7 @@ public function overquantity_update_inventory_usage() ]); } /** @test */ - public function _invalid_unit_update_inventory_usage() + public function invalid_unit_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -460,7 +485,7 @@ public function _invalid_unit_update_inventory_usage() ]); } /** @test */ - public function _invalid_productionnumber_update_inventory_usage() + public function invalid_productionnumber_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -483,7 +508,7 @@ public function _invalid_productionnumber_update_inventory_usage() ]); } /** @test */ - public function _invalid_expirydate_update_inventory_usage() + public function invalid_expirydate_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -506,7 +531,7 @@ public function _invalid_expirydate_update_inventory_usage() ]); } /** @test */ - public function _invalid_notes_update_inventory_usage() + public function invalid_notes_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -528,7 +553,7 @@ public function _invalid_notes_update_inventory_usage() ]); } /** @test */ - public function _invalid_warehouse_update_inventory_usage() + public function invalid_warehouse_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -547,7 +572,7 @@ public function _invalid_warehouse_update_inventory_usage() ]); } /** @test */ - public function _invalid_item_update_inventory_usage() + public function invalid_item_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -568,7 +593,7 @@ public function _invalid_item_update_inventory_usage() ]); } /** @test */ - public function _invalid_account_update_inventory_usage() + public function invalid_account_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -593,19 +618,57 @@ public function success_update_inventory_usage() { $this->success_create_inventory_usage(); - $inventoryUsage = InventoryUsage::orderBy('id', 'asc')->first(); + $usage = InventoryUsage::orderBy('id', 'asc')->first(); + $usageItem = $usage->items()->first(); + $usageItemAmount = $usageItem->item->cogs($usageItem->item_id) * $usageItem->quantity; - $data = $this->getDummyData($inventoryUsage); - $data = data_set($data, 'id', $inventoryUsage->id, false); + $data = $this->getDummyData($usage); + $data = data_set($data, 'id', $usage->id, false); Mail::fake(); - $response = $this->json('PATCH', self::$path . '/' . $inventoryUsage->id, $data, $this->headers); + $response = $this->json('PATCH', self::$path . '/' . $usage->id, $data, $this->headers); + + $response->assertStatus(201) + ->assertJsonStructure([ + "data" => [ + "id", + "warehouse_id", + "employee_id", + "form" => [ + "id", + "branch_id", + "approval_status", + "date", + "done", + "notes", + "number", + "request_approval_to", + "updated_by", + ], + "items" => [ + [ + "expiry_date", + "id", + "chart_of_account_id", + "item_id", + "allocation_id", + "notes", + "production_number", + "quantity", + "unit", + ] + ] + ], + ]); - $response->assertStatus(201); + $formNumberFormat = $usage->defaultNumberPrefix.date('ym')."000"; + $formNumber = $response->json('data.form.number'); + $this->assertStringContainsString($formNumberFormat, $formNumber, "not expected form number format") ; - $this->assertDatabaseHas('forms', [ + $this->assertDatabaseHas('forms', [ 'number' => $response->json('data.form.number'), + 'request_approval_to' => $response->json('data.form.request_approval_to'), 'approval_status' => 0, ], 'tenant'); $this->assertDatabaseHas('forms', [ 'edited_number' => $response->json('data.form.number') ], 'tenant'); @@ -616,11 +679,32 @@ public function success_update_inventory_usage() 'activity' => 'Update - 1' ], 'tenant'); + $this->assertDatabaseHas('inventory_usages', [ + 'id' => $response->json('data.id'), + 'warehouse_id' => $response->json('data.warehouse_id'), + 'employee_id' => $response->json('data.employee_id'), + ], 'tenant'); + $this->assertDatabaseHas('inventory_usage_items', [ + 'inventory_usage_id' => $response->json('data.id'), + 'item_id' => $response->json('data.items.0.item_id'), + 'chart_of_account_id' => $response->json('data.items.0.chart_of_account_id'), + 'allocation_id' => $response->json('data.items.0.allocation_id'), + 'quantity' => $response->json('data.items.0.quantity'), + ], 'tenant'); + $this->assertDatabaseMissing('journals', [ 'form_id' => $response->json('data.form.id'), 'journalable_type' => Item::$morphName, 'journalable_id' => $response->json('data.items.0.item_id'), 'chart_of_account_id' => $response->json('data.items.0.chart_of_account_id'), + 'debit' => $usageItemAmount, + ], 'tenant'); + $this->assertDatabaseMissing('journals', [ + 'form_id' => $response->json('data.form.id'), + 'journalable_type' => Item::$morphName, + 'journalable_id' => $response->json('data.items.0.item_id'), + 'chart_of_account_id' => get_setting_journal('inventory usage', 'difference stock expense'), + 'credit' => $usageItemAmount, ], 'tenant'); Mail::assertQueued(InventoryUsageApprovalMail::class); From 55903148542b104a27b966dcd0e4e5dd4a0e052e Mon Sep 17 00:00:00 2001 From: addincw Date: Sat, 7 Jan 2023 10:20:39 +0700 Subject: [PATCH 16/16] fix([inventory-usage] edit): tdd feedbacks --- .../Http/Inventory/InventoryUsage/InventoryUsageTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php index 6ef9bec1a..44d95ccd3 100644 --- a/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php +++ b/tests/Feature/Http/Inventory/InventoryUsage/InventoryUsageTest.php @@ -430,7 +430,7 @@ public function invalid_date_update_inventory_usage() ]); } /** @test */ - public function invalid_update_inventory_usage() + public function invalid_approver_update_inventory_usage() { $this->success_create_inventory_usage(); @@ -446,6 +446,9 @@ public function invalid_update_inventory_usage() ->assertJson([ "code" => 422, "message" => "The given data was invalid.", + "errors" => [ + "request_approval_to" => ["The request approval to field is required."], + ] ]); } /** @test */