tenantId(); return ItemBomItem::where('tenant_id', $tenantId) ->orderBy('created_at', 'desc') ->get(); } /** * 독립 BOM 생성 (섹션 연결 없음) * * POST /api/v1/item-master/bom-items */ public function storeIndependent(array $data): ItemBomItem { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $bomItem = ItemBomItem::create([ 'tenant_id' => $tenantId, 'group_id' => $data['group_id'] ?? 1, 'item_code' => $data['item_code'] ?? null, 'item_name' => $data['item_name'], 'quantity' => $data['quantity'] ?? 1, 'unit' => $data['unit'] ?? null, 'unit_price' => $data['unit_price'] ?? null, 'total_price' => $data['total_price'] ?? null, 'spec' => $data['spec'] ?? null, 'note' => $data['note'] ?? null, 'created_by' => $userId, ]); return $bomItem; } /** * BOM 항목 생성 및 섹션에 연결 */ public function store(int $sectionId, array $data): ItemBomItem { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); // 섹션 존재 확인 $section = ItemSection::where('tenant_id', $tenantId) ->where('id', $sectionId) ->first(); if (! $section) { throw new NotFoundHttpException(__('error.not_found')); } // BOM 항목 생성 $bomItem = ItemBomItem::create([ 'tenant_id' => $tenantId, 'group_id' => $data['group_id'] ?? 1, 'item_code' => $data['item_code'] ?? null, 'item_name' => $data['item_name'], 'quantity' => $data['quantity'] ?? 1, 'unit' => $data['unit'] ?? null, 'unit_price' => $data['unit_price'] ?? null, 'total_price' => $data['total_price'] ?? null, 'spec' => $data['spec'] ?? null, 'note' => $data['note'] ?? null, 'created_by' => $userId, ]); // 섹션-BOM 관계 생성 EntityRelationship::link( $tenantId, EntityRelationship::TYPE_SECTION, $sectionId, EntityRelationship::TYPE_BOM, $bomItem->id, 0, null, $data['group_id'] ?? 1 ); return $bomItem; } /** * BOM 항목 수정 */ public function update(int $id, array $data): ItemBomItem { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $bomItem = ItemBomItem::where('tenant_id', $tenantId) ->where('id', $id) ->first(); if (! $bomItem) { throw new NotFoundHttpException(__('error.not_found')); } $bomItem->update([ 'item_code' => $data['item_code'] ?? $bomItem->item_code, 'item_name' => $data['item_name'] ?? $bomItem->item_name, 'quantity' => $data['quantity'] ?? $bomItem->quantity, 'unit' => $data['unit'] ?? $bomItem->unit, 'unit_price' => $data['unit_price'] ?? $bomItem->unit_price, 'total_price' => $data['total_price'] ?? $bomItem->total_price, 'spec' => $data['spec'] ?? $bomItem->spec, 'note' => $data['note'] ?? $bomItem->note, 'updated_by' => $userId, ]); return $bomItem->fresh(); } /** * BOM 항목 삭제 (Soft Delete) * * 독립 엔티티 아키텍처: BOM 삭제 시 모든 부모 관계도 해제 */ public function destroy(int $id): void { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); $bomItem = ItemBomItem::where('tenant_id', $tenantId) ->where('id', $id) ->first(); if (! $bomItem) { throw new NotFoundHttpException(__('error.not_found')); } // 잠금 체크: 이 BOM이 잠금된 연결로 보호되고 있는지 확인 $this->checkCanDelete(EntityRelationship::TYPE_BOM, $id); // 1. entity_relationships에서 이 BOM의 모든 부모 관계 해제 // (section→bom 관계에서 이 BOM 제거) // 주의: 잠금된 연결이 있으면 위에서 예외 발생 EntityRelationship::where('child_type', EntityRelationship::TYPE_BOM) ->where('child_id', $id) ->where('is_locked', false) ->delete(); // 2. BOM Soft Delete $bomItem->update(['deleted_by' => $userId]); $bomItem->delete(); } }