style: Laravel Pint 코드 포맷팅 적용

- PSR-12 스타일 가이드 준수
- 302개 파일 스타일 이슈 자동 수정
- 코드 로직 변경 없음 (포맷팅만)
This commit is contained in:
2025-11-06 17:45:49 +09:00
parent 48e76432ee
commit cc206fdbed
294 changed files with 4476 additions and 2561 deletions

View File

@@ -14,19 +14,24 @@ class AdminApi
* summary="사용자 목록",
* description="필터/검색/페이지네이션으로 사용자 목록을 조회합니다.",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="q", in="query", description="이름/이메일 검색어", @OA\Schema(type="string")),
* @OA\Parameter(name="tenant_id", in="query", description="특정 테넌트로 필터", @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="role", in="query", description="역할 코드", @OA\Schema(type="string", example="manager")),
* @OA\Parameter(name="is_active", in="query", description="활성여부", @OA\Schema(type="boolean", example=1)),
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="object",
@@ -47,6 +52,7 @@ class AdminApi
* }
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -64,11 +70,14 @@ public function index() {}
* summary="사용자 생성",
* description="새 사용자를 생성합니다. (초기 비밀번호/역할 포함 가능)",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(
* type="object",
* required={"name","email","password"},
*
* @OA\Property(property="user_id", type="string", example="test001"),
* @OA\Property(property="name", type="string", example="김관리"),
* @OA\Property(property="email", type="string", example="admin@kdcorp.co.kr"),
@@ -77,16 +86,20 @@ public function index() {}
* @OA\Property(property="roles", type="array", @OA\Items(type="string"), example={"manager"})
* )
* ),
*
* @OA\Response(
* response=201,
* description="생성됨",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/User"))
* }
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -104,15 +117,20 @@ public function store() {}
* summary="사용자 단건 조회",
* description="ID 기준 사용자 상세",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=101)),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={@OA\Schema(ref="#/components/schemas/ApiResponse")},
*
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/User"))
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="존재하지 않는 URI 또는 데이터", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -129,17 +147,22 @@ public function show() {}
* summary="사용자 수정",
* description="이름/연락처/역할/활성여부 등 변경",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="name", type="string", example="김관리"),
* @OA\Property(property="phone", type="string", example="010-3333-4444"),
* @OA\Property(property="is_active", type="integer", example=1),
* @OA\Property(property="roles", type="array", @OA\Items(type="string"), example={"manager","staff"})
* )
* ),
*
* @OA\Response(response=200, description="수정 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -158,18 +181,23 @@ public function update() {}
* summary="활성/비활성 전환",
* description="지정된 사용자의 is_active 상태를 변경합니다.",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="사용자 고유 ID",
*
* @OA\Schema(type="integer")
* ),
*
* @OA\Response(
* response=200,
* description="변경 성공",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="테넌트 사용자 활성/비활성 성공"),
* @OA\Property(
@@ -179,6 +207,7 @@ public function update() {}
* )
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -196,16 +225,21 @@ public function toggleStatus() {}
* summary="사용자 삭제(소프트 삭제)",
* description="deleted_at / deleted_by 기록",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=204,
* 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")
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="존재하지 않는 URI 또는 데이터", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -222,16 +256,21 @@ public function destroy() {}
* summary="삭제 복구",
* description="소프트 삭제 복구",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=204,
* 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")
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="존재하지 않는 URI 또는 데이터", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -248,10 +287,14 @@ public function restore() {}
* summary="역할 부여",
* description="사용자에게 역할 추가",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true,
*
* @OA\JsonContent(type="object",
* required={"roles"},
*
* @OA\Property(property="roles", type="array", @OA\Items(type="string"), example={"manager"})
* )
* ),
@@ -259,12 +302,15 @@ public function restore() {}
* @OA\Response(
* response=204,
* description="부여 성공",
*
* @OA\JsonContent(
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="변경 성공"),
* @OA\Property(property="data", type="object", nullable=true, example=null)
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -283,17 +329,22 @@ public function attachRoles() {}
* summary="역할 해제",
* description="사용자에서 특정 역할 제거",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(name="role", in="path", required=true, @OA\Schema(type="string", example="manager")),
*
* @OA\Response(
* response=204,
* description="부여 성공",
*
* @OA\JsonContent(
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="변경 성공"),
* @OA\Property(property="data", type="object", nullable=true, example=null)
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="존재하지 않는 URI 또는 데이터", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -313,26 +364,34 @@ public function detachRole() {}
* - 관리자 권한 확인은 미들웨어/가드에서 처리됩니다.
* - 기본적으로 응답에 비밀번호를 노출하지 않으며, return_password=1일 때만 임시 비밀번호를 반환합니다(운영 환경에서는 노출 비권장).",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="사용자 고유 ID",
*
* @OA\Schema(type="integer")
* ),
*
* @OA\RequestBody(
* required=false,
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="new_password", type="string", minLength=8, maxLength=64, example="Temp!1234", description="지정 시 해당 값으로 비밀번호 초기화, 미지정 시 서버에서 랜덤 생성"),
* @OA\Property(property="return_password", type="integer", enum={0,1}, example=0, description="1이면 응답에 임시 비밀번호 포함(개발/테스트용)")
* )
* ),
*
* @OA\Response(
* response=200,
* description="초기화 성공",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="테넌트 사용자 비밀번호 초기화 성공"),
* @OA\Property(
@@ -343,6 +402,7 @@ public function detachRole() {}
* )
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),

View File

@@ -16,6 +16,7 @@ class AuditLogApi
* tags={"Design Audit"},
* summary="List audit logs",
* security={{"ApiKeyAuth": {}, "BearerAuth": {}}},
*
* @OA\Parameter(name="page", in="query", @OA\Schema(type="integer", minimum=1)),
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", minimum=1, maximum=200)),
* @OA\Parameter(name="target_type", in="query", @OA\Schema(type="string")),
@@ -24,11 +25,14 @@ class AuditLogApi
* @OA\Parameter(name="actor_id", in="query", @OA\Schema(type="integer")),
* @OA\Parameter(name="from", in="query", @OA\Schema(type="string", format="date-time")),
* @OA\Parameter(name="to", in="query", @OA\Schema(type="string", format="date-time")),
*
* @OA\Response(
* response=200,
* description="List",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean"),
* @OA\Property(property="message", type="string"),
* @OA\Property(property="data", type="object",

View File

@@ -17,6 +17,7 @@
* schema="SignupRequest",
* type="object",
* required={"user_id","name","email","password"},
*
* @OA\Property(property="user_id", type="string", maxLength=255, example="userId", description="로그인 ID (고유)"),
* @OA\Property(property="name", type="string", maxLength=255, example="Kent"),
* @OA\Property(property="email", type="string", maxLength=100, example="codebridge@gmail.com"),
@@ -27,6 +28,7 @@
* @OA\Schema(
* schema="SignupResponseData",
* type="object",
*
* @OA\Property(
* property="user",
* ref="#/components/schemas/Member"
@@ -38,13 +40,13 @@
* type="object",
* description="회원 요약 정보(회원가입 응답용)",
* required={"id","user_id","name","email","phone"},
*
* @OA\Property(property="id", type="integer", example=6),
* @OA\Property(property="user_id", type="string", example="userId"),
* @OA\Property(property="name", type="string", example="Kent"),
* @OA\Property(property="email", type="string", example="codebridge1@gmail.com"),
* @OA\Property(property="phone", type="string", example="010-4820-9104")
* )
*
*/
class AuthApi
{
@@ -54,6 +56,7 @@ class AuthApi
* tags={"Auth"},
* summary="API Key 인증 확인",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Response(response=200, description="API Key 인증 성공"),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -66,19 +69,25 @@ public function debugApiKey() {}
* tags={"Auth"},
* summary="로그인 (토큰 발급)",
* security={{"ApiKeyAuth": {}}},
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(
* required={"user_id","user_pwd"},
*
* @OA\Property(property="user_id", type="string", example="hamss"),
* @OA\Property(property="user_pwd", type="string", example="StrongPass!1234")
* )
* ),
*
* @OA\Response(
* response=200,
* description="로그인 성공",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="로그인 성공"),
* @OA\Property(property="data", type="object",
@@ -86,6 +95,7 @@ public function debugApiKey() {}
* )
* )
* ),
*
* @OA\Response(response=401, description="로그인 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -97,15 +107,19 @@ public function login() {}
* tags={"Auth"},
* summary="로그아웃 (Access 및 Token 무효화)",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @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="null", example=null)
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -118,14 +132,19 @@ public function logout() {}
* summary="회원가입",
* description="신규 회원을 생성합니다. (API Key 필요)",
* security={{"ApiKeyAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/SignupRequest")),
*
* @OA\Response(
* response=200,
* description="회원가입 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="object",
@@ -135,6 +154,7 @@ public function logout() {}
* }
* )
* ),
*
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패(API Key 누락/오류)", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )

View File

@@ -9,6 +9,7 @@
* schema="EstimateParametersResponse",
* type="object",
* required={"success","message","data"},
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="견적 파라미터를 성공적으로 조회했습니다."),
* @OA\Property(
@@ -35,8 +36,10 @@
* @OA\Property(
* property="required_parameters",
* type="array",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="key", type="string", example="W0"),
* @OA\Property(property="label", type="string", example="오픈사이즈 가로(mm)"),
* @OA\Property(property="type", type="string", example="integer"),
@@ -53,6 +56,7 @@
* schema="CalculateBomRequest",
* type="object",
* required={"parameters"},
*
* @OA\Property(
* property="parameters",
* type="object",
@@ -67,6 +71,7 @@
* schema="CalculateBomResponse",
* type="object",
* required={"success","message","data"},
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="BOM 계산이 완료되었습니다."),
* @OA\Property(
@@ -98,8 +103,10 @@
* @OA\Property(
* property="bom_items",
* type="array",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="item_id", type="integer", example=1),
* @OA\Property(property="ref_type", type="string", example="MATERIAL"),
* @OA\Property(property="ref_id", type="integer", example=101),
@@ -116,6 +123,7 @@
* schema="CompanyFormulasResponse",
* type="object",
* required={"success","message","data"},
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="업체 산출식 목록을 조회했습니다."),
* @OA\Property(
@@ -126,8 +134,10 @@
* @OA\Property(
* property="formulas",
* type="array",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="type", type="string", example="manufacturing_size"),
* @OA\Property(property="version", type="string", example="v2.0"),
* @OA\Property(property="description", type="string", example="제작사이즈 계산식"),
@@ -141,25 +151,32 @@
* schema="SaveFormulaRequest",
* type="object",
* required={"formula_expression","parameters"},
*
* @OA\Property(property="formula_expression", type="string", example="bracket_quantity"),
* @OA\Property(
* property="parameters",
* type="array",
*
* @OA\Items(type="string"),
* example={"W1", "H1"}
* ),
*
* @OA\Property(
* property="conditions",
* type="array",
*
* @OA\Items(type="string"),
* example={"product_type=screen"}
* ),
*
* @OA\Property(
* property="validation_rules",
* type="array",
*
* @OA\Items(type="string"),
* example={"W1>0", "H1>0"}
* ),
*
* @OA\Property(property="description", type="string", example="브라켓 수량 계산식")
* )
*
@@ -167,6 +184,7 @@
* schema="FormulaTestRequest",
* type="object",
* required={"formula_expression","test_parameters"},
*
* @OA\Property(property="formula_expression", type="string", example="bracket_quantity"),
* @OA\Property(
* property="test_parameters",
@@ -179,6 +197,7 @@
* schema="FormulaTestResponse",
* type="object",
* required={"success","message","data"},
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="계산식 테스트가 완료되었습니다."),
* @OA\Property(
@@ -208,28 +227,36 @@ class BomCalculationApi
* description="특정 모델의 견적 시 필요한 입력 파라미터 스키마를 조회합니다. BOM에 정의된 조건만 동적으로 추출하여 반환합니다.",
* tags={"BOM Calculation"},
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(
* name="model_id",
* in="path",
* required=true,
* description="모델 ID",
*
* @OA\Schema(type="integer", example=1)
* ),
*
* @OA\Parameter(
* name="company_name",
* in="query",
* required=false,
* description="업체명 (선택사항)",
*
* @OA\Schema(type="string", example="경동기업")
* ),
*
* @OA\Response(
* response=200,
* description="견적 파라미터 조회 성공",
*
* @OA\JsonContent(ref="#/components/schemas/EstimateParametersResponse")
* ),
*
* @OA\Response(
* response=404,
* description="모델을 찾을 수 없음",
*
* @OA\JsonContent(ref="#/components/schemas/ErrorResponse")
* )
* )
@@ -243,26 +270,34 @@ public function getEstimateParameters() {}
* description="입력된 파라미터를 기반으로 BOM 수량을 동적으로 계산합니다. 업체별 산출식을 적용하여 실시간 견적을 생성합니다.",
* tags={"BOM Calculation"},
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(
* name="bom_template_id",
* in="path",
* required=true,
* description="BOM 템플릿 ID",
*
* @OA\Schema(type="integer", example=1)
* ),
*
* @OA\RequestBody(
* required=true,
* description="계산 파라미터",
*
* @OA\JsonContent(ref="#/components/schemas/CalculateBomRequest")
* ),
*
* @OA\Response(
* response=200,
* description="BOM 계산 성공",
*
* @OA\JsonContent(ref="#/components/schemas/CalculateBomResponse")
* ),
*
* @OA\Response(
* response=400,
* description="잘못된 파라미터",
*
* @OA\JsonContent(ref="#/components/schemas/ErrorResponse")
* )
* )
@@ -276,21 +311,27 @@ public function calculateBom() {}
* description="특정 업체의 등록된 산출식 목록을 조회합니다.",
* tags={"BOM Calculation"},
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(
* name="company_name",
* in="path",
* required=true,
* description="업체명",
*
* @OA\Schema(type="string", example="경동기업")
* ),
*
* @OA\Response(
* response=200,
* description="업체 산출식 목록 조회 성공",
*
* @OA\JsonContent(ref="#/components/schemas/CompanyFormulasResponse")
* ),
*
* @OA\Response(
* response=404,
* description="업체를 찾을 수 없음",
*
* @OA\JsonContent(ref="#/components/schemas/ErrorResponse")
* )
* )
@@ -304,32 +345,42 @@ public function getCompanyFormulas() {}
* description="특정 업체의 산출식을 등록하거나 수정합니다. 기존 산출식이 있으면 새 버전으로 업데이트됩니다.",
* tags={"BOM Calculation"},
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(
* name="company_name",
* in="path",
* required=true,
* description="업체명",
*
* @OA\Schema(type="string", example="경동기업")
* ),
*
* @OA\Parameter(
* name="formula_type",
* in="path",
* required=true,
* description="산출식 타입",
*
* @OA\Schema(type="string", example="manufacturing_size")
* ),
*
* @OA\RequestBody(
* required=true,
* description="산출식 데이터",
*
* @OA\JsonContent(ref="#/components/schemas/SaveFormulaRequest")
* ),
*
* @OA\Response(
* response=201,
* description="업체 산출식 등록 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="object",
@@ -344,9 +395,11 @@ public function getCompanyFormulas() {}
* }
* )
* ),
*
* @OA\Response(
* response=400,
* description="잘못된 요청",
*
* @OA\JsonContent(ref="#/components/schemas/ErrorResponse")
* )
* )
@@ -360,22 +413,28 @@ public function saveCompanyFormula() {}
* description="산출식을 실제 적용하기 전에 테스트해볼 수 있습니다.",
* tags={"BOM Calculation"},
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\RequestBody(
* required=true,
* description="테스트할 계산식과 파라미터",
*
* @OA\JsonContent(ref="#/components/schemas/FormulaTestRequest")
* ),
*
* @OA\Response(
* response=200,
* description="계산식 테스트 성공",
*
* @OA\JsonContent(ref="#/components/schemas/FormulaTestResponse")
* ),
*
* @OA\Response(
* response=400,
* description="잘못된 계산식",
*
* @OA\JsonContent(ref="#/components/schemas/ErrorResponse")
* )
* )
*/
public function testFormula() {}
}
}

