fix: 품목 삭제 시 BOM 참조 무결성 체크 추가

- 삭제 전 product_components 테이블에서 사용 여부 확인
- BOM 구성품으로 사용 중인 품목 삭제 차단 (400 에러)
- 일괄 삭제에도 동일한 참조 체크 적용
- 품목 관련 에러 메시지 추가 (error.item.*)
- 품목 삭제 API 테스트 플로우 JSON 추가
This commit is contained in:
2025-12-03 22:35:38 +09:00
parent 695afb8a86
commit fbaf2720d8
3 changed files with 337 additions and 2 deletions

View File

@@ -446,6 +446,9 @@ public function updateItem(int $id, array $data): Product
/**
* 품목 삭제 (Product 전용, Soft Delete)
*
* - 이미 삭제된 품목은 404 반환
* - 다른 BOM의 구성품으로 사용 중이면 삭제 불가
*
* @param int $id 품목 ID
*/
public function deleteItem(int $id): void
@@ -457,15 +460,39 @@ public function deleteItem(int $id): void
->find($id);
if (! $product) {
throw new NotFoundHttpException(__('error.not_found'));
throw new NotFoundHttpException(__('error.item.not_found'));
}
// BOM 구성품으로 사용 중인지 체크
$usageCount = $this->checkProductUsageInBom($tenantId, $id);
if ($usageCount > 0) {
throw new BadRequestHttpException(__('error.item.in_use_as_bom_component', ['count' => $usageCount]));
}
$product->delete();
}
/**
* Product가 다른 BOM의 구성품으로 사용 중인지 체크
*
* @param int $tenantId 테넌트 ID
* @param int $productId 제품 ID
* @return int 사용 건수
*/
private function checkProductUsageInBom(int $tenantId, int $productId): int
{
return \App\Models\Products\ProductComponent::query()
->where('tenant_id', $tenantId)
->where('ref_type', 'PRODUCT')
->where('ref_id', $productId)
->count();
}
/**
* 품목 일괄 삭제 (Product 전용, Soft Delete)
*
* - 다른 BOM의 구성품으로 사용 중인 품목은 삭제 불가
*
* @param array $ids 품목 ID 배열
*/
public function batchDeleteItems(array $ids): void
@@ -478,7 +505,20 @@ public function batchDeleteItems(array $ids): void
->get();
if ($products->isEmpty()) {
throw new NotFoundHttpException(__('error.not_found'));
throw new NotFoundHttpException(__('error.item.not_found'));
}
// BOM 구성품으로 사용 중인 품목 체크
$inUseIds = [];
foreach ($products as $product) {
$usageCount = $this->checkProductUsageInBom($tenantId, $product->id);
if ($usageCount > 0) {
$inUseIds[] = $product->id;
}
}
if (! empty($inUseIds)) {
throw new BadRequestHttpException(__('error.item.in_use_as_bom_component', ['count' => count($inUseIds)]));
}
foreach ($products as $product) {