- CASCADE FK → 독립 엔티티 + entity_relationships 링크 테이블 - 독립 API 10개 추가 (섹션/필드/BOM CRUD, clone, usage) - SectionTemplate 모델 제거 → ItemSection.is_template 통합 - 페이지-섹션, 섹션-필드, 섹션-BOM 링크/언링크 API 14개 추가 - Swagger 문서 업데이트
475 lines
16 KiB
PHP
475 lines
16 KiB
PHP
<?php
|
|
|
|
namespace App\Swagger\v1;
|
|
|
|
/**
|
|
* @OA\Tag(name="ItemMaster-Relationships", description="품목기준관리 - 엔티티 관계 API")
|
|
*
|
|
* ========================================
|
|
* 모델 스키마
|
|
* ========================================
|
|
*
|
|
* @OA\Schema(
|
|
* schema="EntityRelationship",
|
|
* type="object",
|
|
*
|
|
* @OA\Property(property="id", type="integer", example=1),
|
|
* @OA\Property(property="tenant_id", type="integer", example=1),
|
|
* @OA\Property(property="group_id", type="integer", example=1, description="그룹 ID (1: 품목관리)"),
|
|
* @OA\Property(property="parent_type", type="string", enum={"page","section"}, example="page"),
|
|
* @OA\Property(property="parent_id", type="integer", example=1),
|
|
* @OA\Property(property="child_type", type="string", enum={"section","field","bom"}, example="section"),
|
|
* @OA\Property(property="child_id", type="integer", example=1),
|
|
* @OA\Property(property="order_no", type="integer", example=0),
|
|
* @OA\Property(property="metadata", type="object", nullable=true, example=null),
|
|
* @OA\Property(property="created_at", type="string", example="2025-11-26 10:00:00"),
|
|
* @OA\Property(property="updated_at", type="string", example="2025-11-26 10:00:00")
|
|
* )
|
|
*
|
|
* @OA\Schema(
|
|
* schema="LinkEntityRequest",
|
|
* type="object",
|
|
* required={"child_id"},
|
|
*
|
|
* @OA\Property(property="child_id", type="integer", example=1, description="연결할 엔티티 ID"),
|
|
* @OA\Property(property="order_no", type="integer", example=0, description="정렬 순서")
|
|
* )
|
|
*
|
|
* @OA\Schema(
|
|
* schema="ReorderRelationshipsRequest",
|
|
* type="object",
|
|
* required={"parent_type","parent_id","ordered_items"},
|
|
*
|
|
* @OA\Property(property="parent_type", type="string", enum={"page","section"}, example="page"),
|
|
* @OA\Property(property="parent_id", type="integer", example=1),
|
|
* @OA\Property(
|
|
* property="ordered_items",
|
|
* type="array",
|
|
*
|
|
* @OA\Items(
|
|
* type="object",
|
|
*
|
|
* @OA\Property(property="child_type", type="string", example="section"),
|
|
* @OA\Property(property="child_id", type="integer", example=1)
|
|
* )
|
|
* )
|
|
* )
|
|
*
|
|
* @OA\Schema(
|
|
* schema="PageStructure",
|
|
* type="object",
|
|
*
|
|
* @OA\Property(property="page", ref="#/components/schemas/ItemPage"),
|
|
* @OA\Property(
|
|
* property="sections",
|
|
* type="array",
|
|
*
|
|
* @OA\Items(
|
|
* type="object",
|
|
*
|
|
* @OA\Property(property="section", ref="#/components/schemas/ItemSection"),
|
|
* @OA\Property(property="order_no", type="integer", example=0),
|
|
* @OA\Property(property="fields", type="array", @OA\Items(type="object")),
|
|
* @OA\Property(property="bom_items", type="array", @OA\Items(type="object"))
|
|
* )
|
|
* ),
|
|
* @OA\Property(
|
|
* property="direct_fields",
|
|
* type="array",
|
|
*
|
|
* @OA\Items(
|
|
* type="object",
|
|
*
|
|
* @OA\Property(property="field", ref="#/components/schemas/ItemField"),
|
|
* @OA\Property(property="order_no", type="integer", example=0)
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
class EntityRelationshipApi
|
|
{
|
|
// ========================================
|
|
// 페이지-섹션 연결
|
|
// ========================================
|
|
|
|
/**
|
|
* @OA\Post(
|
|
* path="/api/v1/item-master/pages/{pageId}/link-section",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="페이지에 섹션 연결",
|
|
* description="페이지와 섹션을 연결합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="pageId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\RequestBody(
|
|
* required=true,
|
|
*
|
|
* @OA\JsonContent(ref="#/components/schemas/LinkEntityRequest")
|
|
* ),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="연결 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="연결 성공"),
|
|
* @OA\Property(property="data", ref="#/components/schemas/EntityRelationship")
|
|
* )
|
|
* ),
|
|
*
|
|
* @OA\Response(response=404, description="페이지 또는 섹션을 찾을 수 없음")
|
|
* )
|
|
*/
|
|
public function linkSectionToPage() {}
|
|
|
|
/**
|
|
* @OA\Delete(
|
|
* path="/api/v1/item-master/pages/{pageId}/unlink-section/{sectionId}",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="페이지에서 섹션 연결 해제",
|
|
* description="페이지와 섹션의 연결을 해제합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="pageId", in="path", required=true, @OA\Schema(type="integer")),
|
|
* @OA\Parameter(name="sectionId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="연결 해제 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="연결 해제 성공"),
|
|
* @OA\Property(property="data", type="string", example="success")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function unlinkSectionFromPage() {}
|
|
|
|
// ========================================
|
|
// 페이지-필드 직접 연결
|
|
// ========================================
|
|
|
|
/**
|
|
* @OA\Post(
|
|
* path="/api/v1/item-master/pages/{pageId}/link-field",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="페이지에 필드 직접 연결",
|
|
* description="페이지와 필드를 직접 연결합니다 (섹션 없이).",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="pageId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\RequestBody(
|
|
* required=true,
|
|
*
|
|
* @OA\JsonContent(ref="#/components/schemas/LinkEntityRequest")
|
|
* ),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="연결 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="연결 성공"),
|
|
* @OA\Property(property="data", ref="#/components/schemas/EntityRelationship")
|
|
* )
|
|
* ),
|
|
*
|
|
* @OA\Response(response=404, description="페이지 또는 필드를 찾을 수 없음")
|
|
* )
|
|
*/
|
|
public function linkFieldToPage() {}
|
|
|
|
/**
|
|
* @OA\Delete(
|
|
* path="/api/v1/item-master/pages/{pageId}/unlink-field/{fieldId}",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="페이지에서 필드 연결 해제",
|
|
* description="페이지와 필드의 연결을 해제합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="pageId", in="path", required=true, @OA\Schema(type="integer")),
|
|
* @OA\Parameter(name="fieldId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="연결 해제 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="연결 해제 성공"),
|
|
* @OA\Property(property="data", type="string", example="success")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function unlinkFieldFromPage() {}
|
|
|
|
// ========================================
|
|
// 페이지 관계 조회
|
|
// ========================================
|
|
|
|
/**
|
|
* @OA\Get(
|
|
* path="/api/v1/item-master/pages/{pageId}/relationships",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="페이지의 모든 관계 조회",
|
|
* description="페이지에 연결된 모든 관계(섹션, 필드)를 조회합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="pageId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="조회 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="조회 성공"),
|
|
* @OA\Property(
|
|
* property="data",
|
|
* type="array",
|
|
*
|
|
* @OA\Items(ref="#/components/schemas/EntityRelationship")
|
|
* )
|
|
* )
|
|
* ),
|
|
*
|
|
* @OA\Response(response=404, description="페이지를 찾을 수 없음")
|
|
* )
|
|
*/
|
|
public function getPageRelationships() {}
|
|
|
|
/**
|
|
* @OA\Get(
|
|
* path="/api/v1/item-master/pages/{pageId}/structure",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="페이지 구조 조회",
|
|
* description="페이지의 전체 구조를 조회합니다 (섹션, 직접 연결된 필드, 중첩 구조).",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="pageId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="조회 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="조회 성공"),
|
|
* @OA\Property(property="data", ref="#/components/schemas/PageStructure")
|
|
* )
|
|
* ),
|
|
*
|
|
* @OA\Response(response=404, description="페이지를 찾을 수 없음")
|
|
* )
|
|
*/
|
|
public function getPageStructure() {}
|
|
|
|
// ========================================
|
|
// 섹션-필드 연결
|
|
// ========================================
|
|
|
|
/**
|
|
* @OA\Post(
|
|
* path="/api/v1/item-master/sections/{sectionId}/link-field",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="섹션에 필드 연결",
|
|
* description="섹션과 필드를 연결합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="sectionId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\RequestBody(
|
|
* required=true,
|
|
*
|
|
* @OA\JsonContent(ref="#/components/schemas/LinkEntityRequest")
|
|
* ),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="연결 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="연결 성공"),
|
|
* @OA\Property(property="data", ref="#/components/schemas/EntityRelationship")
|
|
* )
|
|
* ),
|
|
*
|
|
* @OA\Response(response=404, description="섹션 또는 필드를 찾을 수 없음")
|
|
* )
|
|
*/
|
|
public function linkFieldToSection() {}
|
|
|
|
/**
|
|
* @OA\Delete(
|
|
* path="/api/v1/item-master/sections/{sectionId}/unlink-field/{fieldId}",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="섹션에서 필드 연결 해제",
|
|
* description="섹션과 필드의 연결을 해제합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="sectionId", in="path", required=true, @OA\Schema(type="integer")),
|
|
* @OA\Parameter(name="fieldId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="연결 해제 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="연결 해제 성공"),
|
|
* @OA\Property(property="data", type="string", example="success")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function unlinkFieldFromSection() {}
|
|
|
|
// ========================================
|
|
// 섹션-BOM 연결
|
|
// ========================================
|
|
|
|
/**
|
|
* @OA\Post(
|
|
* path="/api/v1/item-master/sections/{sectionId}/link-bom",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="섹션에 BOM 항목 연결",
|
|
* description="섹션과 BOM 항목을 연결합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="sectionId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\RequestBody(
|
|
* required=true,
|
|
*
|
|
* @OA\JsonContent(ref="#/components/schemas/LinkEntityRequest")
|
|
* ),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="연결 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="연결 성공"),
|
|
* @OA\Property(property="data", ref="#/components/schemas/EntityRelationship")
|
|
* )
|
|
* ),
|
|
*
|
|
* @OA\Response(response=404, description="섹션 또는 BOM 항목을 찾을 수 없음")
|
|
* )
|
|
*/
|
|
public function linkBomToSection() {}
|
|
|
|
/**
|
|
* @OA\Delete(
|
|
* path="/api/v1/item-master/sections/{sectionId}/unlink-bom/{bomId}",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="섹션에서 BOM 항목 연결 해제",
|
|
* description="섹션과 BOM 항목의 연결을 해제합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="sectionId", in="path", required=true, @OA\Schema(type="integer")),
|
|
* @OA\Parameter(name="bomId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="연결 해제 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="연결 해제 성공"),
|
|
* @OA\Property(property="data", type="string", example="success")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function unlinkBomFromSection() {}
|
|
|
|
// ========================================
|
|
// 섹션 관계 조회
|
|
// ========================================
|
|
|
|
/**
|
|
* @OA\Get(
|
|
* path="/api/v1/item-master/sections/{sectionId}/relationships",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="섹션의 자식 관계 조회",
|
|
* description="섹션에 연결된 모든 자식 관계(필드, BOM)를 조회합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\Parameter(name="sectionId", in="path", required=true, @OA\Schema(type="integer")),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="조회 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="조회 성공"),
|
|
* @OA\Property(
|
|
* property="data",
|
|
* type="array",
|
|
*
|
|
* @OA\Items(ref="#/components/schemas/EntityRelationship")
|
|
* )
|
|
* )
|
|
* ),
|
|
*
|
|
* @OA\Response(response=404, description="섹션을 찾을 수 없음")
|
|
* )
|
|
*/
|
|
public function getSectionRelationships() {}
|
|
|
|
// ========================================
|
|
// 관계 순서 변경
|
|
// ========================================
|
|
|
|
/**
|
|
* @OA\Post(
|
|
* path="/api/v1/item-master/relationships/reorder",
|
|
* tags={"ItemMaster-Relationships"},
|
|
* summary="관계 순서 변경",
|
|
* description="특정 부모 아래의 자식 관계 순서를 변경합니다.",
|
|
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
|
*
|
|
* @OA\RequestBody(
|
|
* required=true,
|
|
*
|
|
* @OA\JsonContent(ref="#/components/schemas/ReorderRelationshipsRequest")
|
|
* ),
|
|
*
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="순서 변경 성공",
|
|
*
|
|
* @OA\JsonContent(
|
|
*
|
|
* @OA\Property(property="success", type="boolean", example=true),
|
|
* @OA\Property(property="message", type="string", example="정렬 변경 성공"),
|
|
* @OA\Property(property="data", type="string", example="success")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function reorderRelationships() {}
|
|
}
|