feat: implement comprehensive material and product stock management logic in CuttingService

This commit is contained in:
Yoga Pangestu 2026-06-13 14:03:12 +07:00
parent 1e2d81a86d
commit 837c930c4f

View File

@ -93,7 +93,6 @@ public function getInProgressCuttings(User $user): Collection
}); });
} }
/** /**
* @return Collection<int, RawMaterial> * @return Collection<int, RawMaterial>
*/ */
@ -226,6 +225,9 @@ public function create(array $validated, User $user): Cutting
$cutting->results()->create($resultData); $cutting->results()->create($resultData);
} }
$cutting->load('materials.rawMaterialPrice.rawMaterial');
$this->deductMaterialStock($cutting);
return $cutting; return $cutting;
}); });
} }
@ -242,6 +244,12 @@ public function update(Cutting $cutting, array $validated): void
} }
DB::transaction(function () use ($cutting, $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->materials()->delete();
$cutting->results()->delete(); $cutting->results()->delete();
@ -259,6 +267,11 @@ public function update(Cutting $cutting, array $validated): void
$cutting->results()->create($resultData); $cutting->results()->create($resultData);
} }
if ($cutting->status === CuttingStatus::IN_PROGRESS) {
$cutting->load('materials.rawMaterialPrice.rawMaterial');
$this->deductMaterialStock($cutting);
}
if ($cutting->status === CuttingStatus::REJECTED) { if ($cutting->status === CuttingStatus::REJECTED) {
$cutting->rejection()?->delete(); $cutting->rejection()?->delete();
} }
@ -274,6 +287,9 @@ public function delete(Cutting $cutting): void
} }
DB::transaction(function () use ($cutting): void { DB::transaction(function () use ($cutting): void {
$cutting->load(['materials.rawMaterialPrice.rawMaterial']);
$this->reverseTotalMaterialStock($cutting);
$cutting->materials()->delete(); $cutting->materials()->delete();
$cutting->results()->delete(); $cutting->results()->delete();
$cutting->delete(); $cutting->delete();
@ -292,19 +308,18 @@ public function transitionStatus(Cutting $cutting, CuttingStatus $status, User $
$cutting->load(['materials', 'results']); $cutting->load(['materials', 'results']);
if ($status === CuttingStatus::COMPLETED) { if ($status === CuttingStatus::COMPLETED) {
$this->applyMaterialStockOnComplete($cutting); $this->applyRemainingMaterialStock($cutting);
}
if ($status === CuttingStatus::VERIFIED) {
$this->applyProductStockOnVerify($cutting); $this->applyProductStockOnVerify($cutting);
} }
if ($status === CuttingStatus::REJECTED) { if ($status === CuttingStatus::REJECTED) {
$this->reverseMaterialStock($cutting); $this->reverseMaterialStock($cutting);
$this->reverseProductStock($cutting);
$this->storeRejection($cutting, $reason, $user); $this->storeRejection($cutting, $reason, $user);
} }
if ($status === CuttingStatus::IN_PROGRESS && $cutting->status === CuttingStatus::REJECTED) { if ($status === CuttingStatus::IN_PROGRESS && $cutting->status === CuttingStatus::REJECTED) {
$this->deductMaterialStock($cutting);
$cutting->rejection()?->delete(); $cutting->rejection()?->delete();
} }
@ -407,7 +422,7 @@ private function buildResults(array $results): array
->all(); ->all();
} }
private function applyMaterialStockOnComplete(Cutting $cutting): void private function deductMaterialStock(Cutting $cutting): void
{ {
foreach ($cutting->materials as $material) { foreach ($cutting->materials as $material) {
$totalTaken = (float) $material->material_usage + (float) $material->remaining_material; $totalTaken = (float) $material->material_usage + (float) $material->remaining_material;
@ -426,9 +441,26 @@ private function applyMaterialStockOnComplete(Cutting $cutting): void
} }
$price->decrement('stock', $totalTaken); $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) { 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 private function storeRejection(Cutting $cutting, ?string $reason, User $user): void
{ {
if ($reason === null || trim($reason) === '') { if ($reason === null || trim($reason) === '') {