View File

@@ -9,6 +9,7 @@
* schema="Category",
* type="object",
* required={"id","name"},
*
* @OA\Property(property="id", type="integer", example=12),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="parent_id", type="integer", nullable=true, example=null),
@@ -24,12 +25,15 @@
* @OA\Schema(
* schema="CategoryPagination",
* type="object",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/Category")
* ),
*
* @OA\Property(property="first_page_url", type="string", example="/api/v1/categories?page=1"),
* @OA\Property(property="from", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=3),
@@ -37,7 +41,9 @@
* @OA\Property(
* property="links",
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="url", type="string", nullable=true, example=null),
* @OA\Property(property="label", type="string", example="« Previous"),
* @OA\Property(property="active", type="boolean", example=false)
@@ -55,6 +61,7 @@
* schema="CategoryCreateRequest",
* type="object",
* required={"name"},
*
* @OA\Property(property="parent_id", type="integer", nullable=true),
* @OA\Property(property="code", type="string", nullable=true, maxLength=50),
* @OA\Property(property="name", type="string", maxLength=100),
@@ -66,6 +73,7 @@
* @OA\Schema(
* schema="CategoryUpdateRequest",
* type="object",
*
* @OA\Property(property="parent_id", type="integer", nullable=true),
* @OA\Property(property="code", type="string", nullable=true, maxLength=50),
* @OA\Property(property="name", type="string", maxLength=100),
@@ -77,6 +85,7 @@
* @OA\Schema(
* schema="CategoryTreeNode",
* type="object",
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="code", type="string", nullable=true, example="ELC"),
* @OA\Property(property="name", type="string", example="전자"),
@@ -93,17 +102,22 @@ class CategoryApi
* tags={"Category"},
* summary="카테고리 목록",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="page", in="query", @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", example=20)),
* @OA\Parameter(name="q", in="query", description="코드/이름 검색", @OA\Schema(type="string")),
* @OA\Parameter(name="parent_id", in="query", @OA\Schema(type="integer", nullable=true)),
* @OA\Parameter(name="only_active", in="query", @OA\Schema(type="boolean")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/CategoryPagination"))
* })
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -115,13 +129,18 @@ public function index() {}
* tags={"Category"},
* summary="카테고리 단건 조회",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Category"))
* })
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -133,13 +152,18 @@ public function show() {}
* tags={"Category"},
* summary="카테고리 생성",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/CategoryCreateRequest")),
*
* @OA\Response(response=200, description="생성 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Category"))
* })
* ),
*
* @OA\Response(response=400, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -151,10 +175,15 @@ public function store() {}
* tags={"Category"},
* summary="카테고리 수정",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/CategoryUpdateRequest")),
*
* @OA\Response(response=200, description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Category"))
* })
@@ -169,7 +198,9 @@ public function update() {}
* tags={"Category"},
* summary="카테고리 삭제(soft)",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -181,9 +212,13 @@ public function destroy() {}
* tags={"Category"},
* summary="활성/비활성 토글",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="변경 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Category"))
* })
@@ -198,14 +233,20 @@ public function toggle() {}
* tags={"Category"},
* summary="부모/순서 이동",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(
* type="object",
*
* @OA\Property(property="parent_id", type="integer", nullable=true),
* @OA\Property(property="sort_order", type="integer", nullable=true)
* )),
*
* @OA\Response(response=200, description="이동 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Category"))
* })
@@ -220,14 +261,17 @@ public function move() {}
* tags={"Category"},
* summary="정렬순서 일괄 변경",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(
* type="object",
*
* @OA\Property(property="items", type="array", @OA\Items(
* type="object",
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="sort_order", type="integer", example=10)
* ))
* )),
*
* @OA\Response(response=200, description="저장 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -239,9 +283,13 @@ public function reorder() {}
* tags={"Category"},
* summary="카테고리 트리",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="only_active", in="query", @OA\Schema(type="boolean")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/CategoryTreeNode")))
* })

View File

@@ -19,6 +19,7 @@
* schema="CategoryField",
* type="object",
* required={"id","tenant_id","category_id","field_key","field_name","field_type"},
*
* @OA\Property(property="id", type="integer", example=11),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="category_id", type="integer", example=7),
@@ -43,12 +44,15 @@
* @OA\Schema(
* schema="CategoryFieldPagination",
* type="object",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/CategoryField")
* ),
*
* @OA\Property(property="per_page", type="integer", example=20),
* @OA\Property(property="total", type="integer", example=3)
* )
@@ -57,6 +61,7 @@
* schema="CategoryFieldCreateRequest",
* type="object",
* required={"field_key","field_name","field_type"},
*
* @OA\Property(property="field_key", type="string", example="height"),
* @OA\Property(property="field_name", type="string", example="높이(mm)"),
* @OA\Property(property="field_type", type="string", example="number"),
@@ -75,6 +80,7 @@
* @OA\Schema(
* schema="CategoryFieldUpdateRequest",
* type="object",
*
* @OA\Property(property="field_key", type="string", example="height"),
* @OA\Property(property="field_name", type="string", example="높이(mm)"),
* @OA\Property(property="field_type", type="string", example="number"),
@@ -93,9 +99,11 @@
* @OA\Schema(
* schema="CategoryFieldReorderRequest",
* type="array",
*
* @OA\Items(
* type="object",
* required={"id","sort_order"},
*
* @OA\Property(property="id", type="integer", example=11),
* @OA\Property(property="sort_order", type="integer", example=1)
* )
@@ -105,11 +113,14 @@
* schema="CategoryFieldBulkUpsertRequest",
* type="object",
* required={"items"},
*
* @OA\Property(
* property="items",
* type="array",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="id", type="integer", nullable=true, example=null),
* @OA\Property(property="field_key", type="string", example="thickness"),
* @OA\Property(property="field_name", type="string", example="두께(mm)"),
@@ -127,6 +138,7 @@
* schema="CategoryTemplate",
* type="object",
* required={"id","tenant_id","category_id","version_no","template_json","applied_at"},
*
* @OA\Property(property="id", type="integer", example=1001),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="category_id", type="integer", example=7),
@@ -147,6 +159,7 @@
* schema="CategoryTemplateCreateRequest",
* type="object",
* required={"version_no","template_json","applied_at"},
*
* @OA\Property(property="version_no", type="integer", example=4),
* @OA\Property(
* property="template_json",
@@ -165,6 +178,7 @@
* @OA\Schema(
* schema="CategoryTemplateUpdateRequest",
* type="object",
*
* @OA\Property(
* property="template_json",
* type="object",
@@ -178,6 +192,7 @@
* schema="CategoryLog",
* type="object",
* required={"id","tenant_id","category_id","action","changed_at"},
*
* @OA\Property(property="id", type="integer", example=501),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="category_id", type="integer", example=7),
@@ -203,19 +218,24 @@ class CategoryExtras
* tags={"Category-Fields"},
* summary="카테고리별 필드 목록",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"), description="카테고리 ID"),
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
* @OA\Parameter(name="sort", in="query", @OA\Schema(type="string", example="sort_order")),
* @OA\Parameter(name="order", in="query", @OA\Schema(type="string", enum={"asc","desc"}, example="asc")),
*
* @OA\Response(
* response=200,
* description="목록 조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/CategoryFieldPagination"))
* })
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -227,16 +247,22 @@ public function fieldsIndex() {}
* tags={"Category-Fields"},
* summary="카테고리 필드 생성",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/CategoryFieldCreateRequest")),
*
* @OA\Response(
* response=200,
* description="생성 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/CategoryField"))
* })
* ),
*
* @OA\Response(response=400, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -248,15 +274,20 @@ public function fieldsStore() {}
* tags={"Category-Fields"},
* summary="카테고리 필드 단건 조회",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="field", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/CategoryField"))
* })
* ),
*
* @OA\Response(response=404, description="없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -268,12 +299,17 @@ public function fieldsShow() {}
* tags={"Category-Fields"},
* summary="카테고리 필드 수정",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="field", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/CategoryFieldUpdateRequest")),
*
* @OA\Response(
* response=200,
* description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/CategoryField"))
* })
@@ -288,10 +324,13 @@ public function fieldsUpdate() {}
* tags={"Category-Fields"},
* summary="카테고리 필드 삭제",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="field", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="삭제 성공",
*
* @OA\JsonContent(ref="#/components/schemas/ApiResponse")
* )
* )
@@ -304,8 +343,11 @@ public function fieldsDestroy() {}
* tags={"Category-Fields"},
* summary="카테고리 필드 정렬 저장",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/CategoryFieldReorderRequest")),
*
* @OA\Response(response=200, description="저장 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -317,14 +359,20 @@ public function fieldsReorder() {}
* tags={"Category-Fields"},
* summary="카테고리 필드 일괄 업서트",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/CategoryFieldBulkUpsertRequest")),
*
* @OA\Response(
* response=200,
* description="업서트 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", type="object",
* @OA\Property(property="created", type="integer", example=2),
* @OA\Property(property="updated", type="integer", example=3)
@@ -348,23 +396,30 @@ public function fieldsBulkUpsert() {}
* tags={"Category-Templates"},
* summary="카테고리 템플릿 버전 목록",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
*
* @OA\Response(
* response=200,
* description="목록 조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="object",
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/CategoryTemplate")
* ),
*
* @OA\Property(property="total", type="integer", example=3)
* )
* )
@@ -380,16 +435,22 @@ public function templatesIndex() {}
* tags={"Category-Templates"},
* summary="카테고리 템플릿 생성(새 버전)",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/CategoryTemplateCreateRequest")),
*
* @OA\Response(
* response=200,
* description="생성 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/CategoryTemplate"))
* })
* ),
*
* @OA\Response(response=409, description="버전 중복", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -401,11 +462,15 @@ public function templatesStore() {}
* tags={"Category-Templates"},
* summary="카테고리 템플릿 단건 조회",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="tpl", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/CategoryTemplate"))
* })
@@ -420,12 +485,17 @@ public function templatesShow() {}
* tags={"Category-Templates"},
* summary="카테고리 템플릿 수정",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="tpl", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/CategoryTemplateUpdateRequest")),
*
* @OA\Response(
* response=200,
* description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/CategoryTemplate"))
* })
@@ -440,7 +510,9 @@ public function templatesUpdate() {}
* tags={"Category-Templates"},
* summary="카테고리 템플릿 삭제",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="tpl", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -452,8 +524,10 @@ public function templatesDestroy() {}
* tags={"Category-Templates"},
* summary="카테고리 템플릿 적용(활성화)",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(name="tpl", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="적용 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -465,11 +539,14 @@ public function templatesApply() {}
* tags={"Category-Templates"},
* summary="카테고리 템플릿 미리보기",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(name="tpl", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="미리보기 성공",
*
* @OA\JsonContent(allOf={@OA\Schema(ref="#/components/schemas/ApiResponse")})
* )
* )
@@ -482,15 +559,20 @@ public function templatesPreview() {}
* tags={"Category-Templates"},
* summary="두 버전 비교(diff)",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(name="a", in="query", required=true, @OA\Schema(type="integer"), description="비교 기준 버전"),
* @OA\Parameter(name="b", in="query", required=true, @OA\Schema(type="integer"), description="비교 대상 버전"),
*
* @OA\Response(
* response=200,
* description="비교 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", type="object",
* @OA\Property(property="added", type="array", @OA\Items(type="string")),
* @OA\Property(property="removed", type="array", @OA\Items(type="string"))
@@ -514,26 +596,33 @@ public function templatesDiff() {}
* tags={"Category-Logs"},
* summary="카테고리 변경 이력 목록",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(name="action", in="query", @OA\Schema(type="string", enum={"insert","update","delete"})),
* @OA\Parameter(name="from", in="query", @OA\Schema(type="string", format="date")),
* @OA\Parameter(name="to", in="query", @OA\Schema(type="string", format="date")),
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
*
* @OA\Response(
* response=200,
* description="목록 조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="object",
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/CategoryLog")
* ),
*
* @OA\Property(property="total", type="integer", example=12)
* )
* )
@@ -549,11 +638,15 @@ public function logsIndex() {}
* tags={"Category-Logs"},
* summary="카테고리 변경 이력 단건 조회",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="log", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/CategoryLog"))
* })

View File

@@ -9,6 +9,7 @@
* schema="Classification",
* type="object",
* required={"id","group","name"},
*
* @OA\Property(property="id", type="integer", example=11),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="group", type="string", example="product_type"),
@@ -25,12 +26,15 @@
* schema="ClassificationPagination",
* type="object",
* description="라라벨 LengthAwarePaginator 기본 구조",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/Classification")
* ),
*
* @OA\Property(property="first_page_url", type="string", example="/api/v1/classifications?page=1"),
* @OA\Property(property="from", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=3),
@@ -38,7 +42,9 @@
* @OA\Property(
* property="links",
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="url", type="string", nullable=true, example=null),
* @OA\Property(property="label", type="string", example="« Previous"),
* @OA\Property(property="active", type="boolean", example=false)
@@ -56,6 +62,7 @@
* schema="ClassificationCreateRequest",
* type="object",
* required={"group","name"},
*
* @OA\Property(property="group", type="string", maxLength=50, example="product_type"),
* @OA\Property(property="code", type="string", nullable=true, maxLength=50, example="OUTER"),
* @OA\Property(property="name", type="string", maxLength=100, example="아우터"),
@@ -67,6 +74,7 @@
* @OA\Schema(
* schema="ClassificationUpdateRequest",
* type="object",
*
* @OA\Property(property="group", type="string", maxLength=50),
* @OA\Property(property="code", type="string", nullable=true, maxLength=50),
* @OA\Property(property="name", type="string", maxLength=100),
@@ -84,19 +92,24 @@ class ClassificationApi
* summary="분류 목록",
* description="그룹/검색/활성여부 조건으로 분류 목록을 페이징 반환합니다.",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="page", in="query", @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", example=20)),
* @OA\Parameter(name="q", in="query", description="코드/이름 검색", @OA\Schema(type="string")),
* @OA\Parameter(name="group", in="query", description="분류 그룹 키", @OA\Schema(type="string")),
* @OA\Parameter(name="only_active", in="query", @OA\Schema(type="boolean")),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ClassificationPagination"))
* })
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -108,15 +121,20 @@ public function index() {}
* tags={"Classification"},
* summary="분류 단건 조회",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Classification"))
* })
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -128,15 +146,20 @@ public function show() {}
* tags={"Classification"},
* summary="분류 생성",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ClassificationCreateRequest")),
*
* @OA\Response(
* response=200,
* description="생성 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Classification"))
* })
* ),
*
* @OA\Response(response=400, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -148,16 +171,22 @@ public function store() {}
* tags={"Classification"},
* summary="분류 수정",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ClassificationUpdateRequest")),
*
* @OA\Response(
* response=200,
* description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Classification"))
* })
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -169,7 +198,9 @@ public function update() {}
* tags={"Classification"},
* summary="분류 삭제(soft)",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )

