From 0070d0c49e53bd2b0b218ca78d8ef92817fe3c6e Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Sun, 19 Jul 2026 20:05:08 +0700 Subject: [PATCH] feat: add updateCombinationResult method to CuttingDraftItemController and corresponding route --- .../Cutting/CuttingDraftItemController.php | 9 ++++++ app/Services/Manage/CuttingService.php | 17 +++++++++++ .../manage/cuttings/form/CuttingPosForm.vue | 8 +++++ .../manage/cuttings/form/useCuttingPosCart.ts | 30 +++++++++++++++++++ routes/web.php | 4 +++ 5 files changed, 68 insertions(+) diff --git a/app/Http/Controllers/Admin/Manage/Cutting/CuttingDraftItemController.php b/app/Http/Controllers/Admin/Manage/Cutting/CuttingDraftItemController.php index cce2dd0..afdcc0f 100644 --- a/app/Http/Controllers/Admin/Manage/Cutting/CuttingDraftItemController.php +++ b/app/Http/Controllers/Admin/Manage/Cutting/CuttingDraftItemController.php @@ -61,6 +61,15 @@ public function destroyCombination(Request $request, int $combinationId): JsonRe return response()->json(['ok' => true]); } + public function updateCombinationResult(Request $request, int $combinationId): JsonResponse + { + $result = $request->input('material_result'); + + $this->cuttingService->updateDraftCombinationResult($request->user(), $combinationId, $result); + + return response()->json(['ok' => true]); + } + public function quickCreateProduct(CuttingQuickCreateProductRequest $request): JsonResponse { $product = $this->cuttingService->quickCreateProduct($request->validated()); diff --git a/app/Services/Manage/CuttingService.php b/app/Services/Manage/CuttingService.php index b3a6856..d8522d5 100644 --- a/app/Services/Manage/CuttingService.php +++ b/app/Services/Manage/CuttingService.php @@ -411,6 +411,23 @@ public function removeDraftCombination(User $user, int $combinationId): void $combination->forceDelete(); } + public function updateDraftCombinationResult(User $user, int $combinationId, mixed $result): void + { + $combination = CuttingMaterialCombination::query() + ->whereNull('cutting_id') + ->where('user_id', $user->id) + ->where('id', $combinationId) + ->first(); + + if ($combination === null) { + return; + } + + $materialResult = $result !== null ? (int) $result : null; + + $combination->update(['material_result' => $materialResult]); + } + public function create(array $validated, User $user): Cutting { $cutting = $this->runInTransaction( diff --git a/resources/js/pages/admin/manage/cuttings/form/CuttingPosForm.vue b/resources/js/pages/admin/manage/cuttings/form/CuttingPosForm.vue index 85174b3..1f0333a 100644 --- a/resources/js/pages/admin/manage/cuttings/form/CuttingPosForm.vue +++ b/resources/js/pages/admin/manage/cuttings/form/CuttingPosForm.vue @@ -65,6 +65,7 @@ const { resultCart, filteredRawMaterials, totalMaterialCost, + totalMaterialResult, totalResultPieces, materialLineCost, setCarts, @@ -150,6 +151,13 @@ if (isCreateMode.value && resultCart.value.length === 0) { }); } +watch(totalMaterialResult, (newVal) => { + const val = newVal > 0 ? String(newVal) : null; + resultCart.value.forEach((item) => { + item.cutting_result = val; + }); +}, { immediate: true }); + function buildFormData(): FormData { const formData = new FormData(); diff --git a/resources/js/pages/admin/manage/cuttings/form/useCuttingPosCart.ts b/resources/js/pages/admin/manage/cuttings/form/useCuttingPosCart.ts index 8bda7ac..003b535 100644 --- a/resources/js/pages/admin/manage/cuttings/form/useCuttingPosCart.ts +++ b/resources/js/pages/admin/manage/cuttings/form/useCuttingPosCart.ts @@ -84,6 +84,24 @@ export function useCuttingPosCart(options: { materialCart.value.reduce((sum, item) => sum + materialLineCost(item), 0), ); + const totalMaterialResult = computed(() => { + const seenCombinations = new Set(); + let total = 0; + + materialCart.value.forEach((item) => { + if (item.combination_id) { + if (!seenCombinations.has(item.combination_id)) { + seenCombinations.add(item.combination_id); + total += Number(item.combination_material_result) || 0; + } + } else { + total += Number(item.material_result) || 0; + } + }); + + return total; + }); + const totalResultPieces = computed(() => resultCart.value.reduce( (sum, item) => sum + (Number(item.cutting_result) || 0), @@ -195,6 +213,17 @@ export function useCuttingPosCart(options: { item.combination_material_result = result; } }); + + if (toValue(options.isCreateMode)) { + try { + await apiFetch(draft_combinations.update_result.url(combinationId), { + method: 'PUT', + body: JSON.stringify({ material_result: result }), + }); + } catch (error) { + toast.error(error instanceof Error ? error.message : 'Gagal menyimpan hasil kombinasi.'); + } + } } function getMaterialCartItem(priceId: number): CuttingMaterialCartItem | undefined { @@ -310,6 +339,7 @@ export function useCuttingPosCart(options: { resultCart, filteredRawMaterials, totalMaterialCost, + totalMaterialResult, totalResultPieces, estimatedCostPerUnit, materialLineCost, diff --git a/routes/web.php b/routes/web.php index 3a88067..e532744 100644 --- a/routes/web.php +++ b/routes/web.php @@ -404,6 +404,10 @@ ->middleware('permission:'.Permission::CUTTINGS_CREATE->value) ->name('draft_combinations.destroy'); + Route::put('draft-combinations/{combinationId}/result', [CuttingDraftItemController::class, 'updateCombinationResult']) + ->middleware('permission:'.Permission::CUTTINGS_CREATE->value) + ->name('draft_combinations.update_result'); + Route::post('quick-create-product', [CuttingDraftItemController::class, 'quickCreateProduct']) ->middleware('permission:'.Permission::CUTTINGS_CREATE->value) ->name('quick_create_product');