tenantId(); $userId = $this->apiUserId(); // 페이지 존재 확인 $page = ItemPage::where('tenant_id', $tenantId)->find($pageId); if (! $page) { throw new NotFoundHttpException(__('error.page_not_found')); } // 섹션 존재 확인 $section = ItemSection::where('tenant_id', $tenantId)->find($sectionId); if (! $section) { throw new NotFoundHttpException(__('error.section_not_found')); } return EntityRelationship::link( $tenantId, EntityRelationship::TYPE_PAGE, $pageId, EntityRelationship::TYPE_SECTION, $sectionId, $orderNo ); } /** * 페이지에서 섹션 연결 해제 */ public function unlinkSectionFromPage(int $pageId, int $sectionId): bool { $tenantId = $this->tenantId(); return EntityRelationship::unlink( $tenantId, EntityRelationship::TYPE_PAGE, $pageId, EntityRelationship::TYPE_SECTION, $sectionId ); } /** * 페이지에 필드 직접 연결 */ public function linkFieldToPage(int $pageId, int $fieldId, int $orderNo = 0): EntityRelationship { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); // 페이지 존재 확인 $page = ItemPage::where('tenant_id', $tenantId)->find($pageId); if (! $page) { throw new NotFoundHttpException(__('error.page_not_found')); } // 필드 존재 확인 $field = ItemField::where('tenant_id', $tenantId)->find($fieldId); if (! $field) { throw new NotFoundHttpException(__('error.field_not_found')); } return EntityRelationship::link( $tenantId, EntityRelationship::TYPE_PAGE, $pageId, EntityRelationship::TYPE_FIELD, $fieldId, $orderNo ); } /** * 페이지에서 필드 연결 해제 */ public function unlinkFieldFromPage(int $pageId, int $fieldId): bool { $tenantId = $this->tenantId(); return EntityRelationship::unlink( $tenantId, EntityRelationship::TYPE_PAGE, $pageId, EntityRelationship::TYPE_FIELD, $fieldId ); } /** * 섹션에 필드 연결 */ public function linkFieldToSection(int $sectionId, int $fieldId, int $orderNo = 0): EntityRelationship { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); // 섹션 존재 확인 $section = ItemSection::where('tenant_id', $tenantId)->find($sectionId); if (! $section) { throw new NotFoundHttpException(__('error.section_not_found')); } // 필드 존재 확인 $field = ItemField::where('tenant_id', $tenantId)->find($fieldId); if (! $field) { throw new NotFoundHttpException(__('error.field_not_found')); } return EntityRelationship::link( $tenantId, EntityRelationship::TYPE_SECTION, $sectionId, EntityRelationship::TYPE_FIELD, $fieldId, $orderNo ); } /** * 섹션에서 필드 연결 해제 */ public function unlinkFieldFromSection(int $sectionId, int $fieldId): bool { $tenantId = $this->tenantId(); return EntityRelationship::unlink( $tenantId, EntityRelationship::TYPE_SECTION, $sectionId, EntityRelationship::TYPE_FIELD, $fieldId ); } /** * 섹션에 BOM 항목 연결 */ public function linkBomToSection(int $sectionId, int $bomId, int $orderNo = 0): EntityRelationship { $tenantId = $this->tenantId(); $userId = $this->apiUserId(); // 섹션 존재 확인 $section = ItemSection::where('tenant_id', $tenantId)->find($sectionId); if (! $section) { throw new NotFoundHttpException(__('error.section_not_found')); } // BOM 항목 존재 확인 $bom = ItemBomItem::where('tenant_id', $tenantId)->find($bomId); if (! $bom) { throw new NotFoundHttpException(__('error.bom_not_found')); } return EntityRelationship::link( $tenantId, EntityRelationship::TYPE_SECTION, $sectionId, EntityRelationship::TYPE_BOM, $bomId, $orderNo ); } /** * 섹션에서 BOM 항목 연결 해제 */ public function unlinkBomFromSection(int $sectionId, int $bomId): bool { $tenantId = $this->tenantId(); return EntityRelationship::unlink( $tenantId, EntityRelationship::TYPE_SECTION, $sectionId, EntityRelationship::TYPE_BOM, $bomId ); } /** * 페이지의 모든 관계 조회 */ public function getPageRelationships(int $pageId): Collection { $tenantId = $this->tenantId(); $page = ItemPage::where('tenant_id', $tenantId)->find($pageId); if (! $page) { throw new NotFoundHttpException(__('error.page_not_found')); } return EntityRelationship::where('tenant_id', $tenantId) ->where('parent_type', EntityRelationship::TYPE_PAGE) ->where('parent_id', $pageId) ->orderBy('order_no') ->get(); } /** * 섹션의 모든 자식 관계 조회 */ public function getSectionChildRelationships(int $sectionId): Collection { $tenantId = $this->tenantId(); $section = ItemSection::where('tenant_id', $tenantId)->find($sectionId); if (! $section) { throw new NotFoundHttpException(__('error.section_not_found')); } return EntityRelationship::where('tenant_id', $tenantId) ->where('parent_type', EntityRelationship::TYPE_SECTION) ->where('parent_id', $sectionId) ->orderBy('order_no') ->get(); } /** * 특정 엔티티가 연결된 부모 목록 조회 */ public function getParentRelationships(string $childType, int $childId): Collection { $tenantId = $this->tenantId(); return EntityRelationship::where('tenant_id', $tenantId) ->where('child_type', $childType) ->where('child_id', $childId) ->get(); } /** * 관계 순서 변경 */ public function reorderRelationships(string $parentType, int $parentId, array $orderedChildIds): void { $tenantId = $this->tenantId(); foreach ($orderedChildIds as $index => $item) { EntityRelationship::where([ 'tenant_id' => $tenantId, 'parent_type' => $parentType, 'parent_id' => $parentId, 'child_type' => $item['child_type'], 'child_id' => $item['child_id'], ])->update(['order_no' => $index]); } } /** * 부모의 모든 자식 관계 일괄 삭제 */ public function unlinkAllChildren(string $parentType, int $parentId, ?string $childType = null): int { $tenantId = $this->tenantId(); return EntityRelationship::unlinkAllChildren( $tenantId, $parentType, $parentId, $childType ); } /** * 페이지 구조 조회 (섹션 + 직접 연결된 필드 포함) */ public function getPageStructure(int $pageId): array { $tenantId = $this->tenantId(); $page = ItemPage::where('tenant_id', $tenantId)->find($pageId); if (! $page) { throw new NotFoundHttpException(__('error.page_not_found')); } // 페이지의 모든 관계 조회 $relationships = EntityRelationship::where('tenant_id', $tenantId) ->where('parent_type', EntityRelationship::TYPE_PAGE) ->where('parent_id', $pageId) ->orderBy('order_no') ->get(); $structure = [ 'page' => $page, 'sections' => [], 'direct_fields' => [], ]; foreach ($relationships as $rel) { if ($rel->child_type === EntityRelationship::TYPE_SECTION) { $section = ItemSection::find($rel->child_id); if ($section) { // 섹션의 자식(필드/BOM) 조회 $sectionChildren = $this->getSectionChildren($section->id); $structure['sections'][] = [ 'section' => $section, 'order_no' => $rel->order_no, 'fields' => $sectionChildren['fields'], 'bom_items' => $sectionChildren['bom_items'], ]; } } elseif ($rel->child_type === EntityRelationship::TYPE_FIELD) { $field = ItemField::find($rel->child_id); if ($field) { $structure['direct_fields'][] = [ 'field' => $field, 'order_no' => $rel->order_no, ]; } } } return $structure; } /** * 섹션의 자식 엔티티 조회 */ private function getSectionChildren(int $sectionId): array { $tenantId = $this->tenantId(); $relationships = EntityRelationship::where('tenant_id', $tenantId) ->where('parent_type', EntityRelationship::TYPE_SECTION) ->where('parent_id', $sectionId) ->orderBy('order_no') ->get(); $result = [ 'fields' => [], 'bom_items' => [], ]; foreach ($relationships as $rel) { if ($rel->child_type === EntityRelationship::TYPE_FIELD) { $field = ItemField::find($rel->child_id); if ($field) { $result['fields'][] = [ 'field' => $field, 'order_no' => $rel->order_no, ]; } } elseif ($rel->child_type === EntityRelationship::TYPE_BOM) { $bom = ItemBomItem::find($rel->child_id); if ($bom) { $result['bom_items'][] = [ 'bom_item' => $bom, 'order_no' => $rel->order_no, ]; } } } return $result; } }