Files
sam-api/app/Swagger/v1/EntityRelationshipApi.php
hskwon bccfa19791 feat: Item Master 하이브리드 구조 전환 및 독립 API 추가
- CASCADE FK → 독립 엔티티 + entity_relationships 링크 테이블
- 독립 API 10개 추가 (섹션/필드/BOM CRUD, clone, usage)
- SectionTemplate 모델 제거 → ItemSection.is_template 통합
- 페이지-섹션, 섹션-필드, 섹션-BOM 링크/언링크 API 14개 추가
- Swagger 문서 업데이트
2025-11-26 14:09:31 +09:00

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() {}
}