View File

@@ -9,6 +9,7 @@
* schema="Client",
* type="object",
* required={"id","client_code","name"},
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1, description="고객 그룹 ID"),
@@ -26,12 +27,15 @@
* @OA\Schema(
* schema="ClientPagination",
* type="object",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/Client")
* ),
*
* @OA\Property(property="first_page_url", type="string", example="/api/v1/clients?page=1"),
* @OA\Property(property="from", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=3),
@@ -39,7 +43,9 @@
* @OA\Property(
* property="links",
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="url", type="string", nullable=true, example=null),
* @OA\Property(property="label", type="string", example="« Previous"),
* @OA\Property(property="active", type="boolean", example=false)
@@ -57,6 +63,7 @@
* schema="ClientCreateRequest",
* type="object",
* required={"client_code","name"},
*
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1, description="고객 그룹 ID"),
* @OA\Property(property="client_code", type="string", maxLength=50, example="CLIENT_001"),
* @OA\Property(property="name", type="string", maxLength=100, example="거래처명"),
@@ -70,6 +77,7 @@
* @OA\Schema(
* schema="ClientUpdateRequest",
* type="object",
*
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1, description="고객 그룹 ID"),
* @OA\Property(property="client_code", type="string", maxLength=50),
* @OA\Property(property="name", type="string", maxLength=100),
@@ -88,16 +96,21 @@ class ClientApi
* tags={"Client"},
* summary="거래처 목록",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="page", in="query", @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", example=20)),
* @OA\Parameter(name="q", in="query", description="거래처 코드/이름 검색", @OA\Schema(type="string")),
* @OA\Parameter(name="only_active", in="query", @OA\Schema(type="boolean")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ClientPagination"))
* })
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -109,13 +122,18 @@ public function index() {}
* tags={"Client"},
* summary="거래처 단건 조회",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Client"))
* })
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -127,13 +145,18 @@ public function show() {}
* tags={"Client"},
* summary="거래처 생성",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ClientCreateRequest")),
*
* @OA\Response(response=200, description="생성 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Client"))
* })
* ),
*
* @OA\Response(response=400, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -145,10 +168,15 @@ public function store() {}
* tags={"Client"},
* summary="거래처 수정",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ClientUpdateRequest")),
*
* @OA\Response(response=200, description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Client"))
* })
@@ -163,7 +191,9 @@ public function update() {}
* tags={"Client"},
* summary="거래처 삭제(soft)",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -175,9 +205,13 @@ public function destroy() {}
* tags={"Client"},
* summary="활성/비활성 토글",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="변경 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Client"))
* })

View File

@@ -9,6 +9,7 @@
* schema="ClientGroup",
* type="object",
* required={"id","group_code","group_name","price_rate"},
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="group_code", type="string", example="VIP"),
@@ -22,12 +23,15 @@
* @OA\Schema(
* schema="ClientGroupPagination",
* type="object",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/ClientGroup")
* ),
*
* @OA\Property(property="first_page_url", type="string", example="/api/v1/client-groups?page=1"),
* @OA\Property(property="from", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=3),
@@ -35,7 +39,9 @@
* @OA\Property(
* property="links",
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="url", type="string", nullable=true, example=null),
* @OA\Property(property="label", type="string", example="« Previous"),
* @OA\Property(property="active", type="boolean", example=false)
@@ -53,6 +59,7 @@
* schema="ClientGroupCreateRequest",
* type="object",
* required={"group_code","group_name","price_rate"},
*
* @OA\Property(property="group_code", type="string", maxLength=30, example="VIP", description="그룹 코드"),
* @OA\Property(property="group_name", type="string", maxLength=100, example="VIP 고객", description="그룹명"),
* @OA\Property(property="price_rate", type="number", format="decimal", example=0.9, description="가격 배율 (1.0=기준가)"),
@@ -62,6 +69,7 @@
* @OA\Schema(
* schema="ClientGroupUpdateRequest",
* type="object",
*
* @OA\Property(property="group_code", type="string", maxLength=30),
* @OA\Property(property="group_name", type="string", maxLength=100),
* @OA\Property(property="price_rate", type="number", format="decimal"),
@@ -76,16 +84,21 @@ class ClientGroupApi
* tags={"ClientGroup"},
* summary="고객 그룹 목록",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="page", in="query", @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", example=20)),
* @OA\Parameter(name="q", in="query", description="그룹 코드/이름 검색", @OA\Schema(type="string")),
* @OA\Parameter(name="only_active", in="query", @OA\Schema(type="boolean")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ClientGroupPagination"))
* })
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -97,13 +110,18 @@ public function index() {}
* tags={"ClientGroup"},
* summary="고객 그룹 단건 조회",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ClientGroup"))
* })
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -116,13 +134,18 @@ public function show() {}
* summary="고객 그룹 생성",
* description="고객 그룹을 생성합니다. 같은 group_code로 이전에 삭제된 그룹이 있으면 자동으로 복원하고 새 데이터로 업데이트합니다.",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ClientGroupCreateRequest")),
*
* @OA\Response(response=200, description="생성 성공 (또는 삭제된 데이터 복원)",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ClientGroup"))
* })
* ),
*
* @OA\Response(response=400, description="검증 실패 또는 중복 코드", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -134,10 +157,15 @@ public function store() {}
* tags={"ClientGroup"},
* summary="고객 그룹 수정",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ClientGroupUpdateRequest")),
*
* @OA\Response(response=200, description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ClientGroup"))
* })
@@ -152,7 +180,9 @@ public function update() {}
* tags={"ClientGroup"},
* summary="고객 그룹 삭제(soft)",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -164,9 +194,13 @@ public function destroy() {}
* tags={"ClientGroup"},
* summary="활성/비활성 토글",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="변경 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ClientGroup"))
* })
@@ -174,4 +208,4 @@ public function destroy() {}
* )
*/
public function toggle() {}
}
}

View File

@@ -2,6 +2,4 @@
namespace App\Swagger\v1;
class CommonApi {}
class CommonApi {}

View File

