From 837c930c4ff9f1a735cdb305c765cd8faf53fb0b Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Sat, 13 Jun 2026 14:03:12 +0700 Subject: [PATCH] feat: implement comprehensive material and product stock management logic in CuttingService --- app/Services/Manage/CuttingService.php | 59 +++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/app/Services/Manage/CuttingService.php b/app/Services/Manage/CuttingService.php index 2c39ad3..82c7f19 100644 --- a/app/Services/Manage/CuttingService.php +++ b/app/Services/Manage/CuttingService.php @@ -93,7 +93,6 @@ public function getInProgressCuttings(User $user): Collection }); } - /** * @return Collection */ @@ -226,6 +225,9 @@ public function create(array $validated, User $user): Cutting $cutting->results()->create($resultData); } + $cutting->load('materials.rawMaterialPrice.rawMaterial'); + $this->deductMaterialStock($cutting); + return $cutting; }); } @@ -242,6 +244,12 @@ public function update(Cutting $cutting, array $validated): void } DB::transaction(function () use ($cutting, $validated): void { + $cutting->load(['materials.rawMaterialPrice.rawMaterial', 'results']); + + if ($cutting->status === CuttingStatus::IN_PROGRESS) { + $this->reverseTotalMaterialStock($cutting); + } + $cutting->materials()->delete(); $cutting->results()->delete(); @@ -259,6 +267,11 @@ public function update(Cutting $cutting, array $validated): void $cutting->results()->create($resultData); } + if ($cutting->status === CuttingStatus::IN_PROGRESS) { + $cutting->load('materials.rawMaterialPrice.rawMaterial'); + $this->deductMaterialStock($cutting); + } + if ($cutting->status === CuttingStatus::REJECTED) { $cutting->rejection()?->delete(); } @@ -274,6 +287,9 @@ public function delete(Cutting $cutting): void } DB::transaction(function () use ($cutting): void { + $cutting->load(['materials.rawMaterialPrice.rawMaterial']); + $this->reverseTotalMaterialStock($cutting); + $cutting->materials()->delete(); $cutting->results()->delete(); $cutting->delete(); @@ -292,19 +308,18 @@ public function transitionStatus(Cutting $cutting, CuttingStatus $status, User $ $cutting->load(['materials', 'results']); if ($status === CuttingStatus::COMPLETED) { - $this->applyMaterialStockOnComplete($cutting); - } - - if ($status === CuttingStatus::VERIFIED) { + $this->applyRemainingMaterialStock($cutting); $this->applyProductStockOnVerify($cutting); } if ($status === CuttingStatus::REJECTED) { $this->reverseMaterialStock($cutting); + $this->reverseProductStock($cutting); $this->storeRejection($cutting, $reason, $user); } if ($status === CuttingStatus::IN_PROGRESS && $cutting->status === CuttingStatus::REJECTED) { + $this->deductMaterialStock($cutting); $cutting->rejection()?->delete(); } @@ -407,7 +422,7 @@ private function buildResults(array $results): array ->all(); } - private function applyMaterialStockOnComplete(Cutting $cutting): void + private function deductMaterialStock(Cutting $cutting): void { foreach ($cutting->materials as $material) { $totalTaken = (float) $material->material_usage + (float) $material->remaining_material; @@ -426,9 +441,26 @@ private function applyMaterialStockOnComplete(Cutting $cutting): void } $price->decrement('stock', $totalTaken); + } + } + private function reverseTotalMaterialStock(Cutting $cutting): void + { + foreach ($cutting->materials as $material) { + $totalTaken = (float) $material->material_usage + (float) $material->remaining_material; + RawMaterialPrice::query() + ->whereKey($material->raw_material_price_id) + ->increment('stock', $totalTaken); + } + } + + private function applyRemainingMaterialStock(Cutting $cutting): void + { + foreach ($cutting->materials as $material) { if ((float) $material->remaining_material > 0) { - $price->increment('stock', $material->remaining_material); + RawMaterialPrice::query() + ->whereKey($material->raw_material_price_id) + ->increment('stock', $material->remaining_material); } } } @@ -455,6 +487,19 @@ private function applyProductStockOnVerify(Cutting $cutting): void } } + private function reverseProductStock(Cutting $cutting): void + { + foreach ($cutting->results as $result) { + if ($result->warehouse_stock < 1) { + continue; + } + + ProductVariant::query() + ->whereKey($result->product_variant_id) + ->decrement('stock', $result->warehouse_stock); + } + } + private function storeRejection(Cutting $cutting, ?string $reason, User $user): void { if ($reason === null || trim($reason) === '') {