@@ -11,6 +11,7 @@
* in="query",
* required=false,
* description="페이지 번호(1부터)",
*
* @OA\Schema(type="integer", minimum=1, example=1)
* )
*
@@ -20,12 +21,13 @@
* in="query",
* required=false,
* description="페이지 당 개수(기본 20)",
*
* @OA\Schema(type="integer", minimum=1, maximum=200, example=20)
* )
*
* @OA\Schema(
* schema="ApiResponse",
* type="object",
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="요청 성공"),
* @OA\Property(property="data", nullable=true)
@@ -34,6 +36,7 @@
* @OA\Schema(
* schema="PaginationMeta",
* type="object",
*
* @OA\Property(property="page", type="integer", example=1),
* @OA\Property(property="size", type="integer", example=20),
* @OA\Property(property="total", type="integer", example=126),
@@ -44,6 +47,7 @@
* schema="User",
* type="object",
* required={"id","name","email"},
*
* @OA\Property(property="id", type="integer", example=101),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="name", type="string", example="홍길동"),
@@ -59,6 +63,7 @@
* schema="LoginRequest",
* type="object",
* required={"email","password"},
*
* @OA\Property(property="email", type="string", example="hong@kdcorp.co.kr"),
* @OA\Property(property="password", type="string", example="secret1234!")
* )
@@ -66,6 +71,7 @@
* @OA\Schema(
* schema="TokenResponse",
* type="object",
*
* @OA\Property(property="access_token", type="string", example="eyJhbGciOi..."),
* @OA\Property(property="token_type", type="string", example="Bearer"),
* @OA\Property(property="expires_in", type="integer", example=3600)
@@ -74,6 +80,7 @@
* @OA\Schema(
* schema="UserUpdateRequest",
* type="object",
*
* @OA\Property(property="name", type="string", example="홍길동"),
* @OA\Property(property="phone", type="string", example="010-1111-2222")
* )
@@ -82,6 +89,7 @@
* schema="PasswordChangeRequest",
* type="object",
* required={"current_password","new_password"},
*
* @OA\Property(property="current_password", type="string", example="oldPass!234"),
* @OA\Property(property="new_password", type="string", example="NewPass!234")
* )
@@ -90,6 +98,7 @@
* schema="SwitchTenantRequest",
* type="object",
* required={"tenant_id"},
*
* @OA\Property(property="tenant_id", type="integer", example=2, description="스위치할 테넌트 ID")
* )
*
@@ -97,6 +106,7 @@
* schema="ErrorResponse",
* type="object",
* description="공통 에러 응답 포맷",
*
* @OA\Property(property="success", type="boolean", example=false),
* @OA\Property(property="message", type="string", example="요청 실패"),
* @OA\Property(

View File

@@ -21,6 +21,7 @@
* type="object",
* description="부서 상세",
* required={"id","name"},
*
* @OA\Property(property="id", type="integer", example=7),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="code", type="string", nullable=true, example="OPS"),
@@ -37,6 +38,7 @@
* type="object",
* description="부서 요약",
* required={"id","name"},
*
* @OA\Property(property="id", type="integer", example=7),
* @OA\Property(property="code", type="string", nullable=true, example="OPS"),
* @OA\Property(property="name", type="string", example="운영팀"),
@@ -47,6 +49,7 @@
* @OA\Schema(
* schema="DepartmentList",
* type="array",
*
* @OA\Items(ref="#/components/schemas/DepartmentBrief")
* )
*
@@ -54,6 +57,7 @@
* schema="DepartmentCreateRequest",
* type="object",
* required={"name"},
*
* @OA\Property(property="code", type="string", nullable=true, example="OPS"),
* @OA\Property(property="name", type="string", example="운영팀"),
* @OA\Property(property="description", type="string", nullable=true, example="서비스 운영 총괄"),
@@ -64,6 +68,7 @@
* @OA\Schema(
* schema="DepartmentUpdateRequest",
* type="object",
*
* @OA\Property(property="code", type="string", nullable=true, example="OPS2"),
* @OA\Property(property="name", type="string", example="운영기획팀"),
* @OA\Property(property="description", type="string", nullable=true, example="운영 기획/성과 관리"),
@@ -75,6 +80,7 @@
* schema="DepartmentUserAttachRequest",
* type="object",
* required={"user_id"},
*
* @OA\Property(property="user_id", type="integer", example=12),
* @OA\Property(property="is_primary", type="integer", enum={0,1}, nullable=true, example=0),
* @OA\Property(property="joined_at", type="string", format="date-time", nullable=true, example="2025-08-21 10:00:00")
@@ -85,6 +91,7 @@
* type="object",
* description="부서원 요약",
* required={"id","name","email"},
*
* @OA\Property(property="id", type="integer", example=12),
* @OA\Property(property="name", type="string", example="홍길동"),
* @OA\Property(property="email", type="string", format="email", example="hong@example.com"),
@@ -96,6 +103,7 @@
* schema="DepartmentPermissionUpsertSingle",
* type="object",
* required={"permission_id"},
*
* @OA\Property(property="permission_id", type="integer", example=25),
* @OA\Property(property="is_allowed", type="integer", enum={0,1}, example=1, description="1=ALLOW, 0=DENY(차단)")
* )
@@ -104,9 +112,11 @@
* schema="DepartmentPermissionUpsertMany",
* type="object",
* required={"items"},
*
* @OA\Property(
* property="items",
* type="array",
*
* @OA\Items(ref="#/components/schemas/DepartmentPermissionUpsertSingle")
* )
* )
@@ -115,6 +125,7 @@
* schema="DepartmentPermissionRevokeSingle",
* type="object",
* required={"permission_id"},
*
* @OA\Property(property="permission_id", type="integer", example=25)
* )
*
@@ -122,14 +133,15 @@
* schema="DepartmentPermissionRevokeMany",
* type="object",
* required={"items"},
*
* @OA\Property(
* property="items",
* type="array",
*
* @OA\Items(ref="#/components/schemas/DepartmentPermissionRevokeSingle")
* )
* )
*/
class DepartmentApi
{
/**
@@ -139,12 +151,16 @@ class DepartmentApi
* description="테넌트 범위 내 부서 목록을 페이징으로 반환합니다. (q로 이름/코드 검색)",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="page", in="query", required=false, @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="per_page", in="query", required=false, @OA\Schema(type="integer", example=10)),
* @OA\Parameter(name="q", in="query", required=false, @OA\Schema(type="string", example="운영")),
* @OA\Parameter(name="is_active", in="query", required=false, @OA\Schema(type="integer", enum={0,1}, example=1)),
*
* @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="object",
@@ -155,6 +171,7 @@ class DepartmentApi
* )
* )
* ),
*
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -166,14 +183,19 @@ public function index() {}
* summary="부서 단건 조회",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
*
* @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/Department")
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -185,14 +207,19 @@ public function show() {}
* summary="부서 생성",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/DepartmentCreateRequest")),
*
* @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/Department")
* )
* ),
*
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -204,15 +231,21 @@ public function store() {}
* summary="부서 수정",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/DepartmentUpdateRequest")),
*
* @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/Department")
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -225,9 +258,13 @@ public function update() {}
* summary="부서 삭제(소프트)",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
*
* @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="object",
@@ -236,6 +273,7 @@ public function update() {}
* )
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -248,11 +286,15 @@ public function destroy() {}
* description="해당 부서에 속한 사용자 목록을 페이징으로 반환합니다.",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
* @OA\Parameter(name="page", in="query", required=false, @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="per_page", in="query", required=false, @OA\Schema(type="integer", example=20)),
*
* @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="object",
@@ -263,6 +305,7 @@ public function destroy() {}
* )
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -274,10 +317,15 @@ public function users() {}
* summary="부서 사용자 배정(단건)",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/DepartmentUserAttachRequest")),
*
* @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="object",
@@ -286,6 +334,7 @@ public function users() {}
* )
* )
* ),
*
* @OA\Response(response=409, description="이미 배정됨", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="부서 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
@@ -299,10 +348,14 @@ public function attachUser() {}
* summary="부서 사용자 해제(단건)",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
* @OA\Parameter(name="user", in="path", required=true, @OA\Schema(type="integer", example=12)),
*
* @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="object",
@@ -311,6 +364,7 @@ public function attachUser() {}
* )
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -322,16 +376,23 @@ public function detachUser() {}
* summary="주부서 설정/해제",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
* @OA\Parameter(name="user", in="path", required=true, @OA\Schema(type="integer", example=12)),
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(
*
* @OA\Property(property="is_primary", type="integer", enum={0,1}, example=1)
* )
* ),
*
* @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="object",
@@ -341,6 +402,7 @@ public function detachUser() {}
* )
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -354,13 +416,17 @@ public function setPrimary() {}
* description="부서에 설정된 ALLOW/DENY 목록을 조회합니다. (is_allowed=1|0, menu_id 필터 지원)",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
* @OA\Parameter(name="menu_id", in="query", required=false, @OA\Schema(type="integer", example=101)),
* @OA\Parameter(name="is_allowed", in="query", required=false, @OA\Schema(type="integer", enum={0,1}, example=1)),
* @OA\Parameter(name="page", in="query", required=false, @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="per_page", in="query", required=false, @OA\Schema(type="integer", example=20)),
*
* @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="object",
@@ -368,7 +434,9 @@ public function setPrimary() {}
* @OA\Property(property="per_page", type="integer", example=20),
* @OA\Property(property="total", type="integer", example=3),
* @OA\Property(property="data", type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="permission_id", type="integer", example=25),
* @OA\Property(property="permission_code", type="string", example="menu.101.read"),
* @OA\Property(property="is_allowed", type="integer", example=1),
@@ -380,6 +448,7 @@ public function setPrimary() {}
* )
* )
* ),
*
* @OA\Response(response=404, description="부서 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -392,16 +461,23 @@ public function listPermissions() {}
* description="permission_id 기준으로 ALLOW(1) 또는 DENY(0) 처리합니다. 단건 또는 items 배열을 모두 지원합니다.",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(oneOf={
*
* @OA\Schema(ref="#/components/schemas/DepartmentPermissionUpsertSingle"),
* @OA\Schema(ref="#/components/schemas/DepartmentPermissionUpsertMany")
* })
* ),
*
* @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="object",
@@ -411,6 +487,7 @@ public function listPermissions() {}
* )
* )
* ),
*
* @OA\Response(response=404, description="부서 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -424,16 +501,23 @@ public function upsertPermission() {}
* description="지정 권한을 부서 매핑에서 제거합니다. 단건 또는 items 배열을 모두 지원합니다.",
* tags={"Department"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=7)),
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(oneOf={
*
* @OA\Schema(ref="#/components/schemas/DepartmentPermissionRevokeSingle"),
* @OA\Schema(ref="#/components/schemas/DepartmentPermissionRevokeMany")
* })
* ),
*
* @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="object",
@@ -443,6 +527,7 @@ public function upsertPermission() {}
* )
* )
* ),
*
* @OA\Response(response=404, description="부서 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )

View File

@@ -16,13 +16,17 @@ class DesignBomTemplateExtras
* tags={"Design BOM"},
* summary="Diff two BOM templates",
* security={{"ApiKeyAuth": {}, "BearerAuth": {}}},
*
* @OA\Parameter(name="templateId", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(name="other_template_id", in="query", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="Success",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean"),
* @OA\Property(property="message", type="string"),
* @OA\Property(property="data", type="object",
@@ -58,21 +62,28 @@ class DesignBomTemplateExtras
* tags={"Design BOM"},
* summary="Clone a BOM template (deep copy)",
* security={{"ApiKeyAuth": {}, "BearerAuth": {}}},
*
* @OA\Parameter(name="templateId", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(
* required=false,
*
* @OA\JsonContent(type="object",
*
* @OA\Property(property="target_version_id", type="integer", nullable=true),
* @OA\Property(property="name", type="string", nullable=true),
* @OA\Property(property="is_primary", type="boolean", nullable=true),
* @OA\Property(property="notes", type="string", nullable=true)
* )
* ),
*
* @OA\Response(
* response=200,
* description="Cloned",
*
* @OA\JsonContent(
* type="object",
*
* @OA\Property(property="success", type="boolean"),
* @OA\Property(property="message", type="string"),
* @OA\Property(property="data", type="object",
@@ -90,6 +101,7 @@ class DesignBomTemplateExtras
* @OA\Schema(
* schema="DesignBomItemDiffRow",
* type="object",
*
* @OA\Property(property="ref_type", type="string", example="MATERIAL"),
* @OA\Property(property="ref_id", type="integer"),
* @OA\Property(property="qty", type="number"),

View File

@@ -17,6 +17,7 @@
* schema="DesignModel",
* type="object",
* required={"id","tenant_id","code","name"},
*
* @OA\Property(property="id", type="integer", example=101),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="code", type="string", example="KSS01"),
@@ -34,6 +35,7 @@
* schema="DesignModelPagination",
* type="object",
* description="라라벨 LengthAwarePaginator",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/DesignModel")),
* @OA\Property(property="first_page_url", type="string", example="/api/v1/design/models?page=1"),
@@ -58,6 +60,7 @@
* schema="ModelVersion",
* type="object",
* required={"id","tenant_id","model_id","version_no","status"},
*
* @OA\Property(property="id", type="integer", example=201),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="model_id", type="integer", example=101),
@@ -76,6 +79,7 @@
* schema="BomTemplate",
* type="object",
* required={"id","tenant_id","model_version_id","name"},
*
* @OA\Property(property="id", type="integer", example=301),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="model_version_id", type="integer", example=201),
@@ -92,6 +96,7 @@
* schema="BomTemplateItem",
* type="object",
* required={"id","tenant_id","bom_template_id","ref_type","ref_id","qty"},
*
* @OA\Property(property="id", type="integer", example=401),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="bom_template_id", type="integer", example=301),
@@ -110,12 +115,15 @@
* schema="BomTemplateItemReplaceRequest",
* type="object",
* required={"items"},
*
* @OA\Property(
* property="items",
* type="array",
*
* @OA\Items(
* type="object",
* required={"ref_type","ref_id","qty"},
*
* @OA\Property(property="ref_type", type="string", enum={"MATERIAL","PRODUCT"}, example="MATERIAL"),
* @OA\Property(property="ref_id", type="integer", example=101),
* @OA\Property(property="qty", type="number", format="double", example=2),
@@ -140,18 +148,23 @@ class DesignModelApi
* summary="모델 목록",
* description="모델(설계 상위) 목록을 페이징으로 조회합니다.",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="q", in="query", description="검색어(code/name/description like)", @OA\Schema(type="string")),
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
*
* @OA\Response(
* response=200, description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/DesignModelPagination"))
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=500, description="서버 에러", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -165,10 +178,13 @@ public function index() {}
* summary="모델 생성",
* description="모델(설계 상위)을 생성합니다.",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(
* required={"code","name"},
*
* @OA\Property(property="code", type="string", maxLength=100, example="KSS01"),
* @OA\Property(property="name", type="string", maxLength=200, example="KSS 표준 모델"),
* @OA\Property(property="category_id", type="integer", nullable=true, example=12),
@@ -177,10 +193,13 @@ public function index() {}
* @OA\Property(property="is_active", type="boolean", example=true)
* )
* ),
*
* @OA\Response(response=200, description="등록 성공", @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/DesignModel"))
* })),
*
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -193,11 +212,15 @@ public function store() {}
* summary="모델 상세",
* description="단일 모델을 조회합니다. (versions 포함 가능)",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="조회 성공", @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/DesignModel"))
* })),
*
* @OA\Response(response=404, description="없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -209,10 +232,14 @@ public function show() {}
* tags={"Model"},
* summary="모델 수정",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(
*
* @OA\Property(property="code", type="string", maxLength=100, example="KSS01"),
* @OA\Property(property="name", type="string", maxLength=200, example="KSS 표준 모델(개정)"),
* @OA\Property(property="category_id", type="integer", nullable=true, example=12),
@@ -221,6 +248,7 @@ public function show() {}
* @OA\Property(property="is_active", type="boolean", example=true)
* )
* ),
*
* @OA\Response(response=200, description="수정 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")) ,
* @OA\Response(response=404, description="없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -233,7 +261,9 @@ public function update() {}
* tags={"Model"},
* summary="모델 삭제(soft)",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=404, description="없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -252,13 +282,18 @@ class ModelVersionApi
* tags={"ModelVersion"},
* summary="모델의 버전 목록",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="modelId", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/ModelVersion")))
* })
* ),
*
* @OA\Response(response=404, description="없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -271,22 +306,30 @@ public function listVersions() {}
* summary="버전 DRAFT 생성",
* description="version_no 미지정 시 자동 증가",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="modelId", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(
* required=false,
*
* @OA\JsonContent(
*
* @OA\Property(property="version_no", type="integer", nullable=true, example=1),
* @OA\Property(property="notes", type="string", nullable=true, example="초안 메모"),
* @OA\Property(property="effective_from", type="string", format="date-time", nullable=true),
* @OA\Property(property="effective_to", type="string", format="date-time", nullable=true)
* )
* ),
*
* @OA\Response(response=200, description="생성 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ModelVersion"))
* })
* ),
*
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -298,13 +341,18 @@ public function createDraft() {}
* tags={"ModelVersion"},
* summary="버전 RELEASED 전환",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="versionId", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="전환 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ModelVersion"))
* })
* ),
*
* @OA\Response(response=409, description="상태 충돌", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -323,13 +371,18 @@ class BomTemplateApi
* tags={"BomTemplate"},
* summary="모델버전의 BOM 템플릿 목록",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="versionId", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/BomTemplate")))
* })
* ),
*
* @OA\Response(response=404, description="없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -342,21 +395,29 @@ public function listByVersion() {}
* summary="BOM 템플릿 upsert (name 기준)",
* description="is_primary=true 지정 시 동일 모델버전의 기존 대표 템플릿은 자동 해제",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="versionId", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(
* required=false,
*
* @OA\JsonContent(
*
* @OA\Property(property="name", type="string", maxLength=100, example="Main"),
* @OA\Property(property="is_primary", type="boolean", example=true),
* @OA\Property(property="notes", type="string", nullable=true, example="표준 템플릿")
* )
* ),
*
* @OA\Response(response=200, description="저장 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/BomTemplate"))
* })
* ),
*
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -368,13 +429,18 @@ public function upsertTemplate() {}
* tags={"BomTemplate"},
* summary="BOM 템플릿 상세 (항목 포함)",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="templateId", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/BomTemplate"))
* })
* ),
*
* @OA\Response(response=404, description="없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -387,8 +453,11 @@ public function show() {}
* summary="BOM 항목 일괄 치환",
* description="기존 항목을 모두 삭제 후 본문 items로 재삽입",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="templateId", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/BomTemplateItemReplaceRequest")),
*
* @OA\Response(response=200, description="저장 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )

View File

@@ -22,6 +22,7 @@ class FieldProfileApi
* type="object",
* description="전역정의 + 테넌트설정이 merge된 필드 효과값",
* required={"field_key","label","data_type","input_type","enabled"},
*
* @OA\Property(property="field_key", type="string", example="position"),
* @OA\Property(property="label", type="string", example="직급"),
* @OA\Property(property="data_type", type="string", example="string"),
@@ -41,6 +42,7 @@ class FieldProfileApi
* @OA\Schema(
* schema="FieldSettingUpdateRequest",
* type="object",
*
* @OA\Property(property="enabled", type="boolean", example=true),
* @OA\Property(property="required", type="boolean", example=false),
* @OA\Property(property="sort_order", type="integer", example=20),
@@ -52,6 +54,7 @@ class FieldProfileApi
* schema="FieldSettingBulkItem",
* type="object",
* required={"field_key"},
*
* @OA\Property(property="field_key", type="string", example="position"),
* @OA\Property(property="enabled", type="boolean", example=true),
* @OA\Property(property="required", type="boolean", example=false),
@@ -59,13 +62,16 @@ class FieldProfileApi
* @OA\Property(property="option_group_id", type="integer", nullable=true, example=5),
* @OA\Property(property="code_group", type="string", nullable=true, example="employment_type")
* )
*
* @OA\Schema(
* schema="FieldSettingBulkRequest",
* type="object",
* required={"items"},
*
* @OA\Property(
* property="items",
* type="array",
*
* @OA\Items(ref="#/components/schemas/FieldSettingBulkItem")
* )
* )
@@ -79,23 +85,28 @@ public function _fieldSchemasNoop() {}
* schema="OptionGroup",
* type="object",
* required={"id","group_key","name"},
*
* @OA\Property(property="id", type="integer", example=3),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="group_key", type="string", example="position"),
* @OA\Property(property="name", type="string", example="직급표(2025)"),
* @OA\Property(property="description", type="string", nullable=true, example="본사 기준")
* )
*
* @OA\Schema(
* schema="OptionGroupCreateRequest",
* type="object",
* required={"group_key","name"},
*
* @OA\Property(property="group_key", type="string", example="job_title"),
* @OA\Property(property="name", type="string", example="직책"),
* @OA\Property(property="description", type="string", nullable=true, example="영업조직용")
* )
*
* @OA\Schema(
* schema="OptionGroupUpdateRequest",
* type="object",
*
* @OA\Property(property="group_key", type="string", example="job_title"),
* @OA\Property(property="name", type="string", example="직책(개정)"),
* @OA\Property(property="description", type="string", nullable=true, example="영업/CS 통합")
@@ -105,6 +116,7 @@ public function _fieldSchemasNoop() {}
* schema="OptionValue",
* type="object",
* required={"id","group_id","value_key","value_label"},
*
* @OA\Property(property="id", type="integer", example=10),
* @OA\Property(property="group_id", type="integer", example=3),
* @OA\Property(property="value_key", type="string", example="manager"),
@@ -112,34 +124,42 @@ public function _fieldSchemasNoop() {}
* @OA\Property(property="sort_order", type="integer", example=30),
* @OA\Property(property="is_active", type="boolean", example=true)
* )
*
* @OA\Schema(
* schema="OptionValueCreateRequest",
* type="object",
* required={"value_key","value_label"},
*
* @OA\Property(property="value_key", type="string", example="director"),
* @OA\Property(property="value_label", type="string", example="이사"),
* @OA\Property(property="sort_order", type="integer", example=40),
* @OA\Property(property="is_active", type="boolean", example=true)
* )
*
* @OA\Schema(
* schema="OptionValueUpdateRequest",
* type="object",
*
* @OA\Property(property="value_key", type="string", example="director"),
* @OA\Property(property="value_label", type="string", example="이사"),
* @OA\Property(property="sort_order", type="integer", example=45),
* @OA\Property(property="is_active", type="boolean", example=false)
* )
*
* @OA\Schema(
* schema="OptionValueReorderRequest",
* type="object",
* required={"items"},
*
* @OA\Property(
* property="items",
* type="array",
* description="정렬 대상 목록",
*
* @OA\Items(
* type="object",
* required={"id","sort_order"},
*
* @OA\Property(property="id", type="integer", example=10),
* @OA\Property(property="sort_order", type="integer", example=100)
* )
@@ -156,6 +176,7 @@ public function _optionSchemasNoop() {}
* type="object",
* description="테넌트별 사용자 프로필",
* required={"tenant_id","user_id"},
*
* @OA\Property(property="id", type="integer", example=101),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="user_id", type="integer", example=55),
@@ -170,6 +191,7 @@ public function _optionSchemasNoop() {}
* @OA\Property(property="json_extra", type="object", nullable=true,
* example={"employee_no":"A-001","entry_date":"2023-01-02","work_type":"hybrid"})
* )
*
* @OA\Schema(
* schema="ProfileUpdateRequest",
* type="object",
@@ -185,6 +207,7 @@ public function _optionSchemasNoop() {}
* schema="ProfilePagination",
* type="object",
* description="LengthAwarePaginator 구조",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/Profile")),
* @OA\Property(property="total", type="integer", example=3),
@@ -205,16 +228,21 @@ public function _profileSchemasNoop() {}
* description="전역 필드 정의와 테넌트 설정을 병합한, 실제 화면 노출용(Enabled) 필드 목록을 반환합니다.",
* tags={"Tenant.Fields"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Response(
* response=200,
* description="성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="array",
*
* @OA\Items(ref="#/components/schemas/FieldEffective")
* ))
* })
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=500, description="서버 에러", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
@@ -229,15 +257,20 @@ public function fieldsIndex() {}
* description="여러 필드에 대해 enabled/required/sort_order/option_group_id/code_group 설정을 한번에 저장합니다.",
* tags={"Tenant.Fields"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/FieldSettingBulkRequest")),
*
* @OA\Response(
* response=200,
* description="저장 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="object", example={"updated":true}))
* })
* ),
*
* @OA\Response(response=400, description="유효성 오류", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -253,19 +286,25 @@ public function fieldsBulk() {}
* description="특정 field_key에 대한 테넌트 설정을 수정합니다.",
* tags={"Tenant.Fields"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(
* name="key", in="path", required=true,
* description="수정할 필드 키", @OA\Schema(type="string", example="position")
* ),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/FieldSettingUpdateRequest")),
*
* @OA\Response(
* response=200,
* description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/FieldEffective"))
* })
* ),
*
* @OA\Response(response=400, description="유효성 오류", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -282,21 +321,27 @@ public function fieldsUpdateOne() {}
* description="해당 테넌트의 옵션 그룹 목록을 페이징으로 반환합니다.",
* tags={"Tenant.Option Groups"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
* @OA\Parameter(name="q", in="query", required=false, description="검색어(그룹키/이름)", @OA\Schema(type="string", example="position")),
*
* @OA\Response(
* response=200,
* description="성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="object",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/OptionGroup")),
* @OA\Property(property="total", type="integer", example=3)
* ))
* })
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -309,9 +354,13 @@ public function optGroupsIndex() {}
* description="옵션 그룹을 생성합니다.",
* tags={"Tenant.Option Groups"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/OptionGroupCreateRequest")),
*
* @OA\Response(response=200, description="생성 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/OptionGroup"))
* })
@@ -326,9 +375,13 @@ public function optGroupsStore() {}
* summary="옵션 그룹 단건 조회",
* tags={"Tenant.Option Groups"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=3)),
*
* @OA\Response(response=200, description="성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/OptionGroup"))
* })
@@ -343,10 +396,15 @@ public function optGroupsShow() {}
* summary="옵션 그룹 수정",
* tags={"Tenant.Option Groups"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=3)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/OptionGroupUpdateRequest")),
*
* @OA\Response(response=200, description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/OptionGroup"))
* })
@@ -361,9 +419,13 @@ public function optGroupsUpdate() {}
* summary="옵션 그룹 삭제",
* tags={"Tenant.Option Groups"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=3)),
*
* @OA\Response(response=200, description="삭제 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="object", nullable=true, example=null))
* })
@@ -378,10 +440,14 @@ public function optGroupsDestroy() {}
* summary="옵션 값 목록",
* tags={"Tenant.Option Values"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="gid", in="path", required=true, @OA\Schema(type="integer", example=3)),
* @OA\Parameter(name="active_only", in="query", required=false, @OA\Schema(type="boolean", example=true)),
*
* @OA\Response(response=200, description="성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/OptionValue")))
* })
@@ -396,10 +462,15 @@ public function optionValuesIndex() {}
* summary="옵션 값 생성",
* tags={"Tenant.Option Values"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="gid", in="path", required=true, @OA\Schema(type="integer", example=3)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/OptionValueCreateRequest")),
*
* @OA\Response(response=200, description="생성 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/OptionValue"))
* })
@@ -414,10 +485,14 @@ public function optionValuesStore() {}
* summary="옵션 값 단건 조회",
* tags={"Tenant.Option Values"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="gid", in="path", required=true, @OA\Schema(type="integer", example=3)),
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=10)),
*
* @OA\Response(response=200, description="성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/OptionValue"))
* })
@@ -432,11 +507,16 @@ public function optionValuesShow() {}
* summary="옵션 값 수정",
* tags={"Tenant.Option Values"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="gid", in="path", required=true, @OA\Schema(type="integer", example=3)),
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=10)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/OptionValueUpdateRequest")),
*
* @OA\Response(response=200, description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/OptionValue"))
* })
@@ -451,10 +531,14 @@ public function optionValuesUpdate() {}
* summary="옵션 값 삭제",
* tags={"Tenant.Option Values"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="gid", in="path", required=true, @OA\Schema(type="integer", example=3)),
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=10)),
*
* @OA\Response(response=200, description="삭제 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="object", nullable=true, example=null))
* })
@@ -469,10 +553,15 @@ public function optionValuesDestroy() {}
* summary="옵션 값 정렬 순서 일괄 변경",
* tags={"Tenant.Option Values"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="gid", in="path", required=true, @OA\Schema(type="integer", example=3)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/OptionValueReorderRequest")),
*
* @OA\Response(response=200, description="변경 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="object", example={"reordered":true}))
* })
@@ -488,11 +577,15 @@ public function optionValuesReorder() {}
* description="테넌트 내 회원 프로필 목록을 페이징으로 반환합니다.",
* tags={"Tenant.Profiles"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
* @OA\Parameter(name="q", in="query", required=false, description="검색어(표기명/사번 등)", @OA\Schema(type="string", example="A-001")),
*
* @OA\Response(response=200, description="성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ProfilePagination"))
* })
@@ -507,9 +600,13 @@ public function profilesIndex() {}
* summary="프로필 단건 조회",
* tags={"Tenant.Profiles"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="userId", in="path", required=true, @OA\Schema(type="integer", example=55)),
*
* @OA\Response(response=200, description="성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Profile"))
* })
@@ -525,10 +622,15 @@ public function profilesShow() {}
* description="관리자 권한으로 해당 사용자의 프로필을 수정합니다. 테넌트에서 enabled된 필드만 반영됩니다.",
* tags={"Tenant.Profiles"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="userId", in="path", required=true, @OA\Schema(type="integer", example=55)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ProfileUpdateRequest")),
*
* @OA\Response(response=200, description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Profile"))
* })
@@ -543,8 +645,11 @@ public function profilesUpdate() {}
* summary="내 프로필 조회",
* tags={"Tenant.Profiles"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Response(response=200, description="성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Profile"))
* })
@@ -559,9 +664,13 @@ public function profilesMe() {}
* summary="내 프로필 수정",
* tags={"Tenant.Profiles"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ProfileUpdateRequest")),
*
* @OA\Response(response=200, description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Profile"))
* })

View File

@@ -2,5 +2,4 @@
namespace App\Swagger\v1;
class FileApi {}
class FileApi {}

View File

@@ -17,6 +17,7 @@
* schema="MaterialAttribute",
* type="object",
* description="규격 정보 한 항목",
*
* @OA\Property(property="label", type="string", example="두께"),
* @OA\Property(property="value", type="string", example="10"),
* @OA\Property(property="unit", type="string", example="T")
@@ -27,6 +28,7 @@
* type="object",
* description="자재 상세",
* required={"id","tenant_id","name","item_name","unit"},
*
* @OA\Property(property="id", type="integer", example=101),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="category_id", type="integer", nullable=true, example=3),
@@ -42,8 +44,10 @@
* property="attributes",
* type="array",
* nullable=true,
*
* @OA\Items(ref="#/components/schemas/MaterialAttribute")
* ),
*
* @OA\Property(
* property="options",
* type="object",
@@ -61,6 +65,7 @@
* type="object",
* description="자재 요약",
* required={"id","name","item_name","unit"},
*
* @OA\Property(property="id", type="integer", example=101),
* @OA\Property(property="category_id", type="integer", nullable=true, example=3),
* @OA\Property(property="name", type="string", example="철판"),
@@ -71,12 +76,14 @@
* @OA\Schema(
* schema="MaterialList",
* type="array",
*
* @OA\Items(ref="#/components/schemas/MaterialBrief")
* )
*
* @OA\Schema(
* schema="MaterialIndexParams",
* type="object",
*
* @OA\Property(property="q", type="string", nullable=true, example="알루미늄"),
* @OA\Property(property="category", type="integer", nullable=true, example=3),
* @OA\Property(property="page", type="integer", nullable=true, example=1),
@@ -87,6 +94,7 @@
* schema="MaterialCreateRequest",
* type="object",
* required={"name","unit"},
*
* @OA\Property(property="category_id", type="integer", nullable=true, example=3),
* @OA\Property(property="name", type="string", example="철판"),
* @OA\Property(property="unit", type="string", example="EA"),
@@ -97,8 +105,10 @@
* property="attributes",
* type="array",
* nullable=true,
*
* @OA\Items(ref="#/components/schemas/MaterialAttribute")
* ),
*
* @OA\Property(
* property="options",
* type="object",
@@ -112,6 +122,7 @@
* @OA\Schema(
* schema="MaterialUpdateRequest",
* type="object",
*
* @OA\Property(property="category_id", type="integer", nullable=true, example=3),
* @OA\Property(property="name", type="string", nullable=true, example="철판(개선)"),
* @OA\Property(property="unit", type="string", nullable=true, example="KG"),
@@ -122,8 +133,10 @@
* property="attributes",
* type="array",
* nullable=true,
*
* @OA\Items(ref="#/components/schemas/MaterialAttribute")
* ),
*
* @OA\Property(
* property="options",
* type="object",
@@ -134,7 +147,6 @@
* @OA\Property(property="specification", type="string", nullable=true, example="두께 12T, 길이 180CM")
* )
*/
class MaterialApi
{
/**
@@ -144,18 +156,23 @@ class MaterialApi
* description="자재 목록을 페이징으로 반환합니다. (q로 코드/이름/태그 검색, category로 분류 필터)",
* tags={"Material"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="q", in="query", required=false, @OA\Schema(type="string"), description="검색어(이름/코드/태그 등)"),
* @OA\Parameter(name="category", in="query", required=false, @OA\Schema(type="integer"), description="카테고리 ID"),
* @OA\Parameter(name="page", in="query", required=false, @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="per_page", in="query", required=false, @OA\Schema(type="integer", example=20)),
*
* @OA\Response(
* response=200, description="자재 목록 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(
* property="data",
* type="object",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="per_page", type="integer", example=20),
* @OA\Property(property="total", type="integer", example=2),
@@ -175,16 +192,21 @@ public function index() {}
* description="자재를 등록합니다. item_name/specification은 name+attributes를 기반으로 서버에서 자동 생성됩니다.",
* tags={"Material"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/MaterialCreateRequest")),
*
* @OA\Response(
* response=200, description="자재 등록 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Material"))
* }
* )
* ),
*
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -196,16 +218,21 @@ public function store() {}
* summary="자재 단건 조회",
* tags={"Material"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=101)),
*
* @OA\Response(
* response=200, description="자재 단건 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Material"))
* }
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -218,17 +245,23 @@ public function show() {}
* description="자재를 수정합니다. name/attributes 변경 시 item_name/specification이 서버에서 재계산됩니다.",
* tags={"Material"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=101)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/MaterialUpdateRequest")),
*
* @OA\Response(
* response=200, description="자재 수정 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Material"))
* }
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -242,17 +275,23 @@ public function updatePut() {}
* description="자재의 일부 필드를 수정합니다. name/attributes 변경 시 item_name/specification이 서버에서 재계산됩니다.",
* tags={"Material"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=101)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/MaterialUpdateRequest")),
*
* @OA\Response(
* response=200, description="자재 수정 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Material"))
* }
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -266,7 +305,9 @@ public function updatePatch() {}
* description="자재를 소프트 삭제합니다.",
* tags={"Material"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=101)),
*
* @OA\Response(response=200, description="자재 삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )

View File

@@ -12,6 +12,7 @@
* type="object",
* description="메뉴 상세",
* required={"id","name"},
*
* @OA\Property(property="id", type="integer", example=12),
* @OA\Property(property="tenant_id", type="integer", nullable=true, example=1, description="null=공용"),
* @OA\Property(property="parent_id", type="integer", nullable=true, example=null),
@@ -34,6 +35,7 @@
* type="object",
* description="메뉴 요약",
* required={"id","name"},
*
* @OA\Property(property="id", type="integer", example=12),
* @OA\Property(property="parent_id", type="integer", nullable=true, example=null),
* @OA\Property(property="name", type="string", example="메뉴 관리"),
@@ -50,6 +52,7 @@
* @OA\Schema(
* schema="MenuList",
* type="array",
*
* @OA\Items(ref="#/components/schemas/MenuBrief")
* )
*
@@ -57,6 +60,7 @@
* schema="MenuCreateRequest",
* type="object",
* required={"name"},
*
* @OA\Property(property="parent_id", type="integer", nullable=true, example=null, description="상위 메뉴 ID"),
* @OA\Property(property="name", type="string", example="새 메뉴", description="메뉴명"),
* @OA\Property(property="slug", type="string", nullable=true, example="menu.new", description="권한 키로도 활용"),
@@ -72,6 +76,7 @@
* @OA\Schema(
* schema="MenuUpdateRequest",
* type="object",
*
* @OA\Property(property="parent_id", type="integer", nullable=true, example=null),
* @OA\Property(property="name", type="string", example="메뉴명 변경"),
* @OA\Property(property="slug", type="string", nullable=true, example="menu.changed"),
@@ -93,12 +98,16 @@ class MenuApi
* description="테넌트 범위 내(또는 공용) 메뉴 목록을 반환합니다. parent_id/is_active/hidden 필터 지원.",
* tags={"Menu"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="parent_id", in="query", required=false, @OA\Schema(type="integer", example=0)),
* @OA\Parameter(name="is_active", in="query", required=false, @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="hidden", in="query", required=false, @OA\Schema(type="integer", example=0)),
*
* @OA\Response(response=200, description="목록 조회 성공",
*
* @OA\JsonContent(allOf={@OA\Schema(ref="#/components/schemas/ApiResponse"), @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/MenuList"))})
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=500, description="서버 에러", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
@@ -113,10 +122,14 @@ public function index() {}
* description="ID로 메뉴 상세 정보를 조회합니다.",
* tags={"Menu"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=12)),
*
* @OA\Response(response=200, description="단건 조회 성공",
*
* @OA\JsonContent(allOf={@OA\Schema(ref="#/components/schemas/ApiResponse"), @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Menu"))})
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -132,13 +145,19 @@ public function show() {}
* description="새로운 메뉴를 등록합니다.",
* tags={"Menu"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/MenuCreateRequest")),
*
* @OA\Response(response=200, description="등록 성공",
*
* @OA\JsonContent(allOf={@OA\Schema(ref="#/components/schemas/ApiResponse"), @OA\Schema(@OA\Property(property="data", type="object", @OA\Property(property="id", type="integer", example=12)))})
* ),
*
* @OA\Response(response=400, description="파라미터 오류", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
*
* @OA\ResponsE(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
*
* @OA\Response(response=500, description="서버 에러", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -151,11 +170,16 @@ public function store() {}
* description="기존 메뉴 정보를 수정합니다(부분 수정).",
* tags={"Menu"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=12)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/MenuUpdateRequest")),
*
* @OA\Response(response=200, description="수정 성공",
*
* @OA\JsonContent(allOf={@OA\Schema(ref="#/components/schemas/ApiResponse"), @OA\Schema(@OA\Property(property="data", type="object", @OA\Property(property="id", type="integer", example=12)))})
* ),
*
* @OA\Response(response=400, description="파라미터 오류", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -172,10 +196,14 @@ public function update() {}
* description="지정한 메뉴를 소프트 삭제합니다.",
* tags={"Menu"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=12)),
*
* @OA\Response(response=200, description="삭제 성공",
*
* @OA\JsonContent(allOf={@OA\Schema(ref="#/components/schemas/ApiResponse"), @OA\Schema(@OA\Property(property="data", type="object", @OA\Property(property="id", type="integer", example=12), @OA\Property(property="deleted", type="boolean", example=true)))})
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -191,13 +219,17 @@ public function destroy() {}
* description="여러 메뉴의 sort_order를 일괄 변경합니다.",
* tags={"Menu"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="id", type="integer", example=12),
* @OA\Property(property="sort_order", type="integer", example=1)
* )
* )),
*
* @OA\Response(response=200, description="정렬 변경 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=400, description="파라미터 오류", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -214,12 +246,16 @@ public function reorder() {}
* description="is_active / hidden / is_external 중 하나 이상을 토글합니다.",
* tags={"Menu"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=12)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(type="object",
*
* @OA\Property(property="is_active", type="boolean", nullable=true, example=true),
* @OA\Property(property="hidden", type="boolean", nullable=true, example=false),
* @OA\Property(property="is_external", type="boolean", nullable=true, example=false)
* )),
*
* @OA\Response(response=200, description="토글 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=400, description="파라미터 오류", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),

View File

@@ -2,6 +2,4 @@
namespace App\Swagger\v1;
class ModelApi {}
class ModelApi {}

View File

@@ -19,6 +19,7 @@
* @OA\Schema(
* schema="MenuMatrixAction",
* type="object",
*
* @OA\Property(property="permission_id", type="integer", example=1),
* @OA\Property(property="permission_code", type="string", example="menu:16.view"),
* @OA\Property(property="guard_name", type="string", example="api"),
@@ -29,6 +30,7 @@
* @OA\Schema(
* schema="MenuMatrixNode",
* type="object",
*
* @OA\Property(property="menu_id", type="integer", example=16),
* @OA\Property(property="parent_id", type="integer", nullable=true, example=10),
* @OA\Property(property="name", type="string", example="스크린 작업"),
@@ -46,6 +48,7 @@
* @OA\Property(
* property="children",
* type="array",
*
* @OA\Items(ref="#/components/schemas/MenuMatrixNode")
* )
* )
@@ -53,19 +56,22 @@
* @OA\Schema(
* schema="MenuMatrixPayload",
* type="object",
*
* @OA\Property(
* property="actions",
* type="array",
*
* @OA\Items(type="string", example="view")
* ),
*
* @OA\Property(
* property="tree",
* type="array",
*
* @OA\Items(ref="#/components/schemas/MenuMatrixNode")
* )
* )
*/
class PermissionApi
{
/**
@@ -75,19 +81,25 @@ class PermissionApi
* description="부서 기준으로 메뉴 트리 및 액션별 권한 상태(allow/deny/none)를 반환합니다.",
* tags={"Permission"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, description="부서 ID", @OA\Schema(type="integer", example=1)),
*
* @OA\Response(
* response=200,
* description="부서 메뉴 권한 매트릭스 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", ref="#/components/schemas/MenuMatrixPayload")
* )
* }
* )
* ),
*
* @OA\Response(response=404, description="부서 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -100,19 +112,25 @@ public function deptMenuMatrix() {}
* description="스파티 기본 Role 기준으로 메뉴 트리 및 액션별 권한 상태(allow/deny/none)를 반환합니다.",
* tags={"Permission"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, description="역할 ID", @OA\Schema(type="integer", example=3)),
*
* @OA\Response(
* response=200,
* description="역할 메뉴 권한 매트릭스 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", ref="#/components/schemas/MenuMatrixPayload")
* )
* }
* )
* ),
*
* @OA\Response(response=404, description="역할 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -125,19 +143,25 @@ public function roleMenuMatrix() {}
* description="사용자 기준으로 메뉴 트리 및 액션별 권한 상태(allow/deny/none)를 반환합니다.",
* tags={"Permission"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, description="사용자 ID", @OA\Schema(type="integer", example=12)),
*
* @OA\Response(
* response=200,
* description="유저 메뉴 권한 매트릭스 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", ref="#/components/schemas/MenuMatrixPayload")
* )
* }
* )
* ),
*
* @OA\Response(response=404, description="사용자 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/

View File

@@ -9,6 +9,7 @@
* schema="PriceHistory",
* type="object",
* required={"id","item_type_code","item_id","price_type_code","price","started_at"},
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="item_type_code", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT", description="항목 유형"),
@@ -25,12 +26,15 @@
* @OA\Schema(
* schema="PriceHistoryPagination",
* type="object",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/PriceHistory")
* ),
*
* @OA\Property(property="first_page_url", type="string", example="/api/v1/pricing?page=1"),
* @OA\Property(property="from", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=3),
@@ -38,7 +42,9 @@
* @OA\Property(
* property="links",
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="url", type="string", nullable=true, example=null),
* @OA\Property(property="label", type="string", example="« Previous"),
* @OA\Property(property="active", type="boolean", example=false)
@@ -56,6 +62,7 @@
* schema="PriceUpsertRequest",
* type="object",
* required={"item_type_code","item_id","price_type_code","price","started_at"},
*
* @OA\Property(property="item_type_code", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT"),
* @OA\Property(property="item_id", type="integer", example=10),
* @OA\Property(property="price_type_code", type="string", enum={"SALE","PURCHASE"}, example="SALE"),
@@ -68,6 +75,7 @@
* @OA\Schema(
* schema="PriceQueryResult",
* type="object",
*
* @OA\Property(property="price", type="number", format="decimal", nullable=true, example=50000.00),
* @OA\Property(property="price_history_id", type="integer", nullable=true, example=1),
* @OA\Property(property="client_group_id", type="integer", nullable=true, example=1),
@@ -78,10 +86,13 @@
* schema="BulkPriceQueryRequest",
* type="object",
* required={"items"},
*
* @OA\Property(
* property="items",
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="item_type", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT"),
* @OA\Property(property="item_id", type="integer", example=10)
* )
@@ -93,10 +104,13 @@
* @OA\Schema(
* schema="BulkPriceQueryResult",
* type="object",
*
* @OA\Property(
* property="prices",
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="item_type", type="string", example="PRODUCT"),
* @OA\Property(property="item_id", type="integer", example=10),
* @OA\Property(property="price", type="number", nullable=true, example=50000.00),
@@ -115,18 +129,23 @@ class PricingApi
* tags={"Pricing"},
* summary="가격 이력 목록",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="item_type_code", in="query", @OA\Schema(type="string", enum={"PRODUCT","MATERIAL"})),
* @OA\Parameter(name="item_id", in="query", @OA\Schema(type="integer")),
* @OA\Parameter(name="price_type_code", in="query", @OA\Schema(type="string", enum={"SALE","PURCHASE"})),
* @OA\Parameter(name="client_group_id", in="query", @OA\Schema(type="integer")),
* @OA\Parameter(name="date", in="query", description="특정 날짜 기준 유효한 가격", @OA\Schema(type="string", format="date")),
* @OA\Parameter(name="size", in="query", @OA\Schema(type="integer", example=15)),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PriceHistoryPagination"))
* })
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -139,12 +158,16 @@ public function index() {}
* summary="단일 항목 가격 조회",
* description="특정 제품/자재의 현재 유효한 가격 조회",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="item_type", in="query", required=true, @OA\Schema(type="string", enum={"PRODUCT","MATERIAL"})),
* @OA\Parameter(name="item_id", in="query", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(name="client_id", in="query", @OA\Schema(type="integer"), description="고객 ID (고객 그룹별 가격 적용)"),
* @OA\Parameter(name="date", in="query", @OA\Schema(type="string", format="date"), description="기준일 (미지정시 오늘)"),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PriceQueryResult"))
* })
@@ -160,9 +183,13 @@ public function show() {}
* summary="여러 항목 일괄 가격 조회",
* description="여러 제품/자재의 가격을 한 번에 조회",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/BulkPriceQueryRequest")),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/BulkPriceQueryResult"))
* })
@@ -178,13 +205,18 @@ public function bulk() {}
* summary="가격 등록/수정",
* description="가격 이력 등록 (동일 조건 존재 시 업데이트)",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/PriceUpsertRequest")),
*
* @OA\Response(response=200, description="저장 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PriceHistory"))
* })
* ),
*
* @OA\Response(response=400, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -196,9 +228,11 @@ public function upsert() {}
* tags={"Pricing"},
* summary="가격 이력 삭제(soft)",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
public function destroy() {}
}
}

View File

@@ -12,10 +12,12 @@
* ========= 공용 스키마(이 파일에서 사용하는 것만 정의) =========
*
* 트리 노드 스키마 (재귀)
*
* @OA\Schema(
* schema="BomTreeNode",
* type="object",
* description="BOM 트리 한 노드(제품/자재 공통)",
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="type", type="string", example="PRODUCT", description="PRODUCT / MATERIAL 등"),
* @OA\Property(property="code", type="string", example="PRD-001"),
@@ -34,24 +36,29 @@
* property="children",
* type="array",
* description="자식 노드 목록(없으면 빈 배열)",
*
* @OA\Items(ref="#/components/schemas/BomTreeNode")
* )
* )
*
* BOM 카테고리 사용/추천 항목
*
* @OA\Schema(
* schema="BomCategoryStat",
* type="object",
*
* @OA\Property(property="category_id", type="integer", nullable=true, example=1),
* @OA\Property(property="category_name", type="string", example="기본"),
* @OA\Property(property="count", type="integer", example=5, description="해당 카테고리를 사용하는 BOM 항목 수(빈도)")
* )
*
* BOM 전체 교체 저장용 스키마
*
* @OA\Schema(
* schema="BomReplaceItem",
* type="object",
* required={"ref_type","ref_id","quantity"},
*
* @OA\Property(property="ref_type", type="string", enum={"MATERIAL","PRODUCT"}, example="MATERIAL", description="참조 타입"),
* @OA\Property(property="ref_id", type="integer", example=201, description="참조 ID (materials.id 또는 products.id)"),
* @OA\Property(property="quantity", type="number", format="float", example=2, description="수량(0 이상, 소수 허용)"),
@@ -62,11 +69,13 @@
* schema="BomReplaceCategory",
* type="object",
* required={"items"},
*
* @OA\Property(property="id", type="integer", nullable=true, example=1, description="프론트 임시 카테고리 ID(선택)"),
* @OA\Property(property="name", type="string", nullable=true, example="기본", description="프론트 카테고리명(선택)"),
* @OA\Property(
* property="items",
* type="array",
*
* @OA\Items(ref="#/components/schemas/BomReplaceItem")
* )
* )
@@ -75,9 +84,11 @@
* schema="BomReplaceRequest",
* type="object",
* required={"categories"},
*
* @OA\Property(
* property="categories",
* type="array",
*
* @OA\Items(ref="#/components/schemas/BomReplaceCategory")
* ),
* example={
@@ -104,6 +115,7 @@
* @OA\Schema(
* schema="BomReplaceResult",
* type="object",
*
* @OA\Property(property="deleted_count", type="integer", example=5, description="삭제된 기존 항목 수"),
* @OA\Property(property="inserted_count", type="integer", example=7, description="신규로 삽입된 항목 수")
* )
@@ -112,28 +124,35 @@ class ProductApi
{
/**
* 카테고리 목록 조회 (기존)
*
* @OA\Get(
* path="/api/v1/product/category",
* summary="제품 카테고리 목록 조회",
* description="제품 카테고리(최상위: parent_id = null) 리스트를 반환합니다.",
* tags={"Products"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Response(
* response=200,
* description="카테고리 목록 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/ProductCategory")
* )
* )
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -142,21 +161,26 @@ public function productCategoryIndex() {}
/**
* 제품 목록/검색
*
* @OA\Get(
* path="/api/v1/products",
* tags={"Products"},
* summary="제품 목록/검색",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
* @OA\Parameter(name="q", in="query", @OA\Schema(type="string"), description="코드/이름/설명 검색"),
* @OA\Parameter(name="category_id", in="query", @OA\Schema(type="integer")),
* @OA\Parameter(name="product_type", in="query", @OA\Schema(type="string", example="PRODUCT")),
* @OA\Parameter(name="active", in="query", @OA\Schema(type="integer", enum={0,1})),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/ProductPagination"))
* })
@@ -167,16 +191,21 @@ public function productsIndex() {}
/**
* 제품 생성
*
* @OA\Post(
* path="/api/v1/products",
* tags={"Products"},
* summary="제품 생성",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ProductCreateRequest")),
*
* @OA\Response(
* response=200,
* description="생성 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Product"))
* })
@@ -187,20 +216,26 @@ public function productsStore() {}
/**
* 제품 단건
*
* @OA\Get(
* path="/api/v1/products/{id}",
* tags={"Products"},
* summary="제품 단건 조회",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Product"))
* })
* ),
*
* @OA\Response(response=404, description="없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
@@ -208,17 +243,23 @@ public function productsShow() {}
/**
* 제품 수정
*
* @OA\Patch(
* path="/api/v1/products/{id}",
* tags={"Products"},
* summary="제품 수정",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/ProductUpdateRequest")),
*
* @OA\Response(
* response=200,
* description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Product"))
* })
@@ -229,12 +270,15 @@ public function productsUpdate() {}
/**
* 제품 삭제(soft)
*
* @OA\Delete(
* path="/api/v1/products/{id}",
* tags={"Products"},
* summary="제품 삭제(soft)",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -242,23 +286,31 @@ public function productsDestroy() {}
/**
* 제품 간편 검색(모달/드롭다운)
*
* @OA\Get(
* path="/api/v1/products/search",
* tags={"Products"},
* summary="제품 간편 검색",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="q", in="query", @OA\Schema(type="string")),
* @OA\Parameter(name="limit", in="query", @OA\Schema(type="integer"), description="기본 20"),
*
* @OA\Response(
* response=200,
* description="검색 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="id", type="integer", example=101),
* @OA\Property(property="code", type="string", example="PRD-001"),
* @OA\Property(property="name", type="string", example="스크린 모듈 KS001"),
@@ -276,18 +328,24 @@ public function productsSearch() {}
/**
* 제품 활성/비활성 토글
*
* @OA\Post(
* path="/api/v1/products/{id}/toggle",
* tags={"Products"},
* summary="제품 활성/비활성 토글",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="토글 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", type="object",
* @OA\Property(property="id", type="integer", example=101),
* @OA\Property(property="is_active", type="integer", example=0)
@@ -302,18 +360,24 @@ public function productsToggle() {}
/**
* BOM 항목 목록
*
* @OA\Get(
* path="/api/v1/products/{id}/bom/items",
* tags={"Products-BOM"},
* summary="BOM 항목 목록(제품+자재 병합)",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/BomItem"))
* )
* })
@@ -324,19 +388,26 @@ public function bomItemsIndex() {}
/**
* BOM 대량 업서트
*
* @OA\Post(
* path="/api/v1/products/{id}/bom/items/bulk",
* tags={"Products-BOM"},
* summary="BOM 항목 대량 업서트",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/BomItemBulkUpsertRequest")),
*
* @OA\Response(
* response=200,
* description="업서트 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", type="object",
* @OA\Property(property="created", type="integer", example=2),
* @OA\Property(property="updated", type="integer", example=3)
@@ -350,18 +421,24 @@ public function bomItemsBulk() {}
/**
* BOM 단건 수정
*
* @OA\Patch(
* path="/api/v1/products/{id}/bom/items/{item}",
* tags={"Products-BOM"},
* summary="BOM 항목 단건 수정",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(name="item", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/BomItemUpdateRequest")),
*
* @OA\Response(
* response=200,
* description="수정 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/BomItem"))
* })
@@ -372,13 +449,16 @@ public function bomItemsUpdate() {}
/**
* BOM 단건 삭제
*
* @OA\Delete(
* path="/api/v1/products/{id}/bom/items/{item}",
* tags={"Products-BOM"},
* summary="BOM 항목 단건 삭제",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
* @OA\Parameter(name="item", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(response=200, description="삭제 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -386,13 +466,17 @@ public function bomItemsDestroy() {}
/**
* BOM 정렬 변경
*
* @OA\Post(
* path="/api/v1/products/{id}/bom/items/reorder",
* tags={"Products-BOM"},
* summary="BOM 정렬 변경",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/BomReorderRequest")),
*
* @OA\Response(response=200, description="저장 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse"))
* )
*/
@@ -400,18 +484,24 @@ public function bomItemsReorder() {}
/**
* BOM 요약(건수/합계 등)
*
* @OA\Get(
* path="/api/v1/products/{id}/bom/summary",
* tags={"Products-BOM"},
* summary="BOM 요약",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="요약 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", type="object",
* @OA\Property(property="count", type="integer", example=5),
* @OA\Property(property="count_product", type="integer", example=2),
@@ -427,22 +517,30 @@ public function bomSummary() {}
/**
* BOM 유효성 검사
*
* @OA\Get(
* path="/api/v1/products/{id}/bom/validate",
* tags={"Products-BOM"},
* summary="BOM 유효성 검사",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
*
* @OA\Response(
* response=200,
* description="검증 결과",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", type="object",
* @OA\Property(property="valid", type="boolean", example=false),
* @OA\Property(property="errors", type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="id", type="integer", example=11),
* @OA\Property(property="error", type="string", example="DUPLICATE_ITEM")
* )
@@ -458,33 +556,42 @@ public function bomValidate() {}
/**
* BOM 전체 교체 저장
* 프론트에서 보낸 현재 BOM 상태로 기존 구성을 모두 삭제 후 재등록합니다.
*
* @OA\Post(
* path="/api/v1/products/{id}/bom",
* tags={"Products-BOM"},
* summary="BOM 구성 저장(구성 전체 교체)",
* description="기존 BOM을 모두 삭제하고, 전달된 categories/items 기준으로 다시 저장합니다.",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="상위(모델) 제품 ID",
*
* @OA\Schema(type="integer", example=123)
* ),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/BomReplaceRequest")),
*
* @OA\Response(
* response=200,
* description="저장 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="message", type="string", example="BOM 항목이 저장되었습니다."),
* @OA\Property(property="data", ref="#/components/schemas/BomReplaceResult")
* )
* }
* )
* ),
*
* @OA\Response(response=400, description="잘못된 요청", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -497,29 +604,37 @@ public function bomReplace() {}
/**
* 제품별 사용 중인 BOM 카테고리 목록
*
* @OA\Get(
* path="/api/v1/products/{id}/bom/categories",
* tags={"Products-BOM"},
* summary="해당 제품에서 사용 중인 BOM 카테고리 목록",
* description="product_components 테이블에서 해당 제품(parent_product_id)의 카테고리(id/name)를 집계하여 반환합니다.",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="상위(모델) 제품 ID",
*
* @OA\Schema(type="integer", example=123)
* ),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/BomCategoryStat")
* )
* )
@@ -534,6 +649,7 @@ public function bomReplace() {}
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -542,36 +658,46 @@ public function bomCategoriesForProduct() {}
/**
* 테넌트 전역 카테고리 추천(히스토리 기반)
*
* @OA\Get(
* path="/api/v1/products/bom/categories",
* tags={"Products-BOM"},
* summary="자주 사용된 BOM 카테고리 추천",
* description="테넌트 전체 product_components 데이터를 집계해 카테고리 사용 빈도가 높은 순으로 반환합니다. q로 부분 검색 가능합니다.",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(
* name="q",
* in="query",
* required=false,
* description="카테고리명 부분 검색",
*
* @OA\Schema(type="string", example="기")
* ),
*
* @OA\Parameter(
* name="limit",
* in="query",
* required=false,
* description="최대 항목 수(기본 20)",
*
* @OA\Schema(type="integer", example=20)
* ),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/BomCategoryStat")
* )
* )
@@ -587,6 +713,7 @@ public function bomCategoriesForProduct() {}
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
@@ -595,27 +722,34 @@ public function bomCategoriesSuggest() {}
/**
* 제품 BOM 트리 조회
*
* @OA\Get(
* path="/api/v1/products/{id}/bom/tree",
* tags={"Products-BOM"},
* summary="제품 BOM 트리 조회(재귀)",
* description="특정 제품의 하위 구성(제품/자재)을 재귀적으로 트리 형태로 반환합니다. depth로 최대 깊이를 제한합니다(기본 10).",
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", minimum=1), description="제품 ID"),
* @OA\Parameter(
* name="depth",
* in="query",
* required=false,
* description="재귀 깊이(루트=0). 기본 10",
*
* @OA\Schema(type="integer", minimum=0, maximum=50, default=10, example=5)
* ),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="object",
@@ -635,6 +769,7 @@ public function bomCategoriesSuggest() {}
* }
* )
* ),
*
* @OA\Response(response=400, description="잘못된 요청", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="대상 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),

View File

@@ -9,10 +9,12 @@ class ProductExtraSchemas
{
/**
* 제품 카테고리 스키마
*
* @OA\Schema(
* schema="ProductCategory",
* type="object",
* required={"id","code_group","code","name","is_active","sort_order"},
*
* @OA\Property(property="id", type="integer", example=4),
* @OA\Property(property="code_group", type="string", example="category"),
* @OA\Property(property="code", type="string", example="BP"),
@@ -33,10 +35,12 @@ public function _category() {}
/**
* 제품 관련 스키마들
*
* @OA\Schema(
* schema="Product",
* type="object",
* required={"id","tenant_id","code","name","category_id","product_type","is_active"},
*
* @OA\Property(property="id", type="integer", example=101),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="code", type="string", example="PRD-001"),
@@ -57,12 +61,15 @@ public function _category() {}
* schema="ProductPagination",
* type="object",
* description="라라벨 LengthAwarePaginator 구조",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/Product")
* ),
*
* @OA\Property(property="per_page", type="integer", example=20),
* @OA\Property(property="total", type="integer", example=123)
* )
@@ -71,6 +78,7 @@ public function _category() {}
* schema="ProductCreateRequest",
* type="object",
* required={"code","name","category_id","product_type"},
*
* @OA\Property(property="code", type="string", example="PRD-001"),
* @OA\Property(property="name", type="string", example="스크린 모듈 KS001"),
* @OA\Property(property="category_id", type="integer", example=7),
@@ -86,6 +94,7 @@ public function _category() {}
* @OA\Schema(
* schema="ProductUpdateRequest",
* type="object",
*
* @OA\Property(property="code", type="string", example="PRD-001"),
* @OA\Property(property="name", type="string", example="스크린 모듈 KS001"),
* @OA\Property(property="category_id", type="integer", example=7),
@@ -102,10 +111,12 @@ public function _product() {}
/**
* BOM 스키마들
*
* @OA\Schema(
* schema="BomItem",
* type="object",
* required={"id","ref_type","ref_id","quantity","sort_order"},
*
* @OA\Property(property="id", type="integer", example=11),
* @OA\Property(property="ref_type", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT"),
* @OA\Property(property="ref_id", type="integer", example=3),
@@ -121,11 +132,14 @@ public function _product() {}
* schema="BomItemBulkUpsertRequest",
* type="object",
* required={"items"},
*
* @OA\Property(
* property="items",
* type="array",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="id", type="integer", nullable=true, example=null),
* @OA\Property(property="ref_type", type="string", enum={"PRODUCT","MATERIAL"}, example="MATERIAL"),
* @OA\Property(property="ref_id", type="integer", example=5),
@@ -139,6 +153,7 @@ public function _product() {}
* @OA\Schema(
* schema="BomItemUpdateRequest",
* type="object",
*
* @OA\Property(property="ref_type", type="string", enum={"PRODUCT","MATERIAL"}, example="PRODUCT"),
* @OA\Property(property="ref_id", type="integer", example=9),
* @OA\Property(property="quantity", type="number", format="float", example=1.5000),
@@ -149,9 +164,11 @@ public function _product() {}
* @OA\Schema(
* schema="BomReorderRequest",
* type="array",
*
* @OA\Items(
* type="object",
* required={"id","sort_order"},
*
* @OA\Property(property="id", type="integer", example=11),
* @OA\Property(property="sort_order", type="integer", example=1)
* )

View File

@@ -12,6 +12,7 @@
* type="object",
* description="역할 상세",
* required={"id","name","guard_name"},
*
* @OA\Property(property="id", type="integer", example=3),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="name", type="string", example="menu-manager"),
@@ -26,6 +27,7 @@
* type="object",
* description="역할 요약",
* required={"id","name"},
*
* @OA\Property(property="id", type="integer", example=3),
* @OA\Property(property="name", type="string", example="readonly"),
* @OA\Property(property="description", type="string", nullable=true, example="읽기 전용"),
@@ -35,6 +37,7 @@
* @OA\Schema(
* schema="RoleList",
* type="array",
*
* @OA\Items(ref="#/components/schemas/RoleBrief")
* )
*
@@ -42,6 +45,7 @@
* schema="RoleCreateRequest",
* type="object",
* required={"name"},
*
* @OA\Property(property="name", type="string", example="menu-manager", description="역할명(테넌트+가드 내 고유)"),
* @OA\Property(property="description", type="string", nullable=true, example="메뉴 관리 역할")
* )
@@ -49,6 +53,7 @@
* @OA\Schema(
* schema="RoleUpdateRequest",
* type="object",
*
* @OA\Property(property="name", type="string", example="menu-admin"),
* @OA\Property(property="description", type="string", nullable=true, example="설명 변경")
* )
@@ -62,14 +67,19 @@ class RoleApi
* description="테넌트 범위 내 역할 목록을 페이징으로 반환합니다. (q로 이름/설명 검색)",
* tags={"Role"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="page", in="query", required=false, @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="size", in="query", required=false, @OA\Schema(type="integer", example=10)),
* @OA\Parameter(name="q", in="query", required=false, @OA\Schema(type="string", example="read")),
*
* @OA\Response(response=200, description="목록 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", type="object",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="per_page", type="integer", example=10),
* @OA\Property(property="total", type="integer", example=2),
@@ -78,6 +88,7 @@ class RoleApi
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=500, description="서버 에러", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
@@ -92,15 +103,20 @@ public function index() {}
* description="새로운 역할을 생성합니다.",
* tags={"Role"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/RoleCreateRequest")),
*
* @OA\Response(response=200, description="생성 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Role"))
* }
* )
* ),
*
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -116,15 +132,20 @@ public function store() {}
* description="ID로 역할 상세를 조회합니다.",
* tags={"Role"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=3)),
*
* @OA\Response(response=200, description="단건 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Role"))
* }
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -140,16 +161,22 @@ public function show() {}
* description="기존 역할 정보를 부분 수정합니다.",
* tags={"Role"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=3)),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/RoleUpdateRequest")),
*
* @OA\Response(response=200, description="수정 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Role"))
* }
* )
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -166,10 +193,14 @@ public function update() {}
* description="지정한 역할을 삭제합니다.",
* tags={"Role"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer", example=3)),
*
* @OA\Response(response=200, description="삭제 성공",
*
* @OA\JsonContent(ref="#/components/schemas/ApiResponse")
* ),
*
* @OA\Response(response=404, description="데이터 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),

View File

@@ -15,6 +15,7 @@
* type="object",
* description="퍼미션 요약",
* required={"id","name","guard_name"},
*
* @OA\Property(property="id", type="integer", example=15),
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="name", type="string", example="menu:101.view"),
@@ -26,6 +27,7 @@
* @OA\Schema(
* schema="PermissionList",
* type="array",
*
* @OA\Items(ref="#/components/schemas/PermissionBrief")
* )
*
@@ -37,11 +39,14 @@
* @OA\Schema(
* description="방법 A: 퍼미션 이름 배열",
* required={"permission_names"},
*
* @OA\Property(property="permission_names", type="array", @OA\Items(type="string"), example={"menu:101.view","menu:101.create"})
* ),
*
* @OA\Schema(
* description="방법 B: 메뉴+액션 조합",
* required={"menus","actions"},
*
* @OA\Property(property="menus", type="array", @OA\Items(type="integer"), example={101,102}),
* @OA\Property(property="actions", type="array", @OA\Items(type="string"), example={"view","create","update","delete"})
* )
@@ -56,11 +61,14 @@
* @OA\Schema(
* description="방법 A: 퍼미션 이름 배열",
* required={"permission_names"},
*
* @OA\Property(property="permission_names", type="array", @OA\Items(type="string"), example={"menu:101.view","menu:101.create"})
* ),
*
* @OA\Schema(
* description="방법 B: 메뉴+액션 조합",
* required={"menus","actions"},
*
* @OA\Property(property="menus", type="array", @OA\Items(type="integer"), example={101}),
* @OA\Property(property="actions", type="array", @OA\Items(type="string"), example={"create"})
* )
@@ -75,11 +83,14 @@
* @OA\Schema(
* description="방법 A: 퍼미션 이름 배열",
* required={"permission_names"},
*
* @OA\Property(property="permission_names", type="array", @OA\Items(type="string"), example={"menu:101.view","menu:101.update"})
* ),
*
* @OA\Schema(
* description="방법 B: 메뉴+액션 조합",
* required={"menus","actions"},
*
* @OA\Property(property="menus", type="array", @OA\Items(type="integer"), example={101,102}),
* @OA\Property(property="actions", type="array", @OA\Items(type="string"), example={"view","update"})
* )
@@ -95,15 +106,20 @@ class RolePermissionApi
* description="해당 역할에 현재 부여된 퍼미션 목록을 반환합니다.",
* tags={"RolePermission"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"), example=3),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PermissionList"))
* }
* )
* ),
*
* @OA\Response(response=404, description="역할 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -119,8 +135,11 @@ public function list() {}
* description="퍼미션 이름 배열 또는 메뉴ID+액션 조합으로 역할에 권한을 부여합니다.",
* tags={"RolePermission"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"), example=3),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/RolePermissionGrantRequest")),
*
* @OA\Response(response=200, description="부여 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=404, description="역할/퍼미션 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -138,8 +157,11 @@ public function grant() {}
* description="퍼미션 이름 배열 또는 메뉴ID+액션 조합으로 권한을 회수합니다.",
* tags={"RolePermission"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"), example=3),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/RolePermissionRevokeRequest")),
*
* @OA\Response(response=200, description="회수 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=404, description="역할/퍼미션 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -157,8 +179,11 @@ public function revoke() {}
* description="전달된 목록으로 역할의 권한을 완전히 교체합니다.",
* tags={"RolePermission"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"), example=3),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/RolePermissionSyncRequest")),
*
* @OA\Response(response=200, description="동기화 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=404, description="역할/퍼미션 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),

View File

@@ -7,6 +7,7 @@
* version="1.0.0",
* title="SAM API Documentation",
* description="===============================<br><strong>[공통 에러 응답 포맷]</strong><br>400: 필수 파라미터 누락<br>401: 인증 실패<br>403: 권한 없음<br>404: 존재하지 않는 URI 또는 데이터<br>405: 허용되지 않는 메서드<br>500: 서버 에러<br><br><strong>모든 에러 응답 예시:</strong><br>{<br>&nbsp;&nbsp;&quot;success&quot;: false,<br>&nbsp;&nbsp;&quot;message&quot;: &quot;에러 메시지&quot;,<br>&nbsp;&nbsp;&quot;data&quot;: null<br>}<br>===============================",
*
* @OA\Contact(
* email="shine1324@gmail.com"
* )
@@ -23,7 +24,6 @@
* in="header",
* name="X-API-KEY"
* )
*
* @OA\SecurityScheme(
* securityScheme="BearerAuth",
* type="http",

View File

@@ -14,6 +14,7 @@
* type="object",
* description="테넌트 상세 정보",
* required={"id","company_name"},
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="company_name", type="string", example="(주)경동기업"),
* @OA\Property(property="code", type="string", example="KDCOM"),
@@ -37,12 +38,15 @@
* schema="TenantPagination",
* type="object",
* description="라라벨 LengthAwarePaginator 기본 구조",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/TenantBrief")
* ),
*
* @OA\Property(property="first_page_url", type="string", example="/api/v1/tenants/list?page=1"),
* @OA\Property(property="from", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=1),
@@ -50,8 +54,10 @@
* @OA\Property(
* property="links",
* type="array",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="url", type="string", nullable=true, example=null),
* @OA\Property(property="label", type="string", example="&laquo; Previous"),
* @OA\Property(property="active", type="boolean", example=false)
@@ -69,6 +75,7 @@
* schema="TenantCreateRequest",
* type="object",
* required={"company_name"},
*
* @OA\Property(property="company_name", type="string", example="(주)신규기업", description="회사명"),
* @OA\Property(property="email", type="string", nullable=true, example="newcompany@example.com", description="대표 이메일"),
* @OA\Property(property="phone", type="string", nullable=true, example="01012345678", description="대표 연락처"),
@@ -80,6 +87,7 @@
* @OA\Schema(
* schema="TenantUpdateRequest",
* type="object",
*
* @OA\Property(property="tenant_id", type="integer", example=1, description="수정 대상 테넌트 ID"),
* @OA\Property(property="company_name", type="string", example="(주)신규기업", description="회사명"),
* @OA\Property(property="email", type="string", example="newcompany@example.com", description="대표 이메일"),
@@ -98,18 +106,23 @@ class TenantApi
* description="등록된 모든 테넌트 목록을 페이징 형태로 반환합니다.",
* tags={"Tenant"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
*
* @OA\Response(
* response=200,
* description="테넌트 목록 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/TenantPagination"))
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=405, description="허용되지 않는 메서드", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -125,23 +138,29 @@ public function index() {}
* description="활성(현재) 테넌트의 상세 정보를 조회합니다. 필요 시 쿼리로 특정 테넌트를 확장할 수 있습니다.",
* tags={"Tenant"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(
* name="tenant_id",
* in="query",
* required=false,
* description="조회할 테넌트 ID (없으면 활성 테넌트)",
*
* @OA\Schema(type="integer", example=1)
* ),
*
* @OA\Response(
* response=200,
* description="테넌트 정보 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Tenant"))
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="존재하지 않는 URI 또는 데이터", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -158,20 +177,26 @@ public function show() {}
* description="새로운 테넌트를 등록합니다.",
* tags={"Tenant"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/TenantCreateRequest")),
*
* @OA\Response(
* response=200,
* description="등록 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="message", type="string", example="등록 성공"),
* @OA\Property(property="data", ref="#/components/schemas/TenantBrief")
* )
* }
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -188,20 +213,26 @@ public function store() {}
* description="기존 테넌트 정보를 수정합니다.",
* tags={"Tenant"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/TenantUpdateRequest")),
*
* @OA\Response(
* response=200,
* description="수정 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="message", type="string", example="수정 성공"),
* @OA\Property(property="data", ref="#/components/schemas/TenantBrief")
* )
* }
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -219,19 +250,24 @@ public function update() {}
* description="테넌트를 삭제(또는 탈퇴 처리)합니다.",
* tags={"Tenant"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Response(
* response=200,
* description="삭제 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="message", type="string", example="삭제 성공"),
* @OA\Property(property="data", type="object", nullable=true, example=null)
* )
* }
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -249,26 +285,33 @@ public function destroy() {}
* description="삭제(소프트 삭제)된 테넌트를 복구합니다.",
* tags={"Tenant"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(
* name="tenant_id",
* in="path",
* required=true,
* description="복구할 테넌트 ID",
*
* @OA\Schema(type="integer", example=1)
* ),
*
* @OA\Response(
* response=200,
* description="복구 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="message", type="string", example="복구 성공"),
* @OA\Property(property="data", type="object", nullable=true, example=null)
* )
* }
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),

View File

@@ -7,13 +7,13 @@
* @OA\Tag(name="User", description="사용자 본인 정보/비밀번호 변경 등")
*/
/**
* @OA\Schema(
* schema="Member",
* type="object",
* description="회원 기본 정보",
* required={"id","user_id","name","email"},
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="user_id", type="string", example="hamss"),
* @OA\Property(property="phone", type="string", nullable=true, example="010-4820-9104"),
@@ -33,12 +33,15 @@
* schema="MemberPagination",
* type="object",
* description="라라벨 LengthAwarePaginator 기본 구조",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/Member")
* ),
*
* @OA\Property(property="first_page_url", type="string", example="/api/v1/users/index?page=1"),
* @OA\Property(property="from", type="integer", example=1),
* @OA\Property(property="last_page", type="integer", example=1),
@@ -46,8 +49,10 @@
* @OA\Property(
* property="links",
* type="array",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="url", type="string", nullable=true, example=null),
* @OA\Property(property="label", type="string", example="&laquo; Previous"),
* @OA\Property(property="active", type="boolean", example=false)
@@ -66,6 +71,7 @@
* type="object",
* description="간단 테넌트 정보",
* required={"id","company_name"},
*
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="company_name", type="string", example="(주)경동기업"),
* @OA\Property(property="code", type="string", example="KDCOM"),
@@ -86,13 +92,13 @@
* schema="MeResponseData",
* type="object",
* description="내 정보 + 테넌트 정보",
*
* @OA\Property(property="user", ref="#/components/schemas/Member"),
* @OA\Property(property="tenant", ref="#/components/schemas/TenantBrief")
* )
*/
class UserApi
{
/**
* @OA\Get(
* path="/api/v1/users/me",
@@ -100,16 +106,20 @@ class UserApi
* description="내 정보와 활성 테넌트 정보를 반환합니다.",
* tags={"User"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Response(
* response=200,
* description="나의 정보 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/MeResponseData"))
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패 (헤더 누락, 유효하지 않은 토큰/키 등)", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=405, description="허용되지 않는 메서드", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=500, description="서버 에러", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
@@ -124,17 +134,22 @@ public function me() {}
* summary="내 정보 수정",
* description="이름/연락처 등 프로필 정보를 수정합니다.",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/UserUpdateRequest")),
*
* @OA\Response(
* response=200,
* description="수정 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Member"))
* }
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -152,16 +167,21 @@ public function updateMe() {}
* summary="비밀번호 변경",
* description="현재 비밀번호 검증 후 새 비밀번호로 변경합니다.",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/PasswordChangeRequest")),
*
* @OA\Response(
* response=204,
* description="변경 성공(콘텐츠 없음)",
*
* @OA\JsonContent(
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="변경 성공"),
* @OA\Property(property="data", type="object", nullable=true, example=null)
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -178,17 +198,23 @@ public function changePassword() {}
* summary="내 테넌트 목록",
* description="사용자가 소속된 테넌트 목록을 반환합니다.",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(type="object",
*
* @OA\Property(property="tenant_id", type="integer", example=1),
* @OA\Property(property="tenant_name", type="string", example="경동기업"),
* @OA\Property(property="is_active", type="boolean", example=true)
@@ -198,6 +224,7 @@ public function changePassword() {}
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="존재하지 않는 URI 또는 데이터", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -214,16 +241,21 @@ public function myTenants() {}
* summary="활성 테넌트 전환",
* description="현재 세션/토큰의 활성 테넌트를 전환합니다.",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/SwitchTenantRequest")),
*
* @OA\Response(
* response=204,
* description="전환 성공(콘텐츠 없음)",
*
* @OA\JsonContent(
*
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(property="message", type="string", example="변경 성공"),
* @OA\Property(property="data", type="object", nullable=true, example=null)
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -234,7 +266,6 @@ public function myTenants() {}
*/
public function switchTenant() {}
/**
* @OA\Get(
* path="/api/v1/users/index",
@@ -242,20 +273,26 @@ public function switchTenant() {}
* description="회원 목록을 페이징 형태로 반환합니다.",
* tags={"User"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(ref="#/components/parameters/Page"),
* @OA\Parameter(ref="#/components/parameters/Size"),
*
* @OA\Response(
* response=200,
* description="회원 목록 조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(property="data", ref="#/components/schemas/MemberPagination")
* )
* }
* )
* ),
*
* @OA\Response(response=400, description="필수 파라미터 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -273,23 +310,29 @@ public function index() {}
* description="user_no 기준으로 회원 상세 정보를 조회합니다.",
* tags={"User"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(
* name="user_no",
* in="path",
* required=true,
* description="회원 번호 (USER_NO)",
*
* @OA\Schema(type="integer", example=1)
* ),
*
* @OA\Response(
* response=200,
* description="회원 상세조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/Member"))
* }
* )
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=404, description="회원 정보 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=405, description="허용되지 않는 메서드", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),

View File

@@ -17,10 +17,13 @@
* oneOf={
* @OA\Schema(
* required={"role_names"},
*
* @OA\Property(property="role_names", type="array", @OA\Items(type="string"), example={"menu-manager","readonly"})
* ),
*
* @OA\Schema(
* required={"role_ids"},
*
* @OA\Property(property="role_ids", type="array", @OA\Items(type="integer"), example={1,2})
* )
* }
@@ -33,10 +36,13 @@
* oneOf={
* @OA\Schema(
* required={"role_names"},
*
* @OA\Property(property="role_names", type="array", @OA\Items(type="string"), example={"readonly"})
* ),
*
* @OA\Schema(
* required={"role_ids"},
*
* @OA\Property(property="role_ids", type="array", @OA\Items(type="integer"), example={2})
* )
* }
@@ -49,10 +55,13 @@
* oneOf={
* @OA\Schema(
* required={"role_names"},
*
* @OA\Property(property="role_names", type="array", @OA\Items(type="string"), example={"menu-manager"})
* ),
*
* @OA\Schema(
* required={"role_ids"},
*
* @OA\Property(property="role_ids", type="array", @OA\Items(type="integer"), example={1})
* )
* }
@@ -67,23 +76,30 @@ class UserRoleApi
* description="해당 사용자에게 현재 부여된 역할 목록을 반환합니다.",
* tags={"UserRole"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"), example=1),
*
* @OA\Response(
* response=200,
* description="조회 성공",
*
* @OA\JsonContent(
* allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
*
* @OA\Property(
* property="data",
* type="array",
*
* @OA\Items(ref="#/components/schemas/RoleBrief")
* )
* )
* }
* )
* ),
*
* @OA\Response(response=404, description="사용자 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=403, description="권한 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -99,8 +115,11 @@ public function index() {}
* description="role_names 또는 role_ids로 여러 역할을 부여합니다.",
* tags={"UserRole"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"), example=1),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/UserRoleGrantRequest")),
*
* @OA\Response(response=200, description="부여 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=404, description="사용자/역할 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -118,8 +137,11 @@ public function grant() {}
* description="role_names 또는 role_ids로 여러 역할을 회수합니다.",
* tags={"UserRole"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"), example=1),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/UserRoleRevokeRequest")),
*
* @OA\Response(response=200, description="회수 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=404, description="사용자/역할 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
@@ -137,8 +159,11 @@ public function revoke() {}
* description="전달된 목록으로 사용자의 역할을 완전히 교체합니다.",
* tags={"UserRole"},
* security={{"ApiKeyAuth": {}},{"BearerAuth": {}}},
*
* @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer"), example=1),
*
* @OA\RequestBody(required=true, @OA\JsonContent(ref="#/components/schemas/UserRoleSyncRequest")),
*
* @OA\Response(response=200, description="동기화 성공", @OA\JsonContent(ref="#/components/schemas/ApiResponse")),
* @OA\Response(response=404, description="사용자/역할 없음", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),