{ "openapi": "3.0.0", "info": { "title": "SAM API Documentation", "description": "===============================
[공통 에러 응답 포맷]
400: 필수 파라미터 누락
401: 인증 실패
403: 권한 없음
404: 존재하지 않는 URI 또는 데이터
405: 허용되지 않는 메서드
500: 서버 에러

모든 에러 응답 예시:
{
  "success": false,
  "message": "에러 메시지",
  "data": null
}
===============================", "contact": { "email": "shine1324@gmail.com" }, "version": "1.0.0" }, "servers": [ { "url": "https://api.sam.kr/", "description": "SAM관리시스템 API 서버" } ], "paths": { "/api/v1/settings/common/code": { "get": { "tags": [ "Settings - Common Codes" ], "summary": "공통 코드 조회", "description": "테넌트의 활성화된 공통 코드 목록을 조회합니다.", "operationId": "4205164d87e9be4155aa6cf608826ef9", "responses": { "200": { "description": "공통 코드 조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "공통코드" }, "data": { "type": "array", "items": { "properties": { "code_group": { "type": "string", "example": "product_type" }, "code": { "type": "string", "example": "PRODUCT" }, "name": { "type": "string", "example": "제품" }, "description": { "type": "string", "example": "완제품" }, "is_active": { "type": "boolean", "example": true } }, "type": "object" } } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [] } ] } }, "/api/v1/settings/common": { "get": { "tags": [ "Settings - Common Codes" ], "summary": "공통 코드 목록 조회", "description": "전체 공통 코드 목록을 조회합니다.", "operationId": "2324e93cb41593bfee2bf826a16fc3a5", "responses": { "200": { "description": "공통 코드 목록 조회 성공" } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "post": { "tags": [ "Settings - Common Codes" ], "summary": "공통 코드 생성", "description": "새로운 공통 코드를 생성합니다.", "operationId": "0f6adf3ff82182588cc4ab4e395bd050", "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "code_group": { "type": "string", "example": "product_type" }, "code": { "type": "string", "example": "SERVICE" }, "name": { "type": "string", "example": "서비스" }, "description": { "type": "string", "example": "서비스 상품" } }, "type": "object" } } } }, "responses": { "201": { "description": "공통 코드 생성 성공" }, "409": { "description": "중복된 공통 코드", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": false }, "message": { "type": "string", "example": "중복된 공통 코드가 존재합니다." } }, "type": "object" } } } }, "422": { "description": "유효성 검사 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/settings/common/{group}": { "get": { "tags": [ "Settings - Common Codes" ], "summary": "특정 그룹 공통 코드 조회", "description": "특정 그룹의 공통 코드 목록을 조회합니다.", "operationId": "87517fb45245479599c34ea974aa186b", "parameters": [ { "name": "group", "in": "path", "description": "코드 그룹", "required": true, "schema": { "type": "string", "example": "product_type" } } ], "responses": { "200": { "description": "그룹 코드 조회 성공" } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/settings/common/{id}": { "delete": { "tags": [ "Settings - Common Codes" ], "summary": "공통 코드 삭제", "description": "공통 코드를 삭제합니다.", "operationId": "1b5c16e83858e6813e4a1a40804216da", "parameters": [ { "name": "id", "in": "path", "description": "공통 코드 ID", "required": true, "schema": { "type": "integer", "example": 1 } } ], "responses": { "200": { "description": "공통 코드 삭제 성공" }, "404": { "description": "공통 코드를 찾을 수 없음", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": false }, "message": { "type": "string", "example": "해당 공통 코드를 찾을 수 없습니다." } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "patch": { "tags": [ "Settings - Common Codes" ], "summary": "공통 코드 수정", "description": "기존 공통 코드를 수정합니다.", "operationId": "f418818d943ba3452ce22e47826c1b2b", "parameters": [ { "name": "id", "in": "path", "description": "공통 코드 ID", "required": true, "schema": { "type": "integer", "example": 1 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "name": { "type": "string", "example": "수정된 이름" }, "description": { "type": "string", "example": "수정된 설명" } }, "type": "object" } } } }, "responses": { "200": { "description": "공통 코드 수정 성공" }, "404": { "description": "공통 코드를 찾을 수 없음", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": false }, "message": { "type": "string", "example": "해당 공통 코드를 찾을 수 없습니다." } }, "type": "object" } } } }, "422": { "description": "유효성 검사 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/v1/estimates": { "get": { "tags": [ "Estimate" ], "summary": "견적 목록 조회", "operationId": "8412588a3df425607550f5cd370aa36d", "parameters": [ { "name": "status", "in": "query", "description": "견적 상태", "schema": { "type": "string" } }, { "name": "customer_name", "in": "query", "description": "고객명", "schema": { "type": "string" } }, { "name": "model_set_id", "in": "query", "description": "모델셋 ID", "schema": { "type": "integer" } }, { "name": "date_from", "in": "query", "description": "시작일", "schema": { "type": "string", "format": "date" } }, { "name": "date_to", "in": "query", "description": "종료일", "schema": { "type": "string", "format": "date" } }, { "name": "search", "in": "query", "description": "검색어", "schema": { "type": "string" } }, { "name": "per_page", "in": "query", "description": "페이지당 항목수", "schema": { "type": "integer", "default": 20 } } ], "responses": { "200": { "description": "성공" } }, "security": [ { "bearerAuth": [] } ] }, "post": { "tags": [ "Estimate" ], "summary": "견적 생성", "operationId": "ba5dec9c54377af493a04df25c2446de", "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "model_set_id", "estimate_name", "parameters" ], "properties": { "model_set_id": { "description": "모델셋 ID", "type": "integer" }, "estimate_name": { "description": "견적명", "type": "string" }, "customer_name": { "description": "고객명", "type": "string" }, "project_name": { "description": "프로젝트명", "type": "string" }, "parameters": { "description": "견적 파라미터", "type": "object" }, "notes": { "description": "비고", "type": "string" } }, "type": "object" } } } }, "responses": { "201": { "description": "생성 성공" } }, "security": [ { "bearerAuth": [] } ] } }, "/v1/estimates/{id}": { "get": { "tags": [ "Estimate" ], "summary": "견적 상세 조회", "operationId": "6e07ef9e2de196f4bfd65bceec60181b", "parameters": [ { "name": "id", "in": "path", "description": "견적 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "성공" } }, "security": [ { "bearerAuth": [] } ] }, "put": { "tags": [ "Estimate" ], "summary": "견적 수정", "operationId": "0cc7fbdcea9aa9d7885897aebc3abf23", "parameters": [ { "name": "id", "in": "path", "description": "견적 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "estimate_name": { "description": "견적명", "type": "string" }, "customer_name": { "description": "고객명", "type": "string" }, "project_name": { "description": "프로젝트명", "type": "string" }, "parameters": { "description": "견적 파라미터", "type": "object" }, "status": { "description": "견적 상태", "type": "string" }, "notes": { "description": "비고", "type": "string" } }, "type": "object" } } } }, "responses": { "200": { "description": "수정 성공" } }, "security": [ { "bearerAuth": [] } ] }, "delete": { "tags": [ "Estimate" ], "summary": "견적 삭제", "operationId": "374fb222f46f23bf1831c5c0369b5cb7", "parameters": [ { "name": "id", "in": "path", "description": "견적 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공" } }, "security": [ { "bearerAuth": [] } ] } }, "/v1/estimates/{id}/clone": { "post": { "tags": [ "Estimate" ], "summary": "견적 복제", "operationId": "6b45e9f8aca02e3d0640b4b2106d6083", "parameters": [ { "name": "id", "in": "path", "description": "견적 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "estimate_name" ], "properties": { "estimate_name": { "description": "새 견적명", "type": "string" }, "customer_name": { "description": "고객명", "type": "string" }, "project_name": { "description": "프로젝트명", "type": "string" }, "notes": { "description": "비고", "type": "string" } }, "type": "object" } } } }, "responses": { "201": { "description": "복제 성공" } }, "security": [ { "bearerAuth": [] } ] } }, "/v1/estimates/{id}/status": { "put": { "tags": [ "Estimate" ], "summary": "견적 상태 변경", "operationId": "e1129be4464b09e17a017bdea0fc034c", "parameters": [ { "name": "id", "in": "path", "description": "견적 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "status" ], "properties": { "status": { "description": "변경할 상태", "type": "string", "enum": [ "DRAFT", "SENT", "APPROVED", "REJECTED", "EXPIRED" ] }, "notes": { "description": "상태 변경 사유", "type": "string" } }, "type": "object" } } } }, "responses": { "200": { "description": "상태 변경 성공" } }, "security": [ { "bearerAuth": [] } ] } }, "/v1/estimates/form-schema/{model_set_id}": { "get": { "tags": [ "Estimate" ], "summary": "견적 폼 스키마 조회", "operationId": "1b29bcbc12f07588e6049c0bb1afaa4f", "parameters": [ { "name": "model_set_id", "in": "path", "description": "모델셋 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "성공" } }, "security": [ { "bearerAuth": [] } ] } }, "/v1/estimates/preview/{model_set_id}": { "post": { "tags": [ "Estimate" ], "summary": "견적 계산 미리보기", "operationId": "f34539b3cf81af8c8286b3f561ef8a70", "parameters": [ { "name": "model_set_id", "in": "path", "description": "모델셋 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "parameters" ], "properties": { "parameters": { "description": "견적 파라미터", "type": "object" } }, "type": "object" } } } }, "responses": { "200": { "description": "계산 성공" } }, "security": [ { "bearerAuth": [] } ] } }, "/api/v1/settings/fields": { "get": { "tags": [ "Settings - Fields" ], "summary": "테넌트 필드 설정 목록 조회", "description": "전역 + 테넌트별 병합된 필드 설정 효과값을 조회합니다.", "operationId": "c1f268831086f9cf0a5a0b05d02605ef", "responses": { "200": { "description": "필드 설정 목록 조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "조회 성공" }, "data": { "type": "array", "items": { "properties": { "field_key": { "type": "string", "example": "product_name_required" }, "field_value": { "type": "string", "example": "true" }, "source": { "description": "global 또는 tenant", "type": "string", "example": "tenant" } }, "type": "object" } } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/settings/fields/bulk": { "put": { "tags": [ "Settings - Fields" ], "summary": "테넌트 필드 설정 대량 저장", "description": "여러 필드 설정을 트랜잭션으로 일괄 저장합니다.", "operationId": "d5f333b7fb766211df283221bc1ca805", "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "fields": { "type": "array", "items": { "properties": { "field_key": { "type": "string", "example": "product_name_required" }, "field_value": { "type": "string", "example": "true" } }, "type": "object" } } }, "type": "object" } } } }, "responses": { "200": { "description": "대량 저장 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "400": { "description": "유효하지 않은 필드 타입", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": false }, "message": { "type": "string", "example": "유효하지 않은 필드 타입입니다." } }, "type": "object" } } } }, "422": { "description": "유효성 검사 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/settings/fields/{key}": { "patch": { "tags": [ "Settings - Fields" ], "summary": "테넌트 필드 설정 단건 수정", "description": "특정 필드 설정을 개별적으로 수정합니다.", "operationId": "c8ab674cac205e62f9c54d06f041bd00", "parameters": [ { "name": "key", "in": "path", "description": "필드 키", "required": true, "schema": { "type": "string", "example": "product_name_required" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "field_value": { "type": "string", "example": "false" } }, "type": "object" } } } }, "responses": { "200": { "description": "필드 설정 수정 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "필드 설정을 찾을 수 없음", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": false }, "message": { "type": "string", "example": "해당 필드 설정을 찾을 수 없습니다." } }, "type": "object" } } } }, "400": { "description": "유효하지 않은 필드 타입", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": false }, "message": { "type": "string", "example": "유효하지 않은 필드 타입입니다." } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/admin/users": { "get": { "tags": [ "Admin-Users" ], "summary": "사용자 목록", "description": "필터/검색/페이지네이션으로 사용자 목록을 조회합니다.", "operationId": "1b7ae16b7a3e0031934d842f83155133", "parameters": [ { "name": "q", "in": "query", "description": "이름/이메일 검색어", "schema": { "type": "string" } }, { "name": "tenant_id", "in": "query", "description": "특정 테넌트로 필터", "schema": { "type": "integer", "example": 1 } }, { "name": "role", "in": "query", "description": "역할 코드", "schema": { "type": "string", "example": "manager" } }, { "name": "is_active", "in": "query", "description": "활성여부", "schema": { "type": "boolean", "example": 1 } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/User" } }, "first_page_url": { "type": "string", "example": "/api/v1/admin/users?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 3 }, "last_page_url": { "type": "string", "example": "/api/v1/admin/users?page=3" }, "next_page_url": { "type": "string", "example": "/api/v1/admin/users?page=2", "nullable": true }, "path": { "type": "string", "example": "/api/v1/admin/users" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 50 } }, "type": "object" } }, "type": "object" } ] } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Admin-Users" ], "summary": "사용자 생성", "description": "새 사용자를 생성합니다. (초기 비밀번호/역할 포함 가능)", "operationId": "63469d8cf97c626b541f2c171ed516ad", "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "name", "email", "password" ], "properties": { "user_id": { "type": "string", "example": "test001" }, "name": { "type": "string", "example": "김관리" }, "email": { "type": "string", "example": "admin@kdcorp.co.kr" }, "password": { "type": "string", "example": "Init!2345" }, "phone": { "type": "string", "example": "010-3333-4444" }, "roles": { "type": "array", "items": { "type": "string" }, "example": [ "manager" ] } }, "type": "object" } } } }, "responses": { "201": { "description": "생성됨", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/User" } }, "type": "object" } ] } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "이메일 중복", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/admin/users/{id}": { "get": { "tags": [ "Admin-Users" ], "summary": "사용자 단건 조회", "description": "ID 기준 사용자 상세", "operationId": "82122febae83557b8327464f8223f085", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 101 } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Admin-Users" ], "summary": "사용자 수정", "description": "이름/연락처/역할/활성여부 등 변경", "operationId": "6558323c5811b3b7c97fd7b20cf8e4f6", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "name": { "type": "string", "example": "김관리" }, "phone": { "type": "string", "example": "010-3333-4444" }, "is_active": { "type": "integer", "example": 1 }, "roles": { "type": "array", "items": { "type": "string" }, "example": [ "manager", "staff" ] } }, "type": "object" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Admin-Users" ], "summary": "사용자 삭제(소프트 삭제)", "description": "deleted_at / deleted_by 기록", "operationId": "559b8bf227a1156fcd1ef4656fa7c6df", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "204": { "description": "삭제성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "변경 성공" }, "data": { "type": "string", "example": "Success" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/admin/users/{id}/status": { "patch": { "tags": [ "Admin-Users" ], "summary": "활성/비활성 전환", "description": "지정된 사용자의 is_active 상태를 변경합니다.", "operationId": "7da65b864daadca1481fa87d0f99930d", "parameters": [ { "name": "id", "in": "path", "description": "사용자 고유 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "변경 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "테넌트 사용자 활성/비활성 성공" }, "data": { "properties": { "is_active": { "type": "integer", "example": 1 } }, "type": "object" } }, "type": "object" } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/admin/users/{id}/restore": { "post": { "tags": [ "Admin-Users" ], "summary": "삭제 복구", "description": "소프트 삭제 복구", "operationId": "78f17d71e4bbd8c78cf51f267fa8f254", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "204": { "description": "삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "변경 성공" }, "data": { "type": "string", "example": "Success" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/admin/users/{id}/roles": { "post": { "tags": [ "Admin-Users" ], "summary": "역할 부여", "description": "사용자에게 역할 추가", "operationId": "be504b509f9d3a4daae50007ddef915f", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "roles" ], "properties": { "roles": { "type": "array", "items": { "type": "string" }, "example": [ "manager" ] } }, "type": "object" } } } }, "responses": { "204": { "description": "부여 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "변경 성공" }, "data": { "type": "object", "example": null, "nullable": true } }, "type": "object" } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "이메일/역할 중복 등 충돌", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/admin/users/{id}/roles/{role}": { "delete": { "tags": [ "Admin-Users" ], "summary": "역할 해제", "description": "사용자에서 특정 역할 제거", "operationId": "4d9980bcd4442c9e8f175083a15d4f62", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "role", "in": "path", "required": true, "schema": { "type": "string", "example": "manager" } } ], "responses": { "204": { "description": "부여 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "변경 성공" }, "data": { "type": "object", "example": null, "nullable": true } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "요청 충돌(없는 역할/이미 제거됨 등)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/admin/users/{id}/reset-password": { "post": { "tags": [ "Admin-Users" ], "summary": "비밀번호 초기화", "description": "지정된 사용자의 비밀번호를 새 임시 비밀번호로 초기화합니다.\n * - 관리자 권한 확인은 미들웨어/가드에서 처리됩니다.\n * - 기본적으로 응답에 비밀번호를 노출하지 않으며, return_password=1일 때만 임시 비밀번호를 반환합니다(운영 환경에서는 노출 비권장).", "operationId": "bb7097f56a0ea290614a78e9e32c7701", "parameters": [ { "name": "id", "in": "path", "description": "사용자 고유 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "properties": { "new_password": { "description": "지정 시 해당 값으로 비밀번호 초기화, 미지정 시 서버에서 랜덤 생성", "type": "string", "maxLength": 64, "minLength": 8, "example": "Temp!1234" }, "return_password": { "description": "1이면 응답에 임시 비밀번호 포함(개발/테스트용)", "type": "integer", "enum": [ 0, 1 ], "example": 0 } }, "type": "object" } } } }, "responses": { "200": { "description": "초기화 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "테넌트 사용자 비밀번호 초기화 성공" }, "data": { "properties": { "status": { "type": "string", "example": "ok" }, "temp_password": { "description": "return_password=1일 때만 포함", "type": "string", "example": "Temp!1234", "nullable": true } }, "type": "object" } }, "type": "object" } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "요청 충돌(정책 위반 등)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/drafts": { "get": { "tags": [ "Approvals" ], "summary": "기안함 - 내가 작성한 문서 목록", "description": "로그인 사용자가 기안한 결재 문서 목록을 조회합니다.", "operationId": "9a2af54c665d12e75e1e0c8af6696109", "parameters": [ { "name": "status", "in": "query", "description": "상태 필터", "schema": { "type": "string", "enum": [ "draft", "pending", "approved", "rejected", "cancelled" ] } }, { "name": "search", "in": "query", "description": "검색어 (제목, 문서번호)", "schema": { "type": "string" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "created_at", "enum": [ "created_at", "submitted_at", "completed_at", "title" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Approval" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 15 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/drafts/summary": { "get": { "tags": [ "Approvals" ], "summary": "기안함 현황 카드", "description": "기안 문서의 상태별 건수를 조회합니다.", "operationId": "4769f4bf3ffa21dfef426e1b97a79632", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ApprovalSummary" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/inbox": { "get": { "tags": [ "Approvals" ], "summary": "결재함 - 내가 결재할/결재한 문서", "description": "로그인 사용자에게 결재 요청된 문서 목록을 조회합니다.", "operationId": "c71cafbc366c35e3e265655eaaeaada6", "parameters": [ { "name": "filter", "in": "query", "description": "필터 (requested: 결재요청, scheduled: 결재예정, completed: 결재완료, rejected: 반려)", "schema": { "type": "string", "enum": [ "requested", "scheduled", "completed", "rejected" ] } }, { "name": "search", "in": "query", "description": "검색어 (제목, 문서번호, 기안자)", "schema": { "type": "string" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "submitted_at", "enum": [ "created_at", "submitted_at", "title" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Approval" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 10 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/inbox/summary": { "get": { "tags": [ "Approvals" ], "summary": "결재함 현황 카드", "description": "결재함의 상태별 건수를 조회합니다.", "operationId": "9fdb213827aa7971c13ab5cf921feeb5", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/InboxSummary" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/reference": { "get": { "tags": [ "Approvals" ], "summary": "참조함 - 참조로 받은 문서", "description": "로그인 사용자가 참조자로 지정된 문서 목록을 조회합니다.", "operationId": "666c4ff1e4a884e139ad8f52c9b8503c", "parameters": [ { "name": "is_read", "in": "query", "description": "열람 여부 필터", "schema": { "type": "boolean" } }, { "name": "search", "in": "query", "description": "검색어 (제목, 문서번호, 기안자)", "schema": { "type": "string" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "submitted_at", "enum": [ "created_at", "submitted_at", "title" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Approval" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 8 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/{id}": { "get": { "tags": [ "Approvals" ], "summary": "결재 문서 상세 조회", "operationId": "b35e33e3fad44a7f1a983071aba48919", "parameters": [ { "name": "id", "in": "path", "description": "문서 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Approval" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "문서를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Approvals" ], "summary": "결재 문서 삭제", "description": "임시저장 상태의 문서만 삭제할 수 있습니다.", "operationId": "ca30f9764c336678e3e5b6500a90b36e", "parameters": [ { "name": "id", "in": "path", "description": "문서 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "삭제 완료" }, "data": { "type": "boolean", "example": true } }, "type": "object" } } } }, "400": { "description": "삭제 불가 상태", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "문서를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Approvals" ], "summary": "결재 문서 수정", "description": "임시저장 상태의 문서만 수정할 수 있습니다.", "operationId": "369f16464c17ce617ab054bcb86c5e15", "parameters": [ { "name": "id", "in": "path", "description": "문서 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Approval" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청 또는 수정 불가 상태", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "문서를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals": { "post": { "tags": [ "Approvals" ], "summary": "결재 문서 생성 (임시저장)", "operationId": "42a5d458f7774900ddb37d21c8736f44", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalStoreRequest" } } } }, "responses": { "201": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Approval" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "양식을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/{id}/submit": { "post": { "tags": [ "Approvals" ], "summary": "결재 상신", "description": "임시저장 문서를 결재선에 상신합니다.", "operationId": "9ab9c789e9d2937e1f7217a31e8b6e06", "parameters": [ { "name": "id", "in": "path", "description": "문서 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalSubmitRequest" } } } }, "responses": { "200": { "description": "상신 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Approval" } }, "type": "object" } ] } } } }, "400": { "description": "상신 불가 상태", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "문서를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/{id}/approve": { "post": { "tags": [ "Approvals" ], "summary": "결재 승인", "description": "현재 순서의 결재자가 문서를 승인합니다.", "operationId": "8252aa372254965115167befe8c217f4", "parameters": [ { "name": "id", "in": "path", "description": "문서 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "properties": { "comment": { "description": "결재 의견 (선택)", "type": "string", "example": "승인합니다." } }, "type": "object" } } } }, "responses": { "200": { "description": "승인 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Approval" } }, "type": "object" } ] } } } }, "400": { "description": "결재 불가 상태 또는 결재 순서 아님", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "문서를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/{id}/reject": { "post": { "tags": [ "Approvals" ], "summary": "결재 반려", "description": "현재 순서의 결재자가 문서를 반려합니다. 반려 사유는 필수입니다.", "operationId": "0d422daa9f154a2fe61e947fef2759ac", "parameters": [ { "name": "id", "in": "path", "description": "문서 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "comment" ], "properties": { "comment": { "description": "반려 사유 (필수)", "type": "string", "example": "서류가 미비합니다. 재작성 바랍니다." } }, "type": "object" } } } }, "responses": { "200": { "description": "반려 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Approval" } }, "type": "object" } ] } } } }, "400": { "description": "결재 불가 상태 또는 결재 순서 아님", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "문서를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "반려 사유 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/{id}/cancel": { "post": { "tags": [ "Approvals" ], "summary": "결재 회수", "description": "기안자가 진행중인 문서를 회수합니다.", "operationId": "8727a68d0c21e819b76f6e4c0f904b3f", "parameters": [ { "name": "id", "in": "path", "description": "문서 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "회수 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Approval" } }, "type": "object" } ] } } } }, "400": { "description": "회수 불가 상태 또는 기안자가 아님", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "문서를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/{id}/read": { "post": { "tags": [ "Approvals" ], "summary": "열람 처리", "description": "참조자가 문서를 열람 처리합니다.", "operationId": "13b764797112791f3439cb4913177bb8", "parameters": [ { "name": "id", "in": "path", "description": "문서 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "열람 처리 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Approval" } }, "type": "object" } ] } } } }, "400": { "description": "참조자가 아님", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "문서를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approvals/{id}/unread": { "post": { "tags": [ "Approvals" ], "summary": "미열람 처리", "description": "참조자가 문서를 미열람 처리합니다.", "operationId": "de78aa2d2c383e07f079008d20c5f7cd", "parameters": [ { "name": "id", "in": "path", "description": "문서 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "미열람 처리 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Approval" } }, "type": "object" } ] } } } }, "400": { "description": "참조자가 아님", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "문서를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approval-forms": { "get": { "tags": [ "Approval Forms" ], "summary": "결재 양식 목록 조회", "description": "필터/검색/페이지네이션으로 결재 양식 목록을 조회합니다.", "operationId": "90b11409d796c75b4ff6298c86c40559", "parameters": [ { "name": "category", "in": "query", "description": "카테고리 필터", "schema": { "type": "string", "enum": [ "request", "expense", "expense_estimate" ] } }, { "name": "is_active", "in": "query", "description": "활성 상태 필터", "schema": { "type": "boolean" } }, { "name": "search", "in": "query", "description": "검색어 (이름, 코드)", "schema": { "type": "string" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "created_at", "enum": [ "created_at", "name", "code", "category" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ApprovalForm" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 10 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Approval Forms" ], "summary": "결재 양식 생성", "operationId": "30b4246af4d226295d54b07ac896924a", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalFormCreateRequest" } } } }, "responses": { "201": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ApprovalForm" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청 (코드 중복 등)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approval-forms/active": { "get": { "tags": [ "Approval Forms" ], "summary": "활성 결재 양식 목록 (셀렉트박스용)", "description": "활성화된 결재 양식만 간략하게 조회합니다.", "operationId": "ba5ea916fed25bee4704d0eb92d54a13", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "품의서" }, "code": { "type": "string", "example": "REQUEST_01" }, "category": { "type": "string", "example": "request" } }, "type": "object" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approval-forms/{id}": { "get": { "tags": [ "Approval Forms" ], "summary": "결재 양식 상세 조회", "operationId": "48eb28aa92ddbc00040563678285608a", "parameters": [ { "name": "id", "in": "path", "description": "양식 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ApprovalForm" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "양식을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Approval Forms" ], "summary": "결재 양식 삭제", "description": "사용 중인 양식은 삭제할 수 없습니다.", "operationId": "5d2123d11fec8fe8e0d0032969a7b1a6", "parameters": [ { "name": "id", "in": "path", "description": "양식 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "삭제 완료" }, "data": { "type": "boolean", "example": true } }, "type": "object" } } } }, "400": { "description": "삭제 불가 (사용 중)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "양식을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Approval Forms" ], "summary": "결재 양식 수정", "operationId": "c71a0f0b624b54c91a83da990f7072c1", "parameters": [ { "name": "id", "in": "path", "description": "양식 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalFormUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ApprovalForm" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "양식을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approval-lines": { "get": { "tags": [ "Approval Lines" ], "summary": "결재선 목록 조회", "operationId": "3b7502ea0b51f0fea26f939fcd5e8727", "parameters": [ { "name": "search", "in": "query", "description": "검색어 (이름)", "schema": { "type": "string" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "created_at", "enum": [ "created_at", "name", "is_default" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ApprovalLine" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 5 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Approval Lines" ], "summary": "결재선 생성", "operationId": "0a55ae96bebd599bff59f086e0dcf15c", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalLineCreateRequest" } } } }, "responses": { "201": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ApprovalLine" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/approval-lines/{id}": { "get": { "tags": [ "Approval Lines" ], "summary": "결재선 상세 조회", "operationId": "9c22e50ede785b2ea0d81c8b344f54bf", "parameters": [ { "name": "id", "in": "path", "description": "결재선 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ApprovalLine" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "결재선을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Approval Lines" ], "summary": "결재선 삭제", "operationId": "33d210e51585bdb3c48e0e4fefc1cdcd", "parameters": [ { "name": "id", "in": "path", "description": "결재선 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "삭제 완료" }, "data": { "type": "boolean", "example": true } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "결재선을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Approval Lines" ], "summary": "결재선 수정", "operationId": "4ed302d725a700acd289339d46930570", "parameters": [ { "name": "id", "in": "path", "description": "결재선 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalLineUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ApprovalLine" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "결재선을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/attendances": { "get": { "tags": [ "Attendances" ], "summary": "근태 목록 조회", "description": "필터/검색/페이지네이션으로 근태 목록을 조회합니다.", "operationId": "417bc75584b71cbbe422ce657a878de1", "parameters": [ { "name": "user_id", "in": "query", "description": "사용자 ID 필터", "schema": { "type": "integer" } }, { "name": "date", "in": "query", "description": "특정 날짜 (YYYY-MM-DD)", "schema": { "type": "string", "format": "date" } }, { "name": "date_from", "in": "query", "description": "시작 날짜", "schema": { "type": "string", "format": "date" } }, { "name": "date_to", "in": "query", "description": "종료 날짜", "schema": { "type": "string", "format": "date" } }, { "name": "status", "in": "query", "description": "근태 상태", "schema": { "type": "string", "enum": [ "onTime", "late", "absent", "vacation", "businessTrip", "fieldWork", "overtime", "remote" ] } }, { "name": "department_id", "in": "query", "description": "부서 ID 필터", "schema": { "type": "integer" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "base_date", "enum": [ "base_date", "status", "created_at" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Attendance" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 100 } }, "type": "object" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Attendances" ], "summary": "근태 등록", "description": "새 근태 기록을 등록합니다.", "operationId": "4f91cb0920afef1c60dfe882abcb6bb0", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AttendanceCreateRequest" } } } }, "responses": { "201": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Attendance" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "같은 날 기록이 이미 존재함", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/attendances/monthly-stats": { "get": { "tags": [ "Attendances" ], "summary": "월간 통계 조회", "description": "월간 근태 통계를 조회합니다.", "operationId": "bbd233d7079f92d16c24208c08d47446", "parameters": [ { "name": "year", "in": "query", "description": "연도", "schema": { "type": "integer", "example": 2024 } }, { "name": "month", "in": "query", "description": "월", "schema": { "type": "integer", "maximum": 12, "minimum": 1, "example": 1 } }, { "name": "user_id", "in": "query", "description": "특정 사용자 ID (미지정시 전체)", "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/AttendanceMonthlyStats" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/attendances/check-in": { "post": { "tags": [ "Attendances" ], "summary": "출근 기록 (체크인)", "description": "출근 시간을 기록합니다. 당일 기록이 없으면 새로 생성, 있으면 업데이트합니다.", "operationId": "b33a3c25a96451335ce3ea6dcc637af0", "requestBody": { "required": false, "content": { "application/json": { "schema": { "properties": { "user_id": { "description": "사용자 ID (미지정시 본인)", "type": "integer", "example": 10 }, "check_in": { "description": "출근 시간 (미지정시 현재 시간)", "type": "string", "example": "09:00:00" }, "gps_data": { "description": "GPS 데이터", "properties": { "latitude": { "type": "number", "format": "float", "example": 37.5665 }, "longitude": { "type": "number", "format": "float", "example": 126.978 } }, "type": "object" } }, "type": "object" } } } }, "responses": { "200": { "description": "출근 기록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Attendance" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/attendances/check-out": { "post": { "tags": [ "Attendances" ], "summary": "퇴근 기록 (체크아웃)", "description": "퇴근 시간을 기록합니다. 출근 기록이 없으면 에러가 발생합니다.", "operationId": "a6ae28fde4fbf4beebc19c9962f5c8b7", "requestBody": { "required": false, "content": { "application/json": { "schema": { "properties": { "user_id": { "description": "사용자 ID (미지정시 본인)", "type": "integer", "example": 10 }, "check_out": { "description": "퇴근 시간 (미지정시 현재 시간)", "type": "string", "example": "18:00:00" }, "gps_data": { "description": "GPS 데이터", "properties": { "latitude": { "type": "number", "format": "float", "example": 37.5665 }, "longitude": { "type": "number", "format": "float", "example": 126.978 } }, "type": "object" } }, "type": "object" } } } }, "responses": { "200": { "description": "퇴근 기록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Attendance" } }, "type": "object" } ] } } } }, "400": { "description": "출근 기록 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/attendances/{id}": { "get": { "tags": [ "Attendances" ], "summary": "근태 상세 조회", "description": "ID 기준 근태 상세 정보를 조회합니다.", "operationId": "3d01da859a1cf850a2baa7456f770068", "parameters": [ { "name": "id", "in": "path", "description": "근태 ID", "required": true, "schema": { "type": "integer", "example": 1 } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Attendance" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "근태 기록을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Attendances" ], "summary": "근태 삭제", "description": "근태 기록을 삭제합니다 (소프트 삭제).", "operationId": "d7427274c39eeec65dcaee048edc70a3", "parameters": [ { "name": "id", "in": "path", "description": "근태 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "삭제 완료" }, "data": { "type": "boolean", "example": true } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "근태 기록을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Attendances" ], "summary": "근태 수정", "description": "근태 기록을 수정합니다.", "operationId": "3ff5cd4d20fca9c33b0b7be3faa526e4", "parameters": [ { "name": "id", "in": "path", "description": "근태 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AttendanceUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Attendance" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "근태 기록을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/attendances/bulk-delete": { "post": { "tags": [ "Attendances" ], "summary": "근태 일괄 삭제", "description": "여러 근태 기록을 일괄 삭제합니다.", "operationId": "de3aca6fc757cdc9b8197d678edd594f", "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "ids" ], "properties": { "ids": { "description": "삭제할 근태 ID 목록", "type": "array", "items": { "type": "integer" }, "example": [ 1, 2, 3 ] } }, "type": "object" } } } }, "responses": { "200": { "description": "일괄 삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "일괄 삭제 완료" }, "data": { "properties": { "deleted_count": { "type": "integer", "example": 3 } }, "type": "object" } }, "type": "object" } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/audit-logs": { "get": { "tags": [ "Design Audit" ], "summary": "List audit logs", "operationId": "16ed858f56b56911d4eb0748ed317dcb", "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "minimum": 1 } }, { "name": "size", "in": "query", "schema": { "type": "integer", "maximum": 200, "minimum": 1 } }, { "name": "target_type", "in": "query", "schema": { "type": "string" } }, { "name": "target_id", "in": "query", "schema": { "type": "integer" } }, { "name": "action", "in": "query", "schema": { "type": "string" } }, { "name": "actor_id", "in": "query", "schema": { "type": "integer" } }, { "name": "from", "in": "query", "schema": { "type": "string", "format": "date-time" } }, { "name": "to", "in": "query", "schema": { "type": "string", "format": "date-time" } } ], "responses": { "200": { "description": "List", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "data": { "properties": { "current_page": { "type": "integer" }, "data": { "type": "array", "items": { "properties": { "tenant_id": { "type": "integer" }, "target_type": { "type": "string" }, "target_id": { "type": "integer", "nullable": true }, "action": { "type": "string" }, "before": { "type": "object", "nullable": true }, "after": { "type": "object", "nullable": true }, "actor_id": { "type": "integer", "nullable": true }, "ip": { "type": "string", "nullable": true }, "ua": { "type": "string", "nullable": true }, "created_at": { "type": "string", "format": "date-time" } }, "type": "object" } } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/debug-apikey": { "get": { "tags": [ "Auth" ], "summary": "API Key 인증 확인", "description": "API Key가 유효한지 확인합니다. Bearer 토큰은 선택사항입니다.", "operationId": "6f9a5e3d875616da751769476d7e7d5b", "responses": { "200": { "description": "API Key 인증 성공", "content": { "application/json": { "schema": { "properties": { "message": { "type": "string", "example": "API Key 인증 성공" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/login": { "post": { "tags": [ "Auth" ], "summary": "로그인 (토큰 + 사용자 정보 + 테넌트 + 메뉴 + 역할)", "description": "로그인 성공 시 인증 토큰과 함께 사용자 정보, 활성 테넌트 정보, 접근 가능한 메뉴 목록, 역할 목록을 반환합니다.", "operationId": "b98c0c67c6e60ff8dbe75665c9294e11", "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "user_id", "user_pwd" ], "properties": { "user_id": { "type": "string", "example": "TestUser5" }, "user_pwd": { "type": "string", "example": "password123!" } }, "type": "object" } } } }, "responses": { "200": { "description": "로그인 성공", "content": { "application/json": { "schema": { "properties": { "message": { "type": "string", "example": "로그인 성공" }, "access_token": { "description": "액세스 토큰 (API 호출에 사용)", "type": "string", "example": "1|abc123xyz456" }, "refresh_token": { "description": "리프레시 토큰 (액세스 토큰 갱신에 사용)", "type": "string", "example": "2|def456uvw789" }, "token_type": { "description": "토큰 타입", "type": "string", "example": "Bearer" }, "expires_in": { "description": "액세스 토큰 만료 시간 (초 단위, null이면 무제한)", "type": "integer", "example": 7200, "nullable": true }, "expires_at": { "description": "액세스 토큰 만료 시각 (null이면 무제한)", "type": "string", "example": "2025-11-10 16:00:00", "nullable": true }, "user": { "description": "사용자 기본 정보", "properties": { "id": { "type": "integer", "example": 1 }, "user_id": { "type": "string", "example": "hamss" }, "name": { "type": "string", "example": "홍길동" }, "email": { "type": "string", "example": "hamss@example.com" }, "phone": { "type": "string", "example": "010-1234-5678", "nullable": true } }, "type": "object" }, "tenant": { "description": "활성 테넌트 정보 (is_default=1 우선, 없으면 is_active=1 중 첫 번째, 없으면 null)", "properties": { "id": { "type": "integer", "example": 1 }, "company_name": { "type": "string", "example": "주식회사 코드브리지" }, "business_num": { "type": "string", "example": "123-45-67890", "nullable": true }, "tenant_st_code": { "type": "string", "example": "ACTIVE", "nullable": true }, "other_tenants": { "description": "사용자가 소속된 다른 활성 테넌트 목록", "type": "array", "items": { "properties": { "tenant_id": { "type": "integer", "example": 2 }, "company_name": { "type": "string", "example": "주식회사 샘플" }, "business_num": { "type": "string", "example": "987-65-43210", "nullable": true }, "tenant_st_code": { "type": "string", "example": "ACTIVE", "nullable": true } }, "type": "object" } } }, "type": "object", "nullable": true }, "menus": { "description": "사용자가 접근 가능한 메뉴 목록 (menu:{menu_id}.view 권한 체크, override deny/allow 적용)", "type": "array", "items": { "properties": { "id": { "type": "integer", "example": 1 }, "parent_id": { "type": "integer", "example": null, "nullable": true }, "name": { "type": "string", "example": "대시보드" }, "url": { "type": "string", "example": "/dashboard", "nullable": true }, "icon": { "type": "string", "example": "dashboard", "nullable": true }, "sort_order": { "type": "integer", "example": 1 }, "is_external": { "description": "외부 링크 여부", "type": "boolean", "example": false }, "external_url": { "description": "외부 링크 URL", "type": "string", "example": "https://example.com", "nullable": true } }, "type": "object" } }, "roles": { "description": "사용자가 가진 역할 목록", "type": "array", "items": { "properties": { "id": { "description": "역할 ID", "type": "integer", "example": 1 }, "name": { "description": "역할명", "type": "string", "example": "system_manager" }, "description": { "description": "역할 설명", "type": "string", "example": "시스템 관리자" } }, "type": "object" } } }, "type": "object" } } } }, "200 (테넌트 없음)": { "description": "로그인 성공 - 활성 테넌트 없는 경우", "content": { "application/json": { "schema": { "properties": { "message": { "type": "string", "example": "로그인 성공" }, "access_token": { "description": "액세스 토큰 (API 호출에 사용)", "type": "string", "example": "1|abc123xyz456" }, "refresh_token": { "description": "리프레시 토큰 (액세스 토큰 갱신에 사용)", "type": "string", "example": "2|def456uvw789" }, "token_type": { "description": "토큰 타입", "type": "string", "example": "Bearer" }, "expires_in": { "description": "액세스 토큰 만료 시간 (초 단위, null이면 무제한)", "type": "integer", "example": 7200, "nullable": true }, "expires_at": { "description": "액세스 토큰 만료 시각 (null이면 무제한)", "type": "string", "example": "2025-11-10 16:00:00", "nullable": true }, "user": { "properties": { "id": { "type": "integer", "example": 1 }, "user_id": { "type": "string", "example": "hamss" }, "name": { "type": "string", "example": "홍길동" }, "email": { "type": "string", "example": "hamss@example.com" }, "phone": { "type": "string", "example": "010-1234-5678", "nullable": true } }, "type": "object" }, "tenant": { "type": "null", "example": null }, "menus": { "type": "array", "items": {} } }, "type": "object" } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "로그인 실패 (비밀번호 불일치)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "사용자를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] } ] } }, "/api/v1/logout": { "post": { "tags": [ "Auth" ], "summary": "로그아웃 (Access 및 Token 무효화)", "operationId": "1f1851015c3096425b6a4fd04c52054c", "responses": { "200": { "description": "로그아웃 성공", "content": { "application/json": { "schema": { "properties": { "message": { "type": "string", "example": "로그아웃 완료" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/signup": { "post": { "tags": [ "Auth" ], "summary": "회원가입", "description": "신규 회원을 생성합니다. (API Key 필요)", "operationId": "53307f8fef91b46ea5feb6ccce58bd08", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SignupRequest" } } } }, "responses": { "200": { "description": "회원가입 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "user": { "$ref": "#/components/schemas/MemberBrief" } }, "type": "object" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패(API Key 누락/오류)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] } ] } }, "/api/v1/bank-accounts": { "get": { "tags": [ "BankAccounts" ], "summary": "계좌 목록 조회", "description": "계좌 목록을 조회합니다.", "operationId": "1524e5f7db08dca39c5173a07cf61c0c", "parameters": [ { "name": "search", "in": "query", "description": "검색어 (계좌명, 은행명, 예금주, 계좌번호)", "schema": { "type": "string" } }, { "name": "status", "in": "query", "description": "상태 필터", "schema": { "type": "string", "enum": [ "active", "inactive" ] } }, { "name": "assigned_user_id", "in": "query", "description": "담당자 ID", "schema": { "type": "integer" } }, { "name": "is_primary", "in": "query", "description": "대표계좌만", "schema": { "type": "boolean" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "created_at", "enum": [ "account_name", "bank_name", "created_at" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/BankAccount" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 10 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "BankAccounts" ], "summary": "계좌 등록", "description": "새로운 계좌를 등록합니다. 첫 번째 계좌는 자동으로 대표계좌로 설정됩니다.", "operationId": "780bdcd49da08c19cef6bea639ddd265", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BankAccountCreateRequest" } } } }, "responses": { "201": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/BankAccount" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/bank-accounts/active": { "get": { "tags": [ "BankAccounts" ], "summary": "활성 계좌 목록 (셀렉트박스용)", "description": "활성 상태의 계좌 목록을 간단한 형태로 조회합니다.", "operationId": "a974c06c80a14879fb85e6842ab543de", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/BankAccountListItem" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/bank-accounts/{id}": { "get": { "tags": [ "BankAccounts" ], "summary": "계좌 상세 조회", "description": "계좌 상세 정보를 조회합니다.", "operationId": "2b0af1b63c081fffd9817afebc562123", "parameters": [ { "name": "id", "in": "path", "description": "계좌 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/BankAccount" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "계좌 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "BankAccounts" ], "summary": "계좌 수정", "description": "계좌 정보를 수정합니다.", "operationId": "4a1b9ecae47808e23c4286b54c9272dd", "parameters": [ { "name": "id", "in": "path", "description": "계좌 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BankAccountUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/BankAccount" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "계좌 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "BankAccounts" ], "summary": "계좌 삭제", "description": "계좌를 삭제합니다. (Soft Delete) 대표계좌 삭제 시 다른 활성 계좌가 대표계좌로 자동 설정됩니다.", "operationId": "dd68774c92f9f8def6d386aadb0cdd5b", "parameters": [ { "name": "id", "in": "path", "description": "계좌 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "계좌 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/bank-accounts/{id}/toggle": { "patch": { "tags": [ "BankAccounts" ], "summary": "계좌 상태 토글", "description": "계좌의 상태를 토글합니다. (active ↔ inactive)", "operationId": "307951eebd919c3cd3ad3e80d7ba7f23", "parameters": [ { "name": "id", "in": "path", "description": "계좌 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "토글 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/BankAccount" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "계좌 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/bank-accounts/{id}/set-primary": { "patch": { "tags": [ "BankAccounts" ], "summary": "대표계좌 설정", "description": "해당 계좌를 대표계좌로 설정합니다. 기존 대표계좌는 자동으로 해제됩니다.", "operationId": "7d53e459de6b2e4336ef8e4e3498f53f", "parameters": [ { "name": "id", "in": "path", "description": "계좌 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "설정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/BankAccount" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "계좌 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/boards": { "get": { "tags": [ "Board" ], "summary": "접근 가능한 게시판 목록 (시스템 + 테넌트)", "operationId": "ef5cdad8bc0f898cb46e2892fcf3cab0", "parameters": [ { "name": "board_type", "in": "query", "description": "게시판 유형 필터", "schema": { "type": "string" } }, { "name": "search", "in": "query", "description": "게시판명 검색", "schema": { "type": "string" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Board" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Board" ], "summary": "테넌트 게시판 생성", "description": "현재 테넌트에 새 게시판을 생성합니다. 시스템 게시판은 mng에서만 생성 가능합니다.", "operationId": "d1d828f2924addfc1097d7f2ed18fbb5", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BoardCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Board" } }, "type": "object" } ] } } } }, "400": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/boards/tenant": { "get": { "tags": [ "Board" ], "summary": "테넌트 게시판 목록만 조회", "operationId": "6792d84f1ef3fc9122719577154d0bbc", "parameters": [ { "name": "board_type", "in": "query", "schema": { "type": "string" } }, { "name": "search", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Board" } } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/boards/{code}": { "get": { "tags": [ "Board" ], "summary": "게시판 상세 조회 (코드 기반)", "operationId": "269da54746b3c9b19e4e49f844c96c05", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Board" } }, "type": "object" } ] } } } }, "404": { "description": "게시판 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/boards/{id}": { "put": { "tags": [ "Board" ], "summary": "테넌트 게시판 수정", "description": "테넌트 게시판만 수정 가능. 시스템 게시판은 수정 불가.", "operationId": "a16ec17e90c7274fadc20f0e129c6bea", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BoardUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Board" } }, "type": "object" } ] } } } }, "404": { "description": "게시판 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Board" ], "summary": "테넌트 게시판 삭제", "description": "테넌트 게시판만 삭제 가능. 시스템 게시판은 삭제 불가.", "operationId": "dd2c045d26f0966426caea3373aeb4e0", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "게시판 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/boards/{code}/fields": { "get": { "tags": [ "Board" ], "summary": "게시판 커스텀 필드 목록", "operationId": "2dcd61e035bcad689c11ddfa91ad7fda", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/BoardField" } } }, "type": "object" } ] } } } }, "404": { "description": "게시판 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/models/{model_id}/estimate-parameters": { "get": { "tags": [ "BOM Calculation" ], "summary": "견적 파라미터 조회", "description": "특정 모델의 견적 시 필요한 입력 파라미터 스키마를 조회합니다. BOM에 정의된 조건만 동적으로 추출하여 반환합니다.", "operationId": "609741310dfb7f033dba40d3389d16ad", "parameters": [ { "name": "model_id", "in": "path", "description": "모델 ID", "required": true, "schema": { "type": "integer", "example": 1 } }, { "name": "company_name", "in": "query", "description": "업체명 (선택사항)", "required": false, "schema": { "type": "string", "example": "경동기업" } } ], "responses": { "200": { "description": "견적 파라미터 조회 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EstimateParametersResponse" } } } }, "404": { "description": "모델을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/bom-templates/{bom_template_id}/calculate-bom": { "post": { "tags": [ "BOM Calculation" ], "summary": "BOM 계산 실행", "description": "입력된 파라미터를 기반으로 BOM 수량을 동적으로 계산합니다. 업체별 산출식을 적용하여 실시간 견적을 생성합니다.", "operationId": "45bacd76a76ffccbe14cebaf4292bc9e", "parameters": [ { "name": "bom_template_id", "in": "path", "description": "BOM 템플릿 ID", "required": true, "schema": { "type": "integer", "example": 1 } } ], "requestBody": { "description": "계산 파라미터", "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CalculateBomRequest" } } } }, "responses": { "200": { "description": "BOM 계산 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CalculateBomResponse" } } } }, "400": { "description": "잘못된 파라미터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/companies/{company_name}/formulas": { "get": { "tags": [ "BOM Calculation" ], "summary": "업체별 산출식 목록 조회", "description": "특정 업체의 등록된 산출식 목록을 조회합니다.", "operationId": "b84098c781548ba29278946b83efe628", "parameters": [ { "name": "company_name", "in": "path", "description": "업체명", "required": true, "schema": { "type": "string", "example": "경동기업" } } ], "responses": { "200": { "description": "업체 산출식 목록 조회 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompanyFormulasResponse" } } } }, "404": { "description": "업체를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/companies/{company_name}/formulas/{formula_type}": { "post": { "tags": [ "BOM Calculation" ], "summary": "업체별 산출식 등록/수정", "description": "특정 업체의 산출식을 등록하거나 수정합니다. 기존 산출식이 있으면 새 버전으로 업데이트됩니다.", "operationId": "9c18692a8f738496e07263c78895181f", "parameters": [ { "name": "company_name", "in": "path", "description": "업체명", "required": true, "schema": { "type": "string", "example": "경동기업" } }, { "name": "formula_type", "in": "path", "description": "산출식 타입", "required": true, "schema": { "type": "string", "example": "manufacturing_size" } } ], "requestBody": { "description": "산출식 데이터", "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SaveFormulaRequest" } } } }, "responses": { "201": { "description": "업체 산출식 등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "id": { "type": "integer", "example": 1 }, "company_name": { "type": "string", "example": "경동기업" }, "formula_type": { "type": "string", "example": "manufacturing_size" }, "version": { "type": "string", "example": "v1.0" }, "is_active": { "type": "boolean", "example": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-09-22T15:30:00Z" } }, "type": "object" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/formulas/test": { "post": { "tags": [ "BOM Calculation" ], "summary": "계산식 테스트 실행", "description": "산출식을 실제 적용하기 전에 테스트해볼 수 있습니다.", "operationId": "29bba41925cd65ebe9310c4487d8d092", "requestBody": { "description": "테스트할 계산식과 파라미터", "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FormulaTestRequest" } } } }, "responses": { "200": { "description": "계산식 테스트 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FormulaTestResponse" } } } }, "400": { "description": "잘못된 계산식", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/cards": { "get": { "tags": [ "Cards" ], "summary": "카드 목록 조회", "description": "카드 목록을 조회합니다.", "operationId": "55f362d66079bf7859df7e0ca13c2bc8", "parameters": [ { "name": "search", "in": "query", "description": "검색어 (카드명, 카드사, 끝4자리)", "schema": { "type": "string" } }, { "name": "status", "in": "query", "description": "상태 필터", "schema": { "type": "string", "enum": [ "active", "inactive" ] } }, { "name": "assigned_user_id", "in": "query", "description": "담당자 ID", "schema": { "type": "integer" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "created_at", "enum": [ "card_name", "card_company", "created_at" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Card" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 10 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Cards" ], "summary": "카드 등록", "description": "새로운 카드를 등록합니다. 카드번호는 암호화되어 저장됩니다.", "operationId": "3448ddb67a03a1e6e8609e24b6705c42", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardCreateRequest" } } } }, "responses": { "201": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Card" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/cards/active": { "get": { "tags": [ "Cards" ], "summary": "활성 카드 목록 (셀렉트박스용)", "description": "활성 상태의 카드 목록을 간단한 형태로 조회합니다.", "operationId": "6f3c5662d676b1479dfd08867f5acf93", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/CardListItem" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/cards/{id}": { "get": { "tags": [ "Cards" ], "summary": "카드 상세 조회", "description": "카드 상세 정보를 조회합니다.", "operationId": "3318609c9211322d9eb88f0b443b82da", "parameters": [ { "name": "id", "in": "path", "description": "카드 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Card" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "카드 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Cards" ], "summary": "카드 수정", "description": "카드 정보를 수정합니다.", "operationId": "ec193da906fb8f625f10c8f6e8abeeb3", "parameters": [ { "name": "id", "in": "path", "description": "카드 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CardUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Card" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "카드 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Cards" ], "summary": "카드 삭제", "description": "카드를 삭제합니다. (Soft Delete)", "operationId": "935f7bd26ca34cda1459adaa593762a6", "parameters": [ { "name": "id", "in": "path", "description": "카드 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "카드 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/cards/{id}/toggle": { "patch": { "tags": [ "Cards" ], "summary": "카드 상태 토글", "description": "카드의 상태를 토글합니다. (active ↔ inactive)", "operationId": "38a68fc717b793ab8ae24fdead09b232", "parameters": [ { "name": "id", "in": "path", "description": "카드 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "토글 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Card" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "카드 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories": { "get": { "tags": [ "Category" ], "summary": "카테고리 목록", "operationId": "9dfb2569b0591f2d50167133fdbf9408", "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "example": 1 } }, { "name": "size", "in": "query", "schema": { "type": "integer", "example": 20 } }, { "name": "q", "in": "query", "description": "코드/이름 검색", "schema": { "type": "string" } }, { "name": "parent_id", "in": "query", "schema": { "type": "integer", "nullable": true } }, { "name": "only_active", "in": "query", "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CategoryPagination" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Category" ], "summary": "카테고리 생성", "operationId": "cf6826efe0e35ff9b8b058f06bd21607", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CategoryCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Category" } }, "type": "object" } ] } } } }, "400": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}": { "get": { "tags": [ "Category" ], "summary": "카테고리 단건 조회", "operationId": "917acd35d29fcc619f4235109703755a", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Category" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Category" ], "summary": "카테고리 삭제(soft)", "operationId": "3a6ebaf31d83b625053a11632609715f", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Category" ], "summary": "카테고리 수정", "operationId": "c5d16e073e43505198ed3a5558ca7af7", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CategoryUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Category" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/toggle": { "post": { "tags": [ "Category" ], "summary": "활성/비활성 토글", "operationId": "6e56172eba67b116543d734800997e7a", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "변경 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Category" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/move": { "patch": { "tags": [ "Category" ], "summary": "부모/순서 이동", "operationId": "5d499802abc8b84010bb18dcc4578c74", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "parent_id": { "type": "integer", "nullable": true }, "sort_order": { "type": "integer", "nullable": true } }, "type": "object" } } } }, "responses": { "200": { "description": "이동 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Category" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/reorder": { "post": { "tags": [ "Category" ], "summary": "정렬순서 일괄 변경", "operationId": "a830e3136e4f2667de993b749e6e5330", "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "items": { "type": "array", "items": { "properties": { "id": { "type": "integer", "example": 1 }, "sort_order": { "type": "integer", "example": 10 } }, "type": "object" } } }, "type": "object" } } } }, "responses": { "200": { "description": "저장 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/tree": { "get": { "tags": [ "Category" ], "summary": "카테고리 트리", "operationId": "066b788e2d1267f1aa11a34a00a473d2", "parameters": [ { "name": "only_active", "in": "query", "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/CategoryTreeNode" } } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/fields": { "get": { "tags": [ "Category-Fields" ], "summary": "카테고리별 필드 목록", "operationId": "79e4505d1914302c2ba0278e5444bf49", "parameters": [ { "name": "id", "in": "path", "description": "카테고리 ID", "required": true, "schema": { "type": "integer" } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" }, { "name": "sort", "in": "query", "schema": { "type": "string", "example": "sort_order" } }, { "name": "order", "in": "query", "schema": { "type": "string", "enum": [ "asc", "desc" ], "example": "asc" } } ], "responses": { "200": { "description": "목록 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CategoryFieldPagination" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Category-Fields" ], "summary": "카테고리 필드 생성", "operationId": "24bd4bc50932890c3d5b14499cc2076f", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CategoryFieldCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CategoryField" } }, "type": "object" } ] } } } }, "400": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/fields/{field}": { "get": { "tags": [ "Category-Fields" ], "summary": "카테고리 필드 단건 조회", "operationId": "5b36f3cfee3218e75a4f1b30fb32f1b8", "parameters": [ { "name": "field", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CategoryField" } }, "type": "object" } ] } } } }, "404": { "description": "없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Category-Fields" ], "summary": "카테고리 필드 삭제", "operationId": "b721a57841a076815eac35f89b425a3f", "parameters": [ { "name": "field", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Category-Fields" ], "summary": "카테고리 필드 수정", "operationId": "4abb3a617cf18ebea69b2412d0c2f4ce", "parameters": [ { "name": "field", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CategoryFieldUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CategoryField" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/fields/reorder": { "post": { "tags": [ "Category-Fields" ], "summary": "카테고리 필드 정렬 저장", "operationId": "d54e4f650902657cd5b7c0dec46f1847", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CategoryFieldReorderRequest" } } } }, "responses": { "200": { "description": "저장 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/fields/bulk-upsert": { "put": { "tags": [ "Category-Fields" ], "summary": "카테고리 필드 일괄 업서트", "operationId": "c31bc43493ef0b5232febdc18e2a6c1f", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CategoryFieldBulkUpsertRequest" } } } }, "responses": { "200": { "description": "업서트 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "created": { "type": "integer", "example": 2 }, "updated": { "type": "integer", "example": 3 } }, "type": "object" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/templates": { "get": { "tags": [ "Category-Templates" ], "summary": "카테고리 템플릿 버전 목록", "operationId": "4796e043b4efa6b7b31799e932fa84d8", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "목록 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/CategoryTemplate" } }, "total": { "type": "integer", "example": 3 } }, "type": "object" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Category-Templates" ], "summary": "카테고리 템플릿 생성(새 버전)", "operationId": "0bc562dc410918a70bcdddcfeb7efd44", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CategoryTemplateCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CategoryTemplate" } }, "type": "object" } ] } } } }, "409": { "description": "버전 중복", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/templates/{tpl}": { "get": { "tags": [ "Category-Templates" ], "summary": "카테고리 템플릿 단건 조회", "operationId": "86aba298b525819f3196079c4dd9c54f", "parameters": [ { "name": "tpl", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CategoryTemplate" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Category-Templates" ], "summary": "카테고리 템플릿 삭제", "operationId": "a7410e16a4b70ecc844d63fac69cd2a2", "parameters": [ { "name": "tpl", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Category-Templates" ], "summary": "카테고리 템플릿 수정", "operationId": "5520cf7e2e960fc804ab3b407061a167", "parameters": [ { "name": "tpl", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CategoryTemplateUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CategoryTemplate" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/templates/{tpl}/apply": { "post": { "tags": [ "Category-Templates" ], "summary": "카테고리 템플릿 적용(활성화)", "operationId": "45aeff70745dece9ef64cf198fc1f2d8", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "tpl", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "적용 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/templates/{tpl}/preview": { "get": { "tags": [ "Category-Templates" ], "summary": "카테고리 템플릿 미리보기", "operationId": "fababa4c826f648ce405f18b554466e2", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "tpl", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "미리보기 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/templates/diff": { "get": { "tags": [ "Category-Templates" ], "summary": "두 버전 비교(diff)", "operationId": "547695d96c378d4768c12e573bd6b214", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "a", "in": "query", "description": "비교 기준 버전", "required": true, "schema": { "type": "integer" } }, { "name": "b", "in": "query", "description": "비교 대상 버전", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "비교 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "added": { "type": "array", "items": { "type": "string" } }, "removed": { "type": "array", "items": { "type": "string" } } }, "type": "object" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/{id}/logs": { "get": { "tags": [ "Category-Logs" ], "summary": "카테고리 변경 이력 목록", "operationId": "379707f3c0cc191043f2ab5d97d4a6ab", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "action", "in": "query", "schema": { "type": "string", "enum": [ "insert", "update", "delete" ] } }, { "name": "from", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "to", "in": "query", "schema": { "type": "string", "format": "date" } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "목록 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/CategoryLog" } }, "total": { "type": "integer", "example": 12 } }, "type": "object" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/categories/logs/{log}": { "get": { "tags": [ "Category-Logs" ], "summary": "카테고리 변경 이력 단건 조회", "operationId": "a7d4cb59bad924379fe2bc659d31c4ec", "parameters": [ { "name": "log", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CategoryLog" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/classifications": { "get": { "tags": [ "Classification" ], "summary": "분류 목록", "description": "그룹/검색/활성여부 조건으로 분류 목록을 페이징 반환합니다.", "operationId": "572dd9379142c1140319d13eccdeab12", "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "example": 1 } }, { "name": "size", "in": "query", "schema": { "type": "integer", "example": 20 } }, { "name": "q", "in": "query", "description": "코드/이름 검색", "schema": { "type": "string" } }, { "name": "group", "in": "query", "description": "분류 그룹 키", "schema": { "type": "string" } }, { "name": "only_active", "in": "query", "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ClassificationPagination" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Classification" ], "summary": "분류 생성", "operationId": "39ec4aec7fcf7da09afdf8bf89db7735", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClassificationCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Classification" } }, "type": "object" } ] } } } }, "400": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/classifications/{id}": { "get": { "tags": [ "Classification" ], "summary": "분류 단건 조회", "operationId": "9340ed32f486ab2464d88f87e22a9563", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Classification" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Classification" ], "summary": "분류 삭제(soft)", "operationId": "65f3364e5e921e358cebd09ed15cac57", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Classification" ], "summary": "분류 수정", "operationId": "5ffd066556d3374d19d77102ac5146e2", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClassificationUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Classification" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/clients": { "get": { "tags": [ "Client" ], "summary": "거래처 목록", "operationId": "ce67333f551df4e1fdeccb07e5bf5545", "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "example": 1 } }, { "name": "size", "in": "query", "schema": { "type": "integer", "example": 20 } }, { "name": "q", "in": "query", "description": "거래처 코드/이름 검색", "schema": { "type": "string" } }, { "name": "only_active", "in": "query", "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ClientPagination" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Client" ], "summary": "거래처 생성", "operationId": "e5b8b51ce9cc90f81e3de10f5ecf8990", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClientCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Client" } }, "type": "object" } ] } } } }, "400": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/clients/{id}": { "get": { "tags": [ "Client" ], "summary": "거래처 단건 조회", "operationId": "8eb353ba0db90b4d3dfb742aec018f5e", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Client" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Client" ], "summary": "거래처 수정", "operationId": "48350431ab22822edc5b2e85785d27b8", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClientUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Client" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Client" ], "summary": "거래처 삭제", "description": "주문이 존재하는 거래처는 삭제할 수 없습니다.", "operationId": "30ef09ebfb7a9828862976f83875d7f3", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "400": { "description": "주문 존재로 삭제 불가", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/clients/{id}/toggle": { "patch": { "tags": [ "Client" ], "summary": "활성/비활성 토글", "operationId": "5959d2132558c2f0d75ebe83a9875540", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "변경 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Client" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/client-groups": { "get": { "tags": [ "ClientGroup" ], "summary": "고객 그룹 목록", "operationId": "421f67cf40a70ef5c2cad356e9b508f1", "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "example": 1 } }, { "name": "size", "in": "query", "schema": { "type": "integer", "example": 20 } }, { "name": "q", "in": "query", "description": "그룹 코드/이름 검색", "schema": { "type": "string" } }, { "name": "only_active", "in": "query", "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ClientGroupPagination" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "ClientGroup" ], "summary": "고객 그룹 생성", "description": "고객 그룹을 생성합니다. 같은 group_code로 이전에 삭제된 그룹이 있으면 자동으로 복원하고 새 데이터로 업데이트합니다.", "operationId": "36ebfd5e0e948adae0d0d77904e059c7", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClientGroupCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공 (또는 삭제된 데이터 복원)", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ClientGroup" } }, "type": "object" } ] } } } }, "400": { "description": "검증 실패 또는 중복 코드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/client-groups/{id}": { "get": { "tags": [ "ClientGroup" ], "summary": "고객 그룹 단건 조회", "operationId": "52b59fe36556445d6e21fa6bcbc4a1fa", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ClientGroup" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "ClientGroup" ], "summary": "고객 그룹 수정", "operationId": "22090341e29366ac9626376c35d14186", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClientGroupUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ClientGroup" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "ClientGroup" ], "summary": "고객 그룹 삭제(soft)", "operationId": "66564c7ba28dc37e98d423909e131500", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/client-groups/{id}/toggle": { "patch": { "tags": [ "ClientGroup" ], "summary": "활성/비활성 토글", "operationId": "eea8930ccf12bdd3eb3e1eefe4b5f3fe", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "변경 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ClientGroup" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/departments": { "get": { "tags": [ "Department" ], "summary": "부서 목록 조회", "description": "테넌트 범위 내 부서 목록을 페이징으로 반환합니다. (q로 이름/코드 검색)", "operationId": "2815f1ebbb4e4342d42ee38fb9be99d1", "parameters": [ { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "example": 1 } }, { "name": "per_page", "in": "query", "required": false, "schema": { "type": "integer", "example": 10 } }, { "name": "q", "in": "query", "required": false, "schema": { "type": "string", "example": "운영" } }, { "name": "is_active", "in": "query", "required": false, "schema": { "type": "integer", "enum": [ 0, 1 ], "example": 1 } } ], "responses": { "200": { "description": "부서 목록 조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 목록 조회 성공" }, "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "per_page": { "type": "integer", "example": 10 }, "total": { "type": "integer", "example": 2 }, "data": { "$ref": "#/components/schemas/DepartmentList" } }, "type": "object" } }, "type": "object" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Department" ], "summary": "부서 생성", "operationId": "7562894b3d471d1281a2ebe032dd2c8b", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DepartmentCreateRequest" } } } }, "responses": { "200": { "description": "부서 생성 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 생성 성공" }, "data": { "$ref": "#/components/schemas/Department" } }, "type": "object" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/departments/{id}": { "get": { "tags": [ "Department" ], "summary": "부서 단건 조회", "operationId": "20ead37634a5fab0b30fafb2b1cae703", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } } ], "responses": { "200": { "description": "부서 조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 조회 성공" }, "data": { "$ref": "#/components/schemas/Department" } }, "type": "object" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Department" ], "summary": "부서 삭제(소프트)", "operationId": "ed1688eeef449c1801c4991417f4ce10", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } } ], "responses": { "200": { "description": "부서 삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 삭제 성공" }, "data": { "properties": { "id": { "type": "integer", "example": 7 }, "deleted_at": { "type": "string", "format": "date-time", "example": "2025-08-21 11:00:00" } }, "type": "object" } }, "type": "object" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Department" ], "summary": "부서 수정", "operationId": "72359452b1ac47f10389ceed978df17a", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DepartmentUpdateRequest" } } } }, "responses": { "200": { "description": "부서 수정 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 수정 성공" }, "data": { "$ref": "#/components/schemas/Department" } }, "type": "object" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/departments/{id}/users": { "get": { "tags": [ "Department" ], "summary": "부서 사용자 목록", "description": "해당 부서에 속한 사용자 목록을 페이징으로 반환합니다.", "operationId": "6c8d0983ae3e653d98cba4d4188128df", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } }, { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "example": 1 } }, { "name": "per_page", "in": "query", "required": false, "schema": { "type": "integer", "example": 20 } } ], "responses": { "200": { "description": "부서 사용자 목록 조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 사용자 목록 조회 성공" }, "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/UserBrief" } } }, "type": "object" } }, "type": "object" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Department" ], "summary": "부서 사용자 배정(단건)", "operationId": "5d923a11765ccb6cb93f0b31f5b9c8c2", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DepartmentUserAttachRequest" } } } }, "responses": { "200": { "description": "부서 사용자 배정 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 사용자 배정 성공" }, "data": { "properties": { "department_id": { "type": "integer", "example": 7 }, "user_id": { "type": "integer", "example": 12 } }, "type": "object" } }, "type": "object" } } } }, "409": { "description": "이미 배정됨", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "부서 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/departments/{id}/users/{user}": { "delete": { "tags": [ "Department" ], "summary": "부서 사용자 해제(단건)", "operationId": "30f4ab61ae09998e682835b5bcc141f3", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } }, { "name": "user", "in": "path", "required": true, "schema": { "type": "integer", "example": 12 } } ], "responses": { "200": { "description": "부서 사용자 해제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 사용자 해제 성공" }, "data": { "properties": { "user_id": { "type": "integer", "example": 12 }, "deleted_at": { "type": "string", "format": "date-time", "example": "2025-08-21 11:00:00" } }, "type": "object" } }, "type": "object" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/departments/{id}/users/{user}/primary": { "patch": { "tags": [ "Department" ], "summary": "주부서 설정/해제", "operationId": "f4f0523282595d3b3c3f467ac929fdc2", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } }, { "name": "user", "in": "path", "required": true, "schema": { "type": "integer", "example": 12 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "is_primary": { "type": "integer", "enum": [ 0, 1 ], "example": 1 } }, "type": "object" } } } }, "responses": { "200": { "description": "주부서 설정 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "주부서 설정 성공" }, "data": { "properties": { "user_id": { "type": "integer", "example": 12 }, "department_id": { "type": "integer", "example": 7 }, "is_primary": { "type": "integer", "example": 1 } }, "type": "object" } }, "type": "object" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/departments/{id}/permissions": { "get": { "tags": [ "Department" ], "summary": "부서 권한 목록", "description": "부서에 설정된 ALLOW/DENY 목록을 조회합니다. (is_allowed=1|0, menu_id 필터 지원)", "operationId": "7e9a95e39f02d3c3b5a5eaa17f18f416", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } }, { "name": "menu_id", "in": "query", "required": false, "schema": { "type": "integer", "example": 101 } }, { "name": "is_allowed", "in": "query", "required": false, "schema": { "type": "integer", "enum": [ 0, 1 ], "example": 1 } }, { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "example": 1 } }, { "name": "per_page", "in": "query", "required": false, "schema": { "type": "integer", "example": 20 } } ], "responses": { "200": { "description": "부서 권한 목록 조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 권한 목록 조회 성공" }, "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 3 }, "data": { "type": "array", "items": { "properties": { "permission_id": { "type": "integer", "example": 25 }, "permission_code": { "type": "string", "example": "menu.101.read" }, "is_allowed": { "type": "integer", "example": 1 }, "reason": { "type": "string", "example": "보안 이슈", "nullable": true }, "effective_from": { "type": "string", "format": "date-time", "nullable": true }, "effective_to": { "type": "string", "format": "date-time", "nullable": true } }, "type": "object" } } }, "type": "object" } }, "type": "object" } } } }, "404": { "description": "부서 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Department" ], "summary": "부서 권한 부여/차단(Upsert: 단건/배치)", "description": "permission_id 기준으로 ALLOW(1) 또는 DENY(0) 처리합니다. 단건 또는 items 배열을 모두 지원합니다.", "operationId": "95e1c346eaeec24d65fef8797ae9deea", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "oneOf": [ { "$ref": "#/components/schemas/DepartmentPermissionUpsertSingle" }, { "$ref": "#/components/schemas/DepartmentPermissionUpsertMany" } ] } } } }, "responses": { "200": { "description": "부서 권한 적용 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 권한 적용 성공" }, "data": { "properties": { "processed": { "type": "integer", "example": 2 }, "succeeded": { "type": "integer", "example": 2 }, "failed": { "type": "array", "items": { "type": "object" } } }, "type": "object" } }, "type": "object" } } } }, "404": { "description": "부서 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Department" ], "summary": "부서 권한 해제(단건/배치)", "description": "지정 권한을 부서 매핑에서 제거합니다. 단건 또는 items 배열을 모두 지원합니다.", "operationId": "32bb7e01990d1a0417474dc3febc5ae6", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 7 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "oneOf": [ { "$ref": "#/components/schemas/DepartmentPermissionRevokeSingle" }, { "$ref": "#/components/schemas/DepartmentPermissionRevokeMany" } ] } } } }, "responses": { "200": { "description": "부서 권한 해제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "부서 권한 해제 성공" }, "data": { "properties": { "processed": { "type": "integer", "example": 2 }, "succeeded": { "type": "integer", "example": 2 }, "failed": { "type": "array", "items": { "type": "object" } } }, "type": "object" } }, "type": "object" } } } }, "404": { "description": "부서 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/deposits": { "get": { "tags": [ "Deposits" ], "summary": "입금 목록 조회", "description": "입금 목록을 조회합니다.", "operationId": "b21d566f227b836f2a5e4862e2963875", "parameters": [ { "name": "search", "in": "query", "description": "검색어 (거래처명, 적요)", "schema": { "type": "string" } }, { "name": "start_date", "in": "query", "description": "시작일", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "description": "종료일", "schema": { "type": "string", "format": "date" } }, { "name": "client_id", "in": "query", "description": "거래처 ID", "schema": { "type": "integer" } }, { "name": "payment_method", "in": "query", "description": "결제수단", "schema": { "type": "string", "enum": [ "cash", "transfer", "card", "check" ] } }, { "name": "bank_account_id", "in": "query", "description": "계좌 ID", "schema": { "type": "integer" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "deposit_date", "enum": [ "deposit_date", "amount", "created_at" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Deposit" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 50 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Deposits" ], "summary": "입금 등록", "description": "새로운 입금을 등록합니다.", "operationId": "4a1a91f0d43f888b68d0801181cc3a18", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DepositCreateRequest" } } } }, "responses": { "201": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Deposit" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/deposits/summary": { "get": { "tags": [ "Deposits" ], "summary": "입금 요약 조회", "description": "기간별 입금 요약을 조회합니다.", "operationId": "770f20ea96ce20712c0c3c1d330ade75", "parameters": [ { "name": "start_date", "in": "query", "description": "시작일", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "description": "종료일", "schema": { "type": "string", "format": "date" } }, { "name": "client_id", "in": "query", "description": "거래처 ID", "schema": { "type": "integer" } }, { "name": "payment_method", "in": "query", "description": "결제수단", "schema": { "type": "string", "enum": [ "cash", "transfer", "card", "check" ] } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/DepositSummary" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/deposits/{id}": { "get": { "tags": [ "Deposits" ], "summary": "입금 상세 조회", "description": "입금 상세 정보를 조회합니다.", "operationId": "1f54ad94db53152bf15c51e94a0baa35", "parameters": [ { "name": "id", "in": "path", "description": "입금 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Deposit" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "입금 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Deposits" ], "summary": "입금 수정", "description": "입금 정보를 수정합니다.", "operationId": "001bcd24971089738c3396ca421b2dee", "parameters": [ { "name": "id", "in": "path", "description": "입금 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DepositUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Deposit" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "입금 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Deposits" ], "summary": "입금 삭제", "description": "입금을 삭제합니다. (Soft Delete)", "operationId": "1635f9f115f7b448c64dc68fd61cff9e", "parameters": [ { "name": "id", "in": "path", "description": "입금 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "입금 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/bom-templates/{templateId}/diff": { "get": { "tags": [ "Design BOM" ], "summary": "Diff two BOM templates", "operationId": "a7b179391b9ba3403befd351bad8e3f6", "parameters": [ { "name": "templateId", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "other_template_id", "in": "query", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "Success", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "data": { "properties": { "left_template_id": { "type": "integer" }, "right_template_id": { "type": "integer" }, "summary": { "properties": { "added": { "type": "integer" }, "removed": { "type": "integer" }, "changed": { "type": "integer" } }, "type": "object" }, "added": { "type": "array", "items": { "properties": { "ref_type": { "type": "string", "example": "MATERIAL" }, "ref_id": { "type": "integer" }, "qty": { "type": "number" }, "waste_rate": { "type": "number" }, "uom_id": { "type": "integer", "nullable": true }, "notes": { "type": "string", "nullable": true }, "sort_order": { "type": "integer" } }, "type": "object" } }, "removed": { "type": "array", "items": { "$ref": "#/components/schemas/DesignBomItemDiffRow" } }, "changed": { "type": "array", "items": { "properties": { "ref_type": { "type": "string" }, "ref_id": { "type": "integer" }, "changes": { "type": "object" } }, "type": "object" } } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/design/bom-templates/{templateId}/clone": { "post": { "tags": [ "Design BOM" ], "summary": "Clone a BOM template (deep copy)", "operationId": "b1f631e18159485e9cc8ef385d36f176", "parameters": [ { "name": "templateId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "properties": { "target_version_id": { "type": "integer", "nullable": true }, "name": { "type": "string", "nullable": true }, "is_primary": { "type": "boolean", "nullable": true }, "notes": { "type": "string", "nullable": true } }, "type": "object" } } } }, "responses": { "200": { "description": "Cloned", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean" }, "message": { "type": "string" }, "data": { "properties": { "id": { "type": "integer" }, "tenant_id": { "type": "integer" }, "model_version_id": { "type": "integer" }, "name": { "type": "string" }, "is_primary": { "type": "boolean" }, "notes": { "type": "string", "nullable": true } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/design/models": { "get": { "tags": [ "Model" ], "summary": "모델 목록", "description": "모델(설계 상위) 목록을 페이징으로 조회합니다.", "operationId": "8ffe609126155eaa855e4b8c7417f717", "parameters": [ { "name": "q", "in": "query", "description": "검색어(code/name/description like)", "schema": { "type": "string" } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/DesignModelPagination" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Model" ], "summary": "모델 생성", "description": "모델(설계 상위)을 생성합니다.", "operationId": "2ff98bf9e947719a4b07a3f0dced9b98", "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "code", "name" ], "properties": { "code": { "type": "string", "maxLength": 100, "example": "KSS01" }, "name": { "type": "string", "maxLength": 200, "example": "KSS 표준 모델" }, "category_id": { "type": "integer", "example": 12, "nullable": true }, "lifecycle": { "type": "string", "example": "ACTIVE", "nullable": true }, "description": { "type": "string", "example": "롤러 구조 표준 설계", "nullable": true }, "is_active": { "type": "boolean", "example": true } }, "type": "object" } } } }, "responses": { "200": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/DesignModel" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/models/{id}": { "get": { "tags": [ "Model" ], "summary": "모델 상세", "description": "단일 모델을 조회합니다. (versions 포함 가능)", "operationId": "1a236f463efa60b83d34b3a453eb130f", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/DesignModel" } }, "type": "object" } ] } } } }, "404": { "description": "없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Model" ], "summary": "모델 수정", "operationId": "facd823622efdc5d089619015ca75540", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "code": { "type": "string", "maxLength": 100, "example": "KSS01" }, "name": { "type": "string", "maxLength": 200, "example": "KSS 표준 모델(개정)" }, "category_id": { "type": "integer", "example": 12, "nullable": true }, "lifecycle": { "type": "string", "example": "ACTIVE", "nullable": true }, "description": { "type": "string", "example": "개정 메모", "nullable": true }, "is_active": { "type": "boolean", "example": true } }, "type": "object" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Model" ], "summary": "모델 삭제(soft)", "operationId": "0e62d61d15adc9503e83cd7baa6dd3d8", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/models/{modelId}/versions": { "get": { "tags": [ "ModelVersion" ], "summary": "모델의 버전 목록", "operationId": "8a2eb9c9477cec8796a8bcf3d34d09a0", "parameters": [ { "name": "modelId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ModelVersion" } } }, "type": "object" } ] } } } }, "404": { "description": "없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "ModelVersion" ], "summary": "버전 DRAFT 생성", "description": "version_no 미지정 시 자동 증가", "operationId": "b79d40b95a3641ade7f5bc720d25718e", "parameters": [ { "name": "modelId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "properties": { "version_no": { "type": "integer", "example": 1, "nullable": true }, "notes": { "type": "string", "example": "초안 메모", "nullable": true }, "effective_from": { "type": "string", "format": "date-time", "nullable": true }, "effective_to": { "type": "string", "format": "date-time", "nullable": true } }, "type": "object" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ModelVersion" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/versions/{versionId}/release": { "post": { "tags": [ "ModelVersion" ], "summary": "버전 RELEASED 전환", "operationId": "a88d334173078711f089d3cd42c20cfa", "parameters": [ { "name": "versionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "전환 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ModelVersion" } }, "type": "object" } ] } } } }, "409": { "description": "상태 충돌", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/versions/{versionId}/bom-templates": { "get": { "tags": [ "BomTemplate" ], "summary": "모델버전의 BOM 템플릿 목록", "operationId": "ff0bfa1c632ba93f57891e92796220ef", "parameters": [ { "name": "versionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/BomTemplate" } } }, "type": "object" } ] } } } }, "404": { "description": "없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "BomTemplate" ], "summary": "BOM 템플릿 upsert (name 기준)", "description": "is_primary=true 지정 시 동일 모델버전의 기존 대표 템플릿은 자동 해제", "operationId": "4d27e80e65ef309e3d7fd082c2f5f855", "parameters": [ { "name": "versionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "properties": { "name": { "type": "string", "maxLength": 100, "example": "Main" }, "is_primary": { "type": "boolean", "example": true }, "notes": { "type": "string", "example": "표준 템플릿", "nullable": true } }, "type": "object" } } } }, "responses": { "200": { "description": "저장 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/BomTemplate" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/bom-templates/{templateId}": { "get": { "tags": [ "BomTemplate" ], "summary": "BOM 템플릿 상세 (항목 포함)", "operationId": "c015500cde3ea9b1ded61911c4d74d6b", "parameters": [ { "name": "templateId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/BomTemplate" } }, "type": "object" } ] } } } }, "404": { "description": "없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/design/bom-templates/{templateId}/items": { "put": { "tags": [ "BomTemplate" ], "summary": "BOM 항목 일괄 치환", "description": "기존 항목을 모두 삭제 후 본문 items로 재삽입", "operationId": "a85263fcb82f3c45c9fe61d91be2ff17", "parameters": [ { "name": "templateId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BomTemplateItemReplaceRequest" } } } }, "responses": { "200": { "description": "저장 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/employees": { "get": { "tags": [ "Employees" ], "summary": "사원 목록 조회", "description": "필터/검색/페이지네이션으로 사원 목록을 조회합니다.", "operationId": "10df01073b4c4295c738e34aecadc888", "parameters": [ { "name": "q", "in": "query", "description": "이름/이메일/사원번호 검색어", "schema": { "type": "string" } }, { "name": "status", "in": "query", "description": "고용상태 필터", "schema": { "type": "string", "enum": [ "active", "leave", "resigned" ] } }, { "name": "department_id", "in": "query", "description": "부서 ID 필터", "schema": { "type": "integer", "example": 5 } }, { "name": "has_account", "in": "query", "description": "시스템 계정 보유 여부", "schema": { "type": "string", "enum": [ "0", "1", "true", "false" ] } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "created_at", "enum": [ "created_at", "name", "employee_status", "department_id" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Employee" } }, "first_page_url": { "type": "string", "example": "/api/v1/employees?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 8 }, "last_page_url": { "type": "string", "example": "/api/v1/employees?page=8" }, "next_page_url": { "type": "string", "example": "/api/v1/employees?page=2", "nullable": true }, "path": { "type": "string", "example": "/api/v1/employees" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 150 } }, "type": "object" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Employees" ], "summary": "사원 등록", "description": "새 사원을 등록합니다. password를 입력하면 시스템 계정도 함께 생성됩니다.", "operationId": "a58c31a6c5f96bfbaf1edefcf3613484", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EmployeeCreateRequest" } } } }, "responses": { "201": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Employee" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "이메일 중복", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/employees/stats": { "get": { "tags": [ "Employees" ], "summary": "사원 통계 조회", "description": "사원 현황 통계를 조회합니다.", "operationId": "6bd50dca39136cabbb8b749dc9c7d09a", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/EmployeeStats" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/employees/{id}": { "get": { "tags": [ "Employees" ], "summary": "사원 상세 조회", "description": "ID 기준 사원 상세 정보를 조회합니다.", "operationId": "74b1c4cc4f612ba553ebd7b18020944d", "parameters": [ { "name": "id", "in": "path", "description": "사원 프로필 ID", "required": true, "schema": { "type": "integer", "example": 1 } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Employee" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "사원을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Employees" ], "summary": "사원 삭제 (퇴직 처리)", "description": "사원을 퇴직 처리합니다. employee_status가 'resigned'로 변경되고 소프트 삭제됩니다.", "operationId": "b649c17a689018531f98753eecf10599", "parameters": [ { "name": "id", "in": "path", "description": "사원 프로필 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "삭제 완료" }, "data": { "type": "boolean", "example": true } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "사원을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Employees" ], "summary": "사원 수정", "description": "사원 정보를 수정합니다.", "operationId": "25d50a1676dac0e6b232eaa2a9d369ee", "parameters": [ { "name": "id", "in": "path", "description": "사원 프로필 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EmployeeUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Employee" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "사원을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "이메일 중복", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/employees/bulk-delete": { "post": { "tags": [ "Employees" ], "summary": "사원 일괄 삭제", "description": "여러 사원을 일괄 퇴직 처리합니다.", "operationId": "f533a371fe69c1f044e151bb95abbb44", "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "ids" ], "properties": { "ids": { "description": "삭제할 사원 ID 목록", "type": "array", "items": { "type": "integer" }, "example": [ 1, 2, 3 ] } }, "type": "object" } } } }, "responses": { "200": { "description": "일괄 삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "일괄 삭제 완료" }, "data": { "properties": { "deleted_count": { "type": "integer", "example": 3 } }, "type": "object" } }, "type": "object" } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/employees/{id}/create-account": { "post": { "tags": [ "Employees" ], "summary": "시스템 계정 생성", "description": "기존 사원에게 시스템 로그인 계정을 생성합니다.", "operationId": "d2c42eea7f5162fb926b8c34a52ffc30", "parameters": [ { "name": "id", "in": "path", "description": "사원 프로필 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "password" ], "properties": { "password": { "description": "계정 비밀번호", "type": "string", "minLength": 8, "example": "Password123!" } }, "type": "object" } } } }, "responses": { "200": { "description": "계정 생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Employee" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "사원을 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "이미 계정이 존재함", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages/{pageId}/link-section": { "post": { "tags": [ "ItemMaster-Relationships" ], "summary": "페이지에 섹션 연결", "description": "페이지와 섹션을 연결합니다.", "operationId": "48dca9099946d924576463800114ae62", "parameters": [ { "name": "pageId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LinkEntityRequest" } } } }, "responses": { "200": { "description": "연결 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "연결 성공" }, "data": { "$ref": "#/components/schemas/EntityRelationship" } }, "type": "object" } } } }, "404": { "description": "페이지 또는 섹션을 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages/{pageId}/unlink-section/{sectionId}": { "delete": { "tags": [ "ItemMaster-Relationships" ], "summary": "페이지에서 섹션 연결 해제", "description": "페이지와 섹션의 연결을 해제합니다.", "operationId": "7c63ffea39be6614006a573451e866d5", "parameters": [ { "name": "pageId", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "sectionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "연결 해제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "연결 해제 성공" }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages/{pageId}/link-field": { "post": { "tags": [ "ItemMaster-Relationships" ], "summary": "페이지에 필드 직접 연결", "description": "페이지와 필드를 직접 연결합니다 (섹션 없이).", "operationId": "22124c102e20f98c2f1c9a9309024ffe", "parameters": [ { "name": "pageId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LinkEntityRequest" } } } }, "responses": { "200": { "description": "연결 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "연결 성공" }, "data": { "$ref": "#/components/schemas/EntityRelationship" } }, "type": "object" } } } }, "404": { "description": "페이지 또는 필드를 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages/{pageId}/unlink-field/{fieldId}": { "delete": { "tags": [ "ItemMaster-Relationships" ], "summary": "페이지에서 필드 연결 해제", "description": "페이지와 필드의 연결을 해제합니다.", "operationId": "576518a664d6bf82d7d0f4dfeffb1d3c", "parameters": [ { "name": "pageId", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "fieldId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "연결 해제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "연결 해제 성공" }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages/{pageId}/relationships": { "get": { "tags": [ "ItemMaster-Relationships" ], "summary": "페이지의 모든 관계 조회", "description": "페이지에 연결된 모든 관계(섹션, 필드)를 조회합니다.", "operationId": "674831e04d3fe76231ffac4928449ee6", "parameters": [ { "name": "pageId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "조회 성공" }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/EntityRelationship" } } }, "type": "object" } } } }, "404": { "description": "페이지를 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages/{pageId}/structure": { "get": { "tags": [ "ItemMaster-Relationships" ], "summary": "페이지 구조 조회", "description": "페이지의 전체 구조를 조회합니다 (섹션, 직접 연결된 필드, 중첩 구조).", "operationId": "416dcd133e8a85b3b699f363eaa459e5", "parameters": [ { "name": "pageId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "조회 성공" }, "data": { "$ref": "#/components/schemas/PageStructure" } }, "type": "object" } } } }, "404": { "description": "페이지를 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{sectionId}/link-field": { "post": { "tags": [ "ItemMaster-Relationships" ], "summary": "섹션에 필드 연결", "description": "섹션과 필드를 연결합니다.", "operationId": "91766abe9e5b59344428a96eb9d61b9e", "parameters": [ { "name": "sectionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LinkEntityRequest" } } } }, "responses": { "200": { "description": "연결 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "연결 성공" }, "data": { "$ref": "#/components/schemas/EntityRelationship" } }, "type": "object" } } } }, "404": { "description": "섹션 또는 필드를 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{sectionId}/unlink-field/{fieldId}": { "delete": { "tags": [ "ItemMaster-Relationships" ], "summary": "섹션에서 필드 연결 해제", "description": "섹션과 필드의 연결을 해제합니다.", "operationId": "3a9ca920fa0eb3141edcae637e4f2d23", "parameters": [ { "name": "sectionId", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "fieldId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "연결 해제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "연결 해제 성공" }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{sectionId}/link-bom": { "post": { "tags": [ "ItemMaster-Relationships" ], "summary": "섹션에 BOM 항목 연결", "description": "섹션과 BOM 항목을 연결합니다.", "operationId": "94d483bc12937d6f326a95eeabb09f74", "parameters": [ { "name": "sectionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LinkEntityRequest" } } } }, "responses": { "200": { "description": "연결 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "연결 성공" }, "data": { "$ref": "#/components/schemas/EntityRelationship" } }, "type": "object" } } } }, "404": { "description": "섹션 또는 BOM 항목을 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{sectionId}/unlink-bom/{bomId}": { "delete": { "tags": [ "ItemMaster-Relationships" ], "summary": "섹션에서 BOM 항목 연결 해제", "description": "섹션과 BOM 항목의 연결을 해제합니다.", "operationId": "5c8919e511bc8649adc8cba72985ce4e", "parameters": [ { "name": "sectionId", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "bomId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "연결 해제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "연결 해제 성공" }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{sectionId}/relationships": { "get": { "tags": [ "ItemMaster-Relationships" ], "summary": "섹션의 자식 관계 조회", "description": "섹션에 연결된 모든 자식 관계(필드, BOM)를 조회합니다.", "operationId": "651e4dc70a7700e0d0698845b613a8e3", "parameters": [ { "name": "sectionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "조회 성공" }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/EntityRelationship" } } }, "type": "object" } } } }, "404": { "description": "섹션을 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/relationships/reorder": { "post": { "tags": [ "ItemMaster-Relationships" ], "summary": "관계 순서 변경", "description": "특정 부모 아래의 자식 관계 순서를 변경합니다.", "operationId": "8b736f2fe59d636398c64b58093fb88d", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReorderRelationshipsRequest" } } } }, "responses": { "200": { "description": "순서 변경 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "정렬 변경 성공" }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/fields": { "get": { "tags": [ "Tenant.Fields" ], "summary": "효과값 필드 목록", "description": "전역 필드 정의와 테넌트 설정을 병합한, 실제 화면 노출용(Enabled) 필드 목록을 반환합니다.", "operationId": "ff880a50359bcee8c50a29afb277fc22", "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/FieldEffective" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/fields/bulk": { "put": { "tags": [ "Tenant.Fields" ], "summary": "필드 설정 대량 저장", "description": "여러 필드에 대해 enabled/required/sort_order/option_group_id/code_group 설정을 한번에 저장합니다.", "operationId": "67119e7c5a2355f380437e81cbbc20aa", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FieldSettingBulkRequest" } } } }, "responses": { "200": { "description": "저장 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "object", "example": { "updated": true } } }, "type": "object" } ] } } } }, "400": { "description": "유효성 오류", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/fields/{key}": { "patch": { "tags": [ "Tenant.Fields" ], "summary": "필드 설정 단건 수정", "description": "특정 field_key에 대한 테넌트 설정을 수정합니다.", "operationId": "4e99c399326d523e29e59dabc905add6", "parameters": [ { "name": "key", "in": "path", "description": "수정할 필드 키", "required": true, "schema": { "type": "string", "example": "position" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FieldSettingUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/FieldEffective" } }, "type": "object" } ] } } } }, "400": { "description": "유효성 오류", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "필드 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/opt-groups": { "get": { "tags": [ "Tenant.Option Groups" ], "summary": "옵션 그룹 목록", "description": "해당 테넌트의 옵션 그룹 목록을 페이징으로 반환합니다.", "operationId": "8e884d63e881d7e1ef6e7cf348624c26", "parameters": [ { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" }, { "name": "q", "in": "query", "description": "검색어(그룹키/이름)", "required": false, "schema": { "type": "string", "example": "position" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/OptionGroup" } }, "total": { "type": "integer", "example": 3 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Tenant.Option Groups" ], "summary": "옵션 그룹 생성", "description": "옵션 그룹을 생성합니다.", "operationId": "b1c29346462d17c16041ed2ea82d453d", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OptionGroupCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/OptionGroup" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/opt-groups/{id}": { "get": { "tags": [ "Tenant.Option Groups" ], "summary": "옵션 그룹 단건 조회", "operationId": "9d4db310ed473c6966625be040be0a2b", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/OptionGroup" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Tenant.Option Groups" ], "summary": "옵션 그룹 삭제", "operationId": "efe4faa34089d3ea7a2645a88ecfcbc3", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "object", "example": null, "nullable": true } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Tenant.Option Groups" ], "summary": "옵션 그룹 수정", "operationId": "3c92a3ff886306615c181b2071483030", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OptionGroupUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/OptionGroup" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/opt-groups/{gid}/values": { "get": { "tags": [ "Tenant.Option Values" ], "summary": "옵션 값 목록", "operationId": "2cd94ad233355b0c2905ad79a5b556f5", "parameters": [ { "name": "gid", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } }, { "name": "active_only", "in": "query", "required": false, "schema": { "type": "boolean", "example": true } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/OptionValue" } } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Tenant.Option Values" ], "summary": "옵션 값 생성", "operationId": "e83ce0f3d33c2fc1a3636b001efb5931", "parameters": [ { "name": "gid", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OptionValueCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/OptionValue" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/opt-groups/{gid}/values/{id}": { "get": { "tags": [ "Tenant.Option Values" ], "summary": "옵션 값 단건 조회", "operationId": "9acb916cd2e90a9a8236858f57c4a31e", "parameters": [ { "name": "gid", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } }, { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 10 } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/OptionValue" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Tenant.Option Values" ], "summary": "옵션 값 삭제", "operationId": "a73379693f01077dad3c6383a9a34e8b", "parameters": [ { "name": "gid", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } }, { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 10 } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "object", "example": null, "nullable": true } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Tenant.Option Values" ], "summary": "옵션 값 수정", "operationId": "f663adf96be75dd4ef30c0ccd20117e6", "parameters": [ { "name": "gid", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } }, { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 10 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OptionValueUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/OptionValue" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/opt-groups/{gid}/values/reorder": { "patch": { "tags": [ "Tenant.Option Values" ], "summary": "옵션 값 정렬 순서 일괄 변경", "operationId": "1735e1287fe945fdcbdfddee6f0d011b", "parameters": [ { "name": "gid", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OptionValueReorderRequest" } } } }, "responses": { "200": { "description": "변경 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "object", "example": { "reordered": true } } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/profiles": { "get": { "tags": [ "Tenant.Profiles" ], "summary": "프로필 목록", "description": "테넌트 내 회원 프로필 목록을 페이징으로 반환합니다.", "operationId": "476c3d2b726569da6f77f0de2ea7a673", "parameters": [ { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" }, { "name": "q", "in": "query", "description": "검색어(표기명/사번 등)", "required": false, "schema": { "type": "string", "example": "A-001" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ProfilePagination" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/profiles/{userId}": { "get": { "tags": [ "Tenant.Profiles" ], "summary": "프로필 단건 조회", "operationId": "cf3d51cda4411b0d6188634a9753faa9", "parameters": [ { "name": "userId", "in": "path", "required": true, "schema": { "type": "integer", "example": 55 } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Profile" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Tenant.Profiles" ], "summary": "프로필 수정(관리자)", "description": "관리자 권한으로 해당 사용자의 프로필을 수정합니다. 테넌트에서 enabled된 필드만 반영됩니다.", "operationId": "e7a5de51f1a997d079dd82f24dc5c3d0", "parameters": [ { "name": "userId", "in": "path", "required": true, "schema": { "type": "integer", "example": 55 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProfileUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Profile" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/profiles/me": { "get": { "tags": [ "Tenant.Profiles" ], "summary": "내 프로필 조회", "operationId": "6cc3e3db4f45bac067f75364fed22123", "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Profile" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Tenant.Profiles" ], "summary": "내 프로필 수정", "operationId": "759f20b0d271d6b37b9ca354d842553f", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProfileUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Profile" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files/upload": { "post": { "tags": [ "Files" ], "summary": "파일 업로드", "description": "파일을 임시 폴더에 업로드합니다. 이후 /files/move로 정식 폴더로 이동시켜야 합니다.", "operationId": "15956f09c71ecf768ffad20470a26330", "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "required": [ "file" ], "properties": { "file": { "description": "업로드할 파일 (최대 20MB)", "type": "string", "format": "binary" }, "description": { "type": "string", "maxLength": 500, "example": "계약서 원본", "nullable": true } }, "type": "object" } } } }, "responses": { "200": { "description": "파일 업로드 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/File" } }, "type": "object" } ] } } } }, "400": { "description": "용량 초과 또는 파일 형식 오류" }, "401": { "description": "인증 실패" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files/move": { "post": { "tags": [ "Files" ], "summary": "파일 이동", "description": "임시 폴더의 파일들을 정식 폴더로 이동하고 문서에 첨부합니다.", "operationId": "f2f669da9a27bcdf27a7b8edf8111878", "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "file_ids", "folder_id" ], "properties": { "file_ids": { "type": "array", "items": { "type": "integer" }, "example": [ 1, 2, 3 ] }, "folder_id": { "description": "대상 폴더 ID", "type": "integer", "example": 1 }, "document_id": { "description": "첨부할 문서 ID", "type": "integer", "example": 10, "nullable": true }, "document_type": { "description": "문서 타입", "type": "string", "maxLength": 100, "example": "Order", "nullable": true } }, "type": "object" } } } }, "responses": { "200": { "description": "파일 이동 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/File" } } }, "type": "object" } ] } } } }, "404": { "description": "파일 또는 폴더를 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files": { "get": { "tags": [ "Files" ], "summary": "파일 목록 조회", "description": "폴더별, 문서별 파일 목록을 조회합니다.", "operationId": "48125dcc4808454ca7354550e3347ce8", "parameters": [ { "name": "folder_id", "in": "query", "description": "폴더 ID (선택)", "schema": { "type": "integer" } }, { "name": "document_id", "in": "query", "description": "문서 ID (선택)", "schema": { "type": "integer" } }, { "name": "document_type", "in": "query", "description": "문서 타입 (선택)", "schema": { "type": "string" } }, { "name": "is_temp", "in": "query", "description": "임시 파일만 조회", "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "파일 목록 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/File" } } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files/{id}": { "get": { "tags": [ "Files" ], "summary": "파일 상세 조회", "description": "파일 ID로 상세 정보를 조회합니다.", "operationId": "fa1cd525929fe962d8d9556ea1d0c46d", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "파일 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/File" } }, "type": "object" } ] } } } }, "404": { "description": "파일을 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Files" ], "summary": "파일 삭제", "description": "파일을 휴지통으로 이동합니다 (복구 가능).", "operationId": "e4fb52ed14024441cf2646cf325d5e1e", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "파일 삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "파일을 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files/trash": { "get": { "tags": [ "Files" ], "summary": "휴지통 파일 목록", "description": "삭제된 파일 목록을 조회합니다 (30일 보관).", "operationId": "45b44cfedcc72c883900957a34e42c39", "responses": { "200": { "description": "휴지통 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/File" } } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files/{id}/download": { "get": { "tags": [ "Files" ], "summary": "파일 다운로드", "description": "파일을 다운로드합니다.", "operationId": "26701c7179386b050ea1e4162e6267c2", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "파일 다운로드", "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } } } }, "404": { "description": "파일을 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files/{id}/restore": { "post": { "tags": [ "Files" ], "summary": "파일 복구", "description": "휴지통의 파일을 복구합니다.", "operationId": "0a8ab9996e47b2f1b79a3e5c0a602cb4", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "파일 복구 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/File" } }, "type": "object" } ] } } } }, "404": { "description": "파일을 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files/{id}/permanent": { "delete": { "tags": [ "Files" ], "summary": "파일 영구 삭제", "description": "파일을 물리적으로 완전히 삭제합니다 (복구 불가).", "operationId": "0588aa504ff8bf3246aca6fa09cd8421", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "파일 영구 삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "파일을 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files/{id}/share": { "post": { "tags": [ "Files" ], "summary": "공유 링크 생성", "description": "파일의 임시 공유 링크를 생성합니다 (기본 24시간).", "operationId": "7cf156b4549a3f933af20c128ccee096", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "content": { "application/json": { "schema": { "properties": { "expiry_hours": { "description": "만료 시간 (시간 단위, 최대 7일)", "type": "integer", "maximum": 168, "minimum": 1, "example": 24 } }, "type": "object" } } } }, "responses": { "200": { "description": "공유 링크 생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/FileShareLink" } }, "type": "object" } ] } } } }, "404": { "description": "파일을 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/files/share/{token}": { "get": { "tags": [ "Files" ], "summary": "공유 파일 다운로드", "description": "공유 토큰으로 파일을 다운로드합니다 (인증 불필요).", "operationId": "37997afde48a1e3e746d019586303cef", "parameters": [ { "name": "token", "in": "path", "description": "64자 공유 토큰", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "파일 다운로드", "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } } } }, "404": { "description": "토큰을 찾을 수 없음" }, "410": { "description": "링크가 만료됨" } } } }, "/api/v1/storage/usage": { "get": { "tags": [ "Files" ], "summary": "저장소 사용량 조회", "description": "현재 테넌트의 저장소 사용량 정보를 조회합니다.", "operationId": "e495fc3e3312464932d88884d815032a", "responses": { "200": { "description": "사용량 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/StorageUsage" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/folders": { "get": { "tags": [ "Folder" ], "summary": "폴더 목록 조회", "description": "테넌트의 모든 폴더를 display_order 순으로 조회합니다.", "operationId": "07e6467df73cd06449b2f7195f3ab335", "responses": { "200": { "description": "폴더 목록 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Folder" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Folder" ], "summary": "폴더 생성", "description": "새로운 폴더를 생성합니다.", "operationId": "a01afc068b575eff51738b3bc8fd2fc3", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FolderStoreRequest" } } } }, "responses": { "200": { "description": "폴더 생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Folder" } }, "type": "object" } ] } } } }, "400": { "description": "유효성 검증 실패" }, "409": { "description": "중복된 folder_key" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/folders/{id}": { "get": { "tags": [ "Folder" ], "summary": "폴더 상세 조회", "description": "폴더 ID로 상세 정보를 조회합니다.", "operationId": "2d992f1e4d009ff11ddf0a1b64d3ec7b", "parameters": [ { "name": "id", "in": "path", "description": "폴더 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "폴더 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Folder" } }, "type": "object" } ] } } } }, "404": { "description": "폴더를 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Folder" ], "summary": "폴더 수정", "description": "폴더 정보를 수정합니다.", "operationId": "83e85c775f38e7feddf0dd68927cefb1", "parameters": [ { "name": "id", "in": "path", "description": "폴더 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FolderUpdateRequest" } } } }, "responses": { "200": { "description": "폴더 수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Folder" } }, "type": "object" } ] } } } }, "400": { "description": "유효성 검증 실패" }, "404": { "description": "폴더를 찾을 수 없음" }, "409": { "description": "중복된 folder_key" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Folder" ], "summary": "폴더 삭제", "description": "폴더를 비활성화합니다. 파일이 있는 폴더는 삭제할 수 없습니다.", "operationId": "1672f3c37c31162dca8a45a45ec227c1", "parameters": [ { "name": "id", "in": "path", "description": "폴더 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "폴더 삭제 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Folder" } }, "type": "object" } ] } } } }, "400": { "description": "폴더에 파일이 있어 삭제 불가" }, "404": { "description": "폴더를 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/folders/reorder": { "post": { "tags": [ "Folder" ], "summary": "폴더 순서 변경", "description": "여러 폴더의 표시 순서를 일괄 변경합니다.", "operationId": "8c96f716978a12bbc89ba25edbd1cd86", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FolderReorderRequest" } } } }, "responses": { "200": { "description": "순서 변경 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Folder" } } }, "type": "object" } ] } } } }, "400": { "description": "유효성 검증 실패" }, "404": { "description": "일부 폴더를 찾을 수 없음" } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/init": { "get": { "tags": [ "ItemMaster" ], "summary": "품목기준관리 초기 데이터 로드", "operationId": "bac71b07461808225e98c7e674f81dae", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemMasterInitResponse" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/fields": { "get": { "tags": [ "ItemMaster" ], "summary": "필드 목록 조회", "description": "섹션과 연결되지 않은 필드 목록을 조회합니다.", "operationId": "d364722fbdabcbb2a10db14859eaec3c", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ItemField" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "ItemMaster" ], "summary": "필드 생성", "description": "섹션과 연결되지 않은 필드를 생성합니다.", "operationId": "4d4da6a8766a3ce750145f222e8962c9", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IndependentFieldStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemField" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{sectionId}/fields": { "post": { "tags": [ "ItemMaster" ], "summary": "필드 생성 (섹션 연결)", "operationId": "83d3060e9cbb95a8d97abec5186b947a", "parameters": [ { "name": "sectionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemFieldStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemField" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/fields/{id}": { "put": { "tags": [ "ItemMaster" ], "summary": "필드 수정", "operationId": "4ccbe0e6ca24108bcebded825b354df7", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemFieldUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemField" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "ItemMaster" ], "summary": "필드 삭제", "operationId": "5e06ce35200010a7cbb46e2aac55e272", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{sectionId}/fields/reorder": { "put": { "tags": [ "ItemMaster" ], "summary": "필드 순서 변경", "operationId": "c3bb551af1388365ece7fff815c26273", "parameters": [ { "name": "sectionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReorderRequest" } } } }, "responses": { "200": { "description": "순서 변경 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/fields/{id}/clone": { "post": { "tags": [ "ItemMaster" ], "summary": "필드 복제", "description": "기존 필드를 복제하여 새 필드를 생성합니다.", "operationId": "8900f0ddcd0211141e9a61f0bff3f5ff", "parameters": [ { "name": "id", "in": "path", "description": "복제할 필드 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "복제 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemField" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/fields/{id}/usage": { "get": { "tags": [ "ItemMaster" ], "summary": "필드 사용처 조회", "description": "필드가 어떤 섹션/페이지에 연결되어 있는지 조회합니다.", "operationId": "eaab4a5b74cf739787c21eb117fdaa8f", "parameters": [ { "name": "id", "in": "path", "description": "필드 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/FieldUsageResponse" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/unit-options": { "get": { "tags": [ "ItemMaster" ], "summary": "단위 옵션 목록", "operationId": "0a22268b06516a7b206dcdd0a6dc2526", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/UnitOption" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "ItemMaster" ], "summary": "단위 옵션 생성", "operationId": "4cd5c6c6f8e8bc5a84ee471b685e2353", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UnitOptionStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/UnitOption" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/unit-options/{id}": { "delete": { "tags": [ "ItemMaster" ], "summary": "단위 옵션 삭제", "operationId": "1e504d250f245d46248758213273b936", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages": { "get": { "tags": [ "ItemMaster" ], "summary": "페이지 목록 조회", "operationId": "9bf69bb84acd8e26b56e53ba6b7492ee", "parameters": [ { "name": "item_type", "in": "query", "description": "품목 유형 필터", "schema": { "type": "string", "enum": [ "FG", "PT", "SM", "RM", "CS" ] } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ItemPage" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "ItemMaster" ], "summary": "페이지 생성", "operationId": "25d4bb71a0b3e707224a323f7d39665a", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemPageStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemPage" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages/{id}": { "put": { "tags": [ "ItemMaster" ], "summary": "페이지 수정", "operationId": "20f8c5e5a569609ae9ab8dd2beb667fb", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemPageUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemPage" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "ItemMaster" ], "summary": "페이지 삭제", "description": "페이지를 삭제합니다. 연결된 섹션/필드는 삭제되지 않고 관계만 해제됩니다.", "operationId": "b2b7e48ad196f0babe2adfa700e3bf56", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections": { "get": { "tags": [ "ItemMaster" ], "summary": "섹션 목록 조회", "description": "페이지와 연결되지 않은 섹션 목록을 조회합니다. is_template 파라미터로 템플릿 필터링이 가능합니다.", "operationId": "08d9380295f0fb2e2b57a9a8ee30cf72", "parameters": [ { "name": "is_template", "in": "query", "description": "템플릿 여부 필터", "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ItemSection" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "ItemMaster" ], "summary": "섹션 생성", "description": "페이지와 연결되지 않은 섹션을 생성합니다.", "operationId": "e9a3c4e287cb1de99d6e54d5be060227", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IndependentSectionStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemSection" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages/{pageId}/sections": { "post": { "tags": [ "ItemMaster" ], "summary": "섹션 생성 (페이지 연결)", "operationId": "4e303dc0abce6b529f0faab963aa25f6", "parameters": [ { "name": "pageId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemSectionStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemSection" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{id}": { "put": { "tags": [ "ItemMaster" ], "summary": "섹션 수정", "operationId": "37422493eabba29cd41df5722206bad5", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemSectionUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemSection" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "ItemMaster" ], "summary": "섹션 삭제", "description": "섹션을 삭제합니다. 연결된 필드/BOM은 삭제되지 않고 관계만 해제됩니다.", "operationId": "4b1be81cef9965746478b4b54d5f62a0", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/pages/{pageId}/sections/reorder": { "put": { "tags": [ "ItemMaster" ], "summary": "섹션 순서 변경", "operationId": "e851440070ff5a49dfba3fe988a80604", "parameters": [ { "name": "pageId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReorderRequest" } } } }, "responses": { "200": { "description": "순서 변경 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{id}/clone": { "post": { "tags": [ "ItemMaster" ], "summary": "섹션 복제", "description": "기존 섹션을 복제하여 새 섹션을 생성합니다. 하위 필드와 BOM 항목도 함께 복제됩니다.", "operationId": "b6be6c685d3601d37b7a6f32726712ea", "parameters": [ { "name": "id", "in": "path", "description": "복제할 섹션 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "복제 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemSection" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{id}/usage": { "get": { "tags": [ "ItemMaster" ], "summary": "섹션 사용처 조회", "description": "섹션이 어떤 페이지에 연결되어 있는지 조회합니다 (entity_relationships 기반).", "operationId": "aa48e0fdd78ad6dc332fe50f6221a15c", "parameters": [ { "name": "id", "in": "path", "description": "섹션 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/SectionUsageResponse" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/section-templates": { "get": { "tags": [ "ItemMaster" ], "summary": "섹션 템플릿 목록", "operationId": "03b2b455382b4379e17a7e28348d7a2d", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/SectionTemplate" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "ItemMaster" ], "summary": "섹션 템플릿 생성", "operationId": "bfddc2f4851147a94517a0d2bf32e54c", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SectionTemplateStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/SectionTemplate" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/section-templates/{id}": { "put": { "tags": [ "ItemMaster" ], "summary": "섹션 템플릿 수정", "operationId": "ff1ecf4fb31cdfd2ea3537c61d294e34", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SectionTemplateUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/SectionTemplate" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "ItemMaster" ], "summary": "섹션 템플릿 삭제", "operationId": "1de889107771a16661556ff7c48f76ce", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/bom-items": { "get": { "tags": [ "ItemMaster" ], "summary": "BOM 목록 조회", "description": "섹션과 연결되지 않은 BOM 항목 목록을 조회합니다.", "operationId": "688d30d831fb6336781498386aac284f", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ItemBomItem" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "ItemMaster" ], "summary": "BOM 생성", "description": "섹션과 연결되지 않은 BOM 항목을 생성합니다.", "operationId": "8b39d430c9ad64dc14f2987cf6b9898c", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IndependentBomItemStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemBomItem" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/sections/{sectionId}/bom-items": { "post": { "tags": [ "ItemMaster" ], "summary": "BOM 항목 생성 (섹션 연결)", "operationId": "145c317aff009dae56f0cbf591668c71", "parameters": [ { "name": "sectionId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemBomItemStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemBomItem" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/bom-items/{id}": { "put": { "tags": [ "ItemMaster" ], "summary": "BOM 항목 수정", "operationId": "75bf5bb4cd6c627fb65f273d83b689e4", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemBomItemUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/ItemBomItem" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "ItemMaster" ], "summary": "BOM 항목 삭제", "operationId": "cadeb90e6dbd6dd3f910fb4570d375fa", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/custom-tabs": { "get": { "tags": [ "ItemMaster" ], "summary": "커스텀 탭 목록", "operationId": "f01f6efd55066496da2dade40890278c", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/CustomTab" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "ItemMaster" ], "summary": "커스텀 탭 생성", "operationId": "f6ff7dc7dde8c6d8315f8e7f97ef2838", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CustomTabStoreRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CustomTab" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/custom-tabs/{id}": { "put": { "tags": [ "ItemMaster" ], "summary": "커스텀 탭 수정", "operationId": "087a05188b0dc53fb3dbe04999926f18", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CustomTabUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/CustomTab" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "ItemMaster" ], "summary": "커스텀 탭 삭제", "operationId": "ff0cf113ca7ba3ea5769b60b32eab3b8", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/item-master/custom-tabs/reorder": { "put": { "tags": [ "ItemMaster" ], "summary": "커스텀 탭 순서 변경", "operationId": "b848e157e4c6b942f49b963f758ff9d1", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReorderRequest" } } } }, "responses": { "200": { "description": "순서 변경 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/items": { "get": { "tags": [ "Items" ], "summary": "품목 목록 조회 (통합)", "description": "Product + Material 통합 조회, 페이징 지원. type 또는 group_id 중 하나는 필수입니다.", "operationId": "7eced92a2cc19d25613742bcb5dfc685", "parameters": [ { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" }, { "name": "search", "in": "query", "description": "검색어 (code, name)", "schema": { "type": "string" }, "example": "P-001" }, { "name": "type", "in": "query", "description": "품목 타입 (FG,PT,SM,RM,CS). type 또는 group_id 중 하나 필수", "schema": { "type": "string" }, "example": "FG" }, { "name": "group_id", "in": "query", "description": "그룹 ID (1=품목). type 또는 group_id 중 하나 필수", "schema": { "type": "integer" }, "example": 1 }, { "name": "category_id", "in": "query", "description": "카테고리 ID 필터", "schema": { "type": "integer" }, "example": 1 }, { "name": "include_deleted", "in": "query", "description": "삭제된 항목 포함 여부", "schema": { "type": "boolean" }, "example": false } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "조회되었습니다." }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Item" } }, "meta": { "$ref": "#/components/schemas/PaginationMeta" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "post": { "tags": [ "Items" ], "summary": "품목 생성", "description": "product_type에 따라 Product(FG,PT) 또는 Material(SM,RM,CS) 테이블에 저장됩니다.", "operationId": "fa3cfc59d0ec4953c7d53a1f83b3962e", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemCreateRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "품목이 등록되었습니다." }, "data": { "$ref": "#/components/schemas/Item" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/code/{code}": { "get": { "tags": [ "Items" ], "summary": "품목 코드로 상세 조회", "description": "Product 먼저 조회 후, 없으면 Material에서 조회합니다.", "operationId": "197fe896c23c3460df823adf0c2850ae", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" }, { "name": "include_bom", "in": "query", "description": "BOM 포함 여부 (Product만 해당)", "schema": { "type": "boolean" }, "example": false } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "품목을 조회했습니다." }, "data": { "$ref": "#/components/schemas/Item" } }, "type": "object" } } } }, "404": { "description": "품목 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{id}": { "get": { "tags": [ "Items" ], "summary": "품목 ID로 상세 조회", "description": "item_type 파라미터로 조회할 테이블을 지정합니다. (FG,PT→products / SM,RM,CS→materials)", "operationId": "269c6720bebb5e8193a378138ccd11ea", "parameters": [ { "name": "id", "in": "path", "description": "품목 ID", "required": true, "schema": { "type": "integer" }, "example": 1 }, { "name": "item_type", "in": "query", "description": "품목 유형 (기본값: FG)", "required": false, "schema": { "type": "string", "default": "FG", "enum": [ "FG", "PT", "SM", "RM", "CS" ] }, "example": "FG" }, { "name": "include_price", "in": "query", "description": "단가 정보 포함 여부", "schema": { "type": "boolean" }, "example": false }, { "name": "client_id", "in": "query", "description": "거래처 ID (단가 조회 시)", "schema": { "type": "integer" }, "example": 1 }, { "name": "price_date", "in": "query", "description": "단가 기준일", "schema": { "type": "string", "format": "date" }, "example": "2025-01-10" } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "조회되었습니다." }, "data": { "$ref": "#/components/schemas/Item" } }, "type": "object" } } } }, "404": { "description": "품목 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "put": { "tags": [ "Items" ], "summary": "품목 수정", "description": "item_type 필드 필수. Product(FG,PT) 또는 Material(SM,RM,CS)을 자동 분기하여 수정합니다.", "operationId": "3945480870bcd8ab82f7e86e3d1a442a", "parameters": [ { "name": "id", "in": "path", "description": "품목 ID", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemUpdateRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "품목이 수정되었습니다." }, "data": { "$ref": "#/components/schemas/Item" } }, "type": "object" } } } }, "400": { "description": "코드 중복", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "품목 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "delete": { "tags": [ "Items" ], "summary": "품목 삭제", "description": "item_type 파라미터로 삭제할 테이블을 지정합니다. BOM 구성품으로 사용 중인 경우 삭제 불가.", "operationId": "aba97452a8c099ff314c380113c466ac", "parameters": [ { "name": "id", "in": "path", "description": "품목 ID", "required": true, "schema": { "type": "integer" }, "example": 1 }, { "name": "item_type", "in": "query", "description": "품목 유형 (기본값: FG)", "required": false, "schema": { "type": "string", "default": "FG", "enum": [ "FG", "PT", "SM", "RM", "CS" ] }, "example": "FG" } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "품목이 삭제되었습니다." }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } }, "400": { "description": "BOM 사용 중", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "품목 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/batch": { "delete": { "tags": [ "Items" ], "summary": "품목 일괄 삭제", "description": "item_type 필드 필수. 여러 품목을 한 번에 삭제합니다. BOM 구성품으로 사용 중인 경우 삭제 불가.", "operationId": "0f4ac27ffb9564afaa967d1a7ed301a0", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemBatchDeleteRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "품목이 일괄 삭제되었습니다." }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } }, "400": { "description": "BOM 사용 중", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "품목 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{code}/bom": { "get": { "tags": [ "Items BOM" ], "summary": "BOM 목록 조회 (flat list)", "operationId": "a4817bb1872400127acea98b60e4c284", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 항목 조회" }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/BOMLine" } } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "post": { "tags": [ "Items BOM" ], "summary": "BOM 라인 추가 (bulk upsert)", "operationId": "ce8df80826af330c00285d1d901b4f79", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BOMCreateRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 항목이 등록되었습니다." }, "data": { "properties": { "created": { "type": "integer", "example": 3 }, "updated": { "type": "integer", "example": 1 } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{code}/bom/tree": { "get": { "tags": [ "Items BOM" ], "summary": "BOM 트리 구조 조회 (계층적)", "operationId": "3a2993f40b201318b1da08dcc5bbe4f5", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" }, { "name": "depth", "in": "query", "description": "최대 깊이 (기본값: 10)", "schema": { "type": "integer" }, "example": 10 } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 항목 조회" }, "data": { "$ref": "#/components/schemas/BOMTree" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{code}/bom/{lineId}": { "put": { "tags": [ "Items BOM" ], "summary": "BOM 라인 수정", "operationId": "7a6b1dd38fa3b8726febe2ab7db887b8", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" }, { "name": "lineId", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BOMUpdateRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 항목이 수정되었습니다." }, "data": { "$ref": "#/components/schemas/BOMLine" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "delete": { "tags": [ "Items BOM" ], "summary": "BOM 라인 삭제", "operationId": "fe910782f518a91f80a34451967f7019", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" }, { "name": "lineId", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 항목이 삭제되었습니다." }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{code}/bom/summary": { "get": { "tags": [ "Items BOM" ], "summary": "BOM 요약 정보", "operationId": "24ade423c70814e4145cf326615ab8c8", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 항목 조회" }, "data": { "properties": { "count": { "type": "integer", "example": 10 }, "count_product": { "type": "integer", "example": 5 }, "count_material": { "type": "integer", "example": 5 }, "quantity_sum": { "type": "string", "example": "25.5000" } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{code}/bom/validate": { "get": { "tags": [ "Items BOM" ], "summary": "BOM 유효성 검사", "operationId": "790c3acc6517d405d7c77b8eb5d79167", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 항목 조회" }, "data": { "properties": { "valid": { "type": "boolean", "example": true }, "errors": { "type": "array", "items": { "properties": { "id": { "type": "integer", "example": 1 }, "error": { "type": "string", "example": "INVALID_QUANTITY" } }, "type": "object" } } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{code}/bom/replace": { "post": { "tags": [ "Items BOM" ], "summary": "BOM 전체 교체 (기존 삭제 후 재등록)", "operationId": "720ee16511337e6a99e43ea0c6f58de3", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "categories": { "type": "array", "items": { "properties": { "id": { "type": "integer", "example": 1, "nullable": true }, "name": { "type": "string", "example": "조립품" }, "items": { "type": "array", "items": { "required": [ "ref_type", "ref_id", "quantity" ], "properties": { "ref_type": { "type": "string", "example": "PRODUCT" }, "ref_id": { "type": "integer", "example": 10 }, "quantity": { "type": "number", "example": 2.5 }, "sort_order": { "type": "integer", "example": 1, "nullable": true } }, "type": "object" } } }, "type": "object" } } }, "type": "object" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 항목이 등록되었습니다." }, "data": { "properties": { "deleted_count": { "type": "integer", "example": 5 }, "inserted_count": { "type": "integer", "example": 8 }, "message": { "type": "string", "example": "BOM 저장 성공" } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{code}/bom/reorder": { "post": { "tags": [ "Items BOM" ], "summary": "BOM 정렬 변경", "operationId": "0e0f17b5f1a0dbc00a2e4ad25475ce72", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "items": { "type": "array", "items": { "required": [ "id", "sort_order" ], "properties": { "id": { "type": "integer", "example": 1 }, "sort_order": { "type": "integer", "example": 2 } }, "type": "object" } } }, "type": "object" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 정렬이 변경되었습니다." }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{code}/bom/categories": { "get": { "tags": [ "Items BOM" ], "summary": "BOM에서 사용 중인 카테고리 목록", "operationId": "a795eb5908b7feb6e067a08da7ed3d36", "parameters": [ { "name": "code", "in": "path", "required": true, "schema": { "type": "string" }, "example": "P-001" } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 항목 조회" }, "data": { "type": "array", "items": { "properties": { "category_id": { "type": "integer", "example": 1, "nullable": true }, "category_name": { "type": "string", "example": "조립품" }, "count": { "type": "integer", "example": 5 } }, "type": "object" } } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{id}/files": { "get": { "tags": [ "Items Files" ], "summary": "품목 파일 목록 조회", "description": "품목에 등록된 모든 파일을 field_key별로 그룹핑하여 조회합니다. 응답은 field_key를 키로 하고 파일 배열을 값으로 하는 객체입니다.", "operationId": "getItemFiles", "parameters": [ { "name": "id", "in": "path", "description": "품목 ID", "required": true, "schema": { "type": "integer", "example": 795 } }, { "name": "item_type", "in": "query", "description": "품목 유형 (FG|PT|SM|RM|CS)", "required": false, "schema": { "type": "string", "default": "FG", "enum": [ "FG", "PT", "SM", "RM", "CS" ] } }, { "name": "field_key", "in": "query", "description": "특정 field_key만 조회 (미지정 시 전체)", "required": false, "schema": { "type": "string", "example": "drawing" } } ], "responses": { "200": { "description": "파일 목록 조회 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "조회되었습니다." }, "data": { "$ref": "#/components/schemas/ItemFilesGrouped" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "품목 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "post": { "tags": [ "Items Files" ], "summary": "품목 파일 업로드", "description": "품목에 파일을 업로드합니다.\n *\n * **동작 방식**:\n * - `file_id` 없음 → 새 파일 추가\n * - `file_id` 있음 → 기존 파일 soft delete 후 새 파일 추가 (교체)\n *\n * **저장 경로**: `storage/app/tenants/{tenant_id}/items/{year}/{month}/{stored_name}`", "operationId": "uploadItemFile", "parameters": [ { "name": "id", "in": "path", "description": "품목 ID", "required": true, "schema": { "type": "integer", "example": 795 } } ], "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "required": [ "field_key", "file" ], "properties": { "field_key": { "description": "필드 키 (자유롭게 지정)", "type": "string", "example": "drawing" }, "file": { "description": "업로드할 파일 (이미지: jpg,png,gif,svg / 문서: pdf,doc,docx,xls,xlsx,hwp). 최대 20MB", "type": "string", "format": "binary" }, "file_id": { "description": "기존 파일 ID (있으면 교체, 없으면 추가)", "type": "integer", "example": 123, "nullable": true }, "item_type": { "description": "품목 유형 (FG|PT|SM|RM|CS)", "type": "string", "example": "FG" } }, "type": "object" } } } }, "responses": { "200": { "description": "파일 업로드 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "파일이 업로드되었습니다." }, "data": { "$ref": "#/components/schemas/ItemFileUploadResponse" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "품목 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/items/{id}/files/{fileId}": { "delete": { "tags": [ "Items Files" ], "summary": "품목 파일 삭제", "description": "품목의 특정 파일을 삭제합니다 (Soft Delete).", "operationId": "deleteItemFile", "parameters": [ { "name": "id", "in": "path", "description": "품목 ID", "required": true, "schema": { "type": "integer", "example": 795 } }, { "name": "fileId", "in": "path", "description": "파일 ID", "required": true, "schema": { "type": "integer", "example": 123 } }, { "name": "item_type", "in": "query", "description": "품목 유형 (FG|PT|SM|RM|CS)", "required": false, "schema": { "type": "string", "default": "FG", "enum": [ "FG", "PT", "SM", "RM", "CS" ] } } ], "responses": { "200": { "description": "파일 삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "파일이 삭제되었습니다." }, "data": { "$ref": "#/components/schemas/ItemFileDeleteResponse" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "품목 또는 파일 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/leaves": { "get": { "tags": [ "Leaves" ], "summary": "휴가 목록 조회", "description": "필터/검색/페이지네이션으로 휴가 목록을 조회합니다.", "operationId": "d63fadf1fa3008683b1f28a6d7ac69e5", "parameters": [ { "name": "user_id", "in": "query", "description": "사용자 ID 필터", "schema": { "type": "integer" } }, { "name": "status", "in": "query", "description": "상태 필터", "schema": { "type": "string", "enum": [ "pending", "approved", "rejected", "cancelled" ] } }, { "name": "leave_type", "in": "query", "description": "휴가 유형 필터", "schema": { "type": "string", "enum": [ "annual", "half_am", "half_pm", "sick", "family", "maternity", "parental" ] } }, { "name": "date_from", "in": "query", "description": "시작일 이후", "schema": { "type": "string", "format": "date" } }, { "name": "date_to", "in": "query", "description": "종료일 이전", "schema": { "type": "string", "format": "date" } }, { "name": "year", "in": "query", "description": "연도 필터", "schema": { "type": "integer" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "start_date", "enum": [ "start_date", "created_at", "status" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Leave" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 50 } }, "type": "object" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Leaves" ], "summary": "휴가 신청", "description": "새 휴가를 신청합니다. 잔여일수를 초과하거나 기간이 중복되면 실패합니다.", "operationId": "535b669d739ce8bbb34365cdba5c18cc", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LeaveCreateRequest" } } } }, "responses": { "201": { "description": "신청 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Leave" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청 (잔여일수 부족, 기간 중복 등)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/leaves/{id}": { "get": { "tags": [ "Leaves" ], "summary": "휴가 상세 조회", "description": "ID 기준 휴가 상세 정보를 조회합니다.", "operationId": "17d665f5c20e3586da106b2ba05580ee", "parameters": [ { "name": "id", "in": "path", "description": "휴가 ID", "required": true, "schema": { "type": "integer", "example": 1 } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Leave" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "휴가를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Leaves" ], "summary": "휴가 삭제", "description": "대기 상태의 휴가만 삭제 가능합니다 (소프트 삭제).", "operationId": "ec74135d6d235b8feb0342c492ad0401", "parameters": [ { "name": "id", "in": "path", "description": "휴가 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "삭제 완료" }, "data": { "type": "boolean", "example": true } }, "type": "object" } } } }, "400": { "description": "잘못된 요청 (삭제 불가 상태)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "휴가를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Leaves" ], "summary": "휴가 수정", "description": "대기 상태의 휴가만 수정 가능합니다.", "operationId": "e25a32cefd45509e1725fad0e60de6a1", "parameters": [ { "name": "id", "in": "path", "description": "휴가 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LeaveUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Leave" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청 (수정 불가 상태)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "휴가를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/leaves/{id}/approve": { "post": { "tags": [ "Leaves" ], "summary": "휴가 승인", "description": "대기 상태의 휴가를 승인합니다. 승인 시 잔여일수가 차감됩니다.", "operationId": "cb136c83008acc5b3ee9b8953ff6da6d", "parameters": [ { "name": "id", "in": "path", "description": "휴가 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "properties": { "comment": { "description": "승인 코멘트", "type": "string", "example": "승인합니다." } }, "type": "object" } } } }, "responses": { "200": { "description": "승인 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Leave" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청 (승인 불가 상태)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "휴가를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/leaves/{id}/reject": { "post": { "tags": [ "Leaves" ], "summary": "휴가 반려", "description": "대기 상태의 휴가를 반려합니다.", "operationId": "f05f46d0ed53181adfa4636b2d67c374", "parameters": [ { "name": "id", "in": "path", "description": "휴가 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "reason" ], "properties": { "reason": { "description": "반려 사유", "type": "string", "example": "인원 부족으로 반려합니다." } }, "type": "object" } } } }, "responses": { "200": { "description": "반려 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Leave" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청 (반려 불가 상태)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "휴가를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/leaves/{id}/cancel": { "post": { "tags": [ "Leaves" ], "summary": "휴가 취소", "description": "승인된 휴가를 취소합니다. 취소 시 잔여일수가 복구됩니다.", "operationId": "7277e505faa941231796365b1e7bd813", "parameters": [ { "name": "id", "in": "path", "description": "휴가 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "properties": { "reason": { "description": "취소 사유", "type": "string", "example": "일정 변경으로 취소합니다." } }, "type": "object" } } } }, "responses": { "200": { "description": "취소 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Leave" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청 (취소 불가 상태)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "휴가를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/leaves/balance": { "get": { "tags": [ "Leaves" ], "summary": "내 잔여 휴가 조회", "description": "로그인한 사용자의 잔여 휴가를 조회합니다.", "operationId": "7e643dd6ba425bd927cb99ee24352ccb", "parameters": [ { "name": "year", "in": "query", "description": "연도 (미지정시 현재 연도)", "schema": { "type": "integer", "example": 2024 } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/LeaveBalance" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Leaves" ], "summary": "잔여 휴가 설정", "description": "특정 사용자의 연간 휴가일수를 설정합니다 (관리자 전용).", "operationId": "8437a0a4189681054d6fa943e4c6ef11", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LeaveBalanceSetRequest" } } } }, "responses": { "200": { "description": "설정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/LeaveBalance" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/leaves/balance/{userId}": { "get": { "tags": [ "Leaves" ], "summary": "특정 사용자 잔여 휴가 조회", "description": "특정 사용자의 잔여 휴가를 조회합니다 (관리자 전용).", "operationId": "896f788dfb060aff220cb1d6f55ab0f5", "parameters": [ { "name": "userId", "in": "path", "description": "사용자 ID", "required": true, "schema": { "type": "integer", "example": 10 } }, { "name": "year", "in": "query", "description": "연도 (미지정시 현재 연도)", "schema": { "type": "integer", "example": 2024 } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/LeaveBalance" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "사용자를 찾을 수 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/menus": { "get": { "tags": [ "Menu" ], "summary": "메뉴 목록 조회", "description": "테넌트 범위 내(또는 공용) 메뉴 목록을 반환합니다. parent_id/is_active/hidden 필터 지원.", "operationId": "fa63e168640744cc184888fe82051ac4", "parameters": [ { "name": "parent_id", "in": "query", "required": false, "schema": { "type": "integer", "example": 0 } }, { "name": "is_active", "in": "query", "required": false, "schema": { "type": "integer", "example": 1 } }, { "name": "hidden", "in": "query", "required": false, "schema": { "type": "integer", "example": 0 } } ], "responses": { "200": { "description": "목록 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/MenuList" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Menu" ], "summary": "메뉴 등록", "description": "새로운 메뉴를 등록합니다.", "operationId": "5fe416f19dda7cb6e15aa76bdc4d704a", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MenuCreateRequest" } } } }, "responses": { "200": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "id": { "type": "integer", "example": 12 } }, "type": "object" } }, "type": "object" } ] } } } }, "400": { "description": "파라미터 오류", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/menus/{id}": { "get": { "tags": [ "Menu" ], "summary": "메뉴 단건 조회", "description": "ID로 메뉴 상세 정보를 조회합니다.", "operationId": "be7ff567d6145885ab351a1ac41e7e96", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 12 } } ], "responses": { "200": { "description": "단건 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Menu" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Menu" ], "summary": "메뉴 삭제(소프트 삭제)", "description": "지정한 메뉴를 소프트 삭제합니다.", "operationId": "7c61cdda0ea3c8df41b3d2670c2d1d63", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 12 } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "id": { "type": "integer", "example": 12 }, "deleted": { "type": "boolean", "example": true } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Menu" ], "summary": "메뉴 수정", "description": "기존 메뉴 정보를 수정합니다(부분 수정).", "operationId": "f2cbb557b50bb7a48a079f1d0b7c1410", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 12 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MenuUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "id": { "type": "integer", "example": 12 } }, "type": "object" } }, "type": "object" } ] } } } }, "400": { "description": "파라미터 오류", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/menus/reorder": { "post": { "tags": [ "Menu" ], "summary": "메뉴 정렬 변경", "description": "여러 메뉴의 sort_order를 일괄 변경합니다.", "operationId": "2d9a1d92a4f3ac0cf7935ec6f2b9468c", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "array", "items": { "properties": { "id": { "type": "integer", "example": 12 }, "sort_order": { "type": "integer", "example": 1 } }, "type": "object" } } } } }, "responses": { "200": { "description": "정렬 변경 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "400": { "description": "파라미터 오류", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/menus/{id}/toggle": { "post": { "tags": [ "Menu" ], "summary": "메뉴 상태 토글", "description": "is_active / hidden / is_external 중 하나 이상을 토글합니다.", "operationId": "6a5ceb946801b2f41ea34b27962f1430", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 12 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "is_active": { "type": "boolean", "example": true, "nullable": true }, "hidden": { "type": "boolean", "example": false, "nullable": true }, "is_external": { "type": "boolean", "example": false, "nullable": true } }, "type": "object" } } } }, "responses": { "200": { "description": "토글 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "400": { "description": "파라미터 오류", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/permissions/departments/{id}/menu-matrix": { "get": { "tags": [ "Permission" ], "summary": "부서 메뉴 권한 매트릭스", "description": "부서 기준으로 메뉴 트리 및 액션별 권한 상태(allow/deny/none)를 반환합니다.", "operationId": "85fb0e51a3a8748b420ebb0d63b50c39", "parameters": [ { "name": "id", "in": "path", "description": "부서 ID", "required": true, "schema": { "type": "integer", "example": 1 } } ], "responses": { "200": { "description": "부서 메뉴 권한 매트릭스 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/MenuMatrixPayload" } }, "type": "object" } ] } } } }, "404": { "description": "부서 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/permissions/roles/{id}/menu-matrix": { "get": { "tags": [ "Permission" ], "summary": "역할 메뉴 권한 매트릭스", "description": "스파티 기본 Role 기준으로 메뉴 트리 및 액션별 권한 상태(allow/deny/none)를 반환합니다.", "operationId": "d648f486aeea20d16e83814e9cefeab0", "parameters": [ { "name": "id", "in": "path", "description": "역할 ID", "required": true, "schema": { "type": "integer", "example": 3 } } ], "responses": { "200": { "description": "역할 메뉴 권한 매트릭스 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/MenuMatrixPayload" } }, "type": "object" } ] } } } }, "404": { "description": "역할 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/permissions/users/{id}/menu-matrix": { "get": { "tags": [ "Permission" ], "summary": "사용자 메뉴 권한 매트릭스", "description": "사용자 기준으로 메뉴 트리 및 액션별 권한 상태(allow/deny/none)를 반환합니다.", "operationId": "9cf071661b609d756812d9daec2b475a", "parameters": [ { "name": "id", "in": "path", "description": "사용자 ID", "required": true, "schema": { "type": "integer", "example": 12 } } ], "responses": { "200": { "description": "유저 메뉴 권한 매트릭스 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/MenuMatrixPayload" } }, "type": "object" } ] } } } }, "404": { "description": "사용자 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/boards/{code}/posts": { "get": { "tags": [ "Post" ], "summary": "게시글 목록", "operationId": "c6cc5b85c66d15de29bb94970197ad1a", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } }, { "name": "page", "in": "query", "schema": { "type": "integer", "example": 1 } }, { "name": "per_page", "in": "query", "schema": { "type": "integer", "example": 15 } }, { "name": "search", "in": "query", "description": "제목/내용 검색", "schema": { "type": "string" } }, { "name": "is_notice", "in": "query", "schema": { "type": "boolean" } }, { "name": "status", "in": "query", "schema": { "type": "string", "enum": [ "draft", "published", "hidden" ] } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/PostPagination" } }, "type": "object" } ] } } } }, "404": { "description": "게시판 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Post" ], "summary": "게시글 작성", "operationId": "e0d50ec87841f405089d96dcb2c3c6cd", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostCreateRequest" } } } }, "responses": { "200": { "description": "작성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Post" } }, "type": "object" } ] } } } }, "400": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "게시판 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/boards/{code}/posts/{id}": { "get": { "tags": [ "Post" ], "summary": "게시글 상세 (조회수 자동 증가)", "operationId": "4292ff85d107a9c3e322513fa3f32334", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } }, { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Post" } }, "type": "object" } ] } } } }, "404": { "description": "게시글 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Post" ], "summary": "게시글 수정", "operationId": "eb6f20b211ca34a75a19465717fb873a", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } }, { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PostUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Post" } }, "type": "object" } ] } } } }, "404": { "description": "게시글 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Post" ], "summary": "게시글 삭제", "operationId": "f12617c508511d0dbeb394de8470f601", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } }, { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "게시글 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/boards/{code}/posts/{postId}/comments": { "get": { "tags": [ "Post" ], "summary": "댓글 목록", "operationId": "dda488a994ba04de43f559b3c8a78a78", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } }, { "name": "postId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Comment" } } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Post" ], "summary": "댓글 작성", "operationId": "bdc380836cc3bd8c93e80f6d79629cb3", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } }, { "name": "postId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentCreateRequest" } } } }, "responses": { "200": { "description": "작성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Comment" } }, "type": "object" } ] } } } }, "400": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/boards/{code}/posts/{postId}/comments/{commentId}": { "put": { "tags": [ "Post" ], "summary": "댓글 수정", "description": "본인이 작성한 댓글만 수정 가능", "operationId": "d5e48e8baa1c9c802876b302fc657e5a", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } }, { "name": "postId", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "commentId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentCreateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Comment" } }, "type": "object" } ] } } } }, "404": { "description": "댓글 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Post" ], "summary": "댓글 삭제", "description": "본인이 작성한 댓글만 삭제 가능 (상태가 deleted로 변경됨)", "operationId": "dfa905aa32155bae3d34500791683add", "parameters": [ { "name": "code", "in": "path", "description": "게시판 코드", "required": true, "schema": { "type": "string" } }, { "name": "postId", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "commentId", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "댓글 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/pricing": { "get": { "tags": [ "Pricing" ], "summary": "단가 목록 조회", "operationId": "d0c45f022ce680907a0e5194c36a9c8e", "parameters": [ { "name": "q", "in": "query", "description": "검색어 (supplier, note)", "schema": { "type": "string" } }, { "name": "item_type_code", "in": "query", "schema": { "type": "string", "enum": [ "PRODUCT", "MATERIAL" ] } }, { "name": "item_id", "in": "query", "schema": { "type": "integer" } }, { "name": "client_group_id", "in": "query", "description": "고객그룹 ID (빈값/null=기본가만)", "schema": { "type": "string" } }, { "name": "status", "in": "query", "schema": { "type": "string", "enum": [ "draft", "active", "inactive", "finalized" ] } }, { "name": "valid_at", "in": "query", "description": "특정 날짜에 유효한 단가만", "schema": { "type": "string", "format": "date" } }, { "name": "size", "in": "query", "schema": { "type": "integer", "example": 20 } }, { "name": "page", "in": "query", "schema": { "type": "integer", "example": 1 } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/PricePagination" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Pricing" ], "summary": "단가 등록", "operationId": "a7142814e8ac6a5ebb0417187a3da5fa", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PriceStoreRequest" } } } }, "responses": { "200": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Price" } }, "type": "object" } ] } } } }, "400": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/pricing/{id}": { "get": { "tags": [ "Pricing" ], "summary": "단가 상세 조회", "operationId": "3a0cd5212bf5b1741d3e83eb279fb6af", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Price" } }, "type": "object" } ] } } } }, "404": { "description": "미존재", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Pricing" ], "summary": "단가 수정", "description": "확정(finalized) 상태의 단가는 수정 불가", "operationId": "0a47b824316ab662a9aa338d5d2cc672", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PriceUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Price" } }, "type": "object" } ] } } } }, "400": { "description": "수정 불가 (확정된 단가)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Pricing" ], "summary": "단가 삭제 (soft)", "description": "확정(finalized) 상태의 단가는 삭제 불가", "operationId": "fd9e703b7f871268d17151f70f3e7be7", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "400": { "description": "삭제 불가", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/pricing/{id}/finalize": { "post": { "tags": [ "Pricing" ], "summary": "단가 확정", "description": "단가를 확정 상태로 변경 (확정 후 수정/삭제 불가)", "operationId": "886e5004c124aade48047fbdda33b88e", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "확정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Price" } }, "type": "object" } ] } } } }, "400": { "description": "확정 불가", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/pricing/by-items": { "post": { "tags": [ "Pricing" ], "summary": "품목별 단가 현황 조회", "description": "여러 품목의 현재 유효한 단가를 한번에 조회", "operationId": "541dfcb106b5f58dc82c137a1003d1b2", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PriceByItemsRequest" } } } }, "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/PriceByItemsResult" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/pricing/{id}/revisions": { "get": { "tags": [ "Pricing" ], "summary": "변경 이력 조회", "operationId": "b77a3681c94a58b580a48e6aef4a2d20", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "size", "in": "query", "schema": { "type": "integer", "example": 20 } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer" }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/PriceRevision" } }, "total": { "type": "integer" } }, "type": "object" } }, "type": "object" } ] } } } }, "404": { "description": "단가 미존재", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/pricing/cost": { "get": { "tags": [ "Pricing" ], "summary": "원가 조회", "description": "품목의 원가를 조회. 자재는 수입검사 입고단가 우선, 없으면 표준원가 사용", "operationId": "71eb592eaaec7382e327672e1c19fe31", "parameters": [ { "name": "item_type_code", "in": "query", "required": true, "schema": { "type": "string", "enum": [ "PRODUCT", "MATERIAL" ] } }, { "name": "item_id", "in": "query", "required": true, "schema": { "type": "integer" } }, { "name": "date", "in": "query", "description": "기준일 (미지정시 오늘)", "schema": { "type": "string", "format": "date" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/PriceCostResult" } }, "type": "object" } ] } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/purchases": { "get": { "tags": [ "Purchases" ], "summary": "매입 목록 조회", "description": "매입 목록을 조회합니다.", "operationId": "6328e8d97ba6083bf2e7b85af22de477", "parameters": [ { "name": "search", "in": "query", "description": "검색어 (매입번호, 거래처명, 적요)", "schema": { "type": "string" } }, { "name": "start_date", "in": "query", "description": "시작일", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "description": "종료일", "schema": { "type": "string", "format": "date" } }, { "name": "client_id", "in": "query", "description": "거래처 ID", "schema": { "type": "integer" } }, { "name": "status", "in": "query", "description": "상태", "schema": { "type": "string", "enum": [ "draft", "confirmed" ] } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "purchase_date", "enum": [ "purchase_date", "total_amount", "created_at" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Purchase" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 50 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Purchases" ], "summary": "매입 등록", "description": "새로운 매입을 등록합니다. 매입번호는 자동 생성됩니다.", "operationId": "26c6e18ab65f31b177a7fa5ad896f3fd", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PurchaseCreateRequest" } } } }, "responses": { "201": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Purchase" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/purchases/summary": { "get": { "tags": [ "Purchases" ], "summary": "매입 요약 조회", "description": "기간별 매입 요약을 조회합니다.", "operationId": "33f48e74780b1207cffafb1f2592c302", "parameters": [ { "name": "start_date", "in": "query", "description": "시작일", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "description": "종료일", "schema": { "type": "string", "format": "date" } }, { "name": "client_id", "in": "query", "description": "거래처 ID", "schema": { "type": "integer" } }, { "name": "status", "in": "query", "description": "상태", "schema": { "type": "string", "enum": [ "draft", "confirmed" ] } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/PurchaseSummary" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/purchases/{id}": { "get": { "tags": [ "Purchases" ], "summary": "매입 상세 조회", "description": "매입 상세 정보를 조회합니다.", "operationId": "c169312b0c60e0a39bcb5128c8cfe9f3", "parameters": [ { "name": "id", "in": "path", "description": "매입 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Purchase" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "매입 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Purchases" ], "summary": "매입 수정", "description": "매입 정보를 수정합니다. 임시저장(draft) 상태에서만 수정 가능합니다.", "operationId": "809858a5b2098c38c53771b050c0747b", "parameters": [ { "name": "id", "in": "path", "description": "매입 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PurchaseUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Purchase" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청 또는 수정 불가", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "매입 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Purchases" ], "summary": "매입 삭제", "description": "매입을 삭제합니다. 임시저장(draft) 상태에서만 삭제 가능합니다. (Soft Delete)", "operationId": "c7479e37feb9ebbb5d4823601e742b2a", "parameters": [ { "name": "id", "in": "path", "description": "매입 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "400": { "description": "삭제 불가", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "매입 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/purchases/{id}/confirm": { "post": { "tags": [ "Purchases" ], "summary": "매입 확정", "description": "매입을 확정합니다. 임시저장(draft) 상태에서만 확정 가능합니다.", "operationId": "1292bc07194f58d85e84ebca40676bc2", "parameters": [ { "name": "id", "in": "path", "description": "매입 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "확정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Purchase" } }, "type": "object" } ] } } } }, "400": { "description": "확정 불가", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "매입 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/quotes": { "get": { "tags": [ "Quote" ], "summary": "견적 목록 조회", "operationId": "82ac3b11d1dcef2b7064b43c24778f1d", "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer" } }, { "name": "size", "in": "query", "schema": { "type": "integer" } }, { "name": "q", "in": "query", "description": "검색어", "schema": { "type": "string" } }, { "name": "status", "in": "query", "schema": { "type": "string", "enum": [ "draft", "sent", "approved", "rejected", "finalized", "converted" ] } }, { "name": "product_category", "in": "query", "schema": { "type": "string", "enum": [ "SCREEN", "STEEL" ] } }, { "name": "client_id", "in": "query", "schema": { "type": "integer" } }, { "name": "date_from", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "date_to", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "sort_by", "in": "query", "schema": { "type": "string" } }, { "name": "sort_order", "in": "query", "schema": { "type": "string", "enum": [ "asc", "desc" ] } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "$ref": "#/components/schemas/QuotePagination" } }, "type": "object" } } } } }, "security": [ { "BearerAuth": [] } ] }, "post": { "tags": [ "Quote" ], "summary": "견적 생성", "operationId": "27bcbb099432b853d3a4a91030c297a3", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteCreateRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "$ref": "#/components/schemas/Quote" } }, "type": "object" } } } } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/{id}": { "get": { "tags": [ "Quote" ], "summary": "견적 상세 조회", "operationId": "e86828ba7568ca7cdeb05a857281a92d", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "$ref": "#/components/schemas/Quote" } }, "type": "object" } } } }, "404": { "description": "견적 없음" } }, "security": [ { "BearerAuth": [] } ] }, "put": { "tags": [ "Quote" ], "summary": "견적 수정", "operationId": "4a3bdb36c509c8fa0d8be4544c621bed", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteUpdateRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "$ref": "#/components/schemas/Quote" } }, "type": "object" } } } }, "400": { "description": "수정 불가 상태" }, "404": { "description": "견적 없음" } }, "security": [ { "BearerAuth": [] } ] }, "delete": { "tags": [ "Quote" ], "summary": "견적 삭제", "operationId": "2c61ff50bf238605bcb26e31af0365b0", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "성공" }, "400": { "description": "삭제 불가 상태" }, "404": { "description": "견적 없음" } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/bulk": { "delete": { "tags": [ "Quote" ], "summary": "견적 일괄 삭제", "operationId": "2cb260b6bdf3d0b7ab43a499d93f4806", "requestBody": { "required": true, "content": { "application/json": { "schema": { "properties": { "ids": { "type": "array", "items": { "type": "integer" }, "example": [ 1, 2, 3 ] } }, "type": "object" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "properties": { "deleted_count": { "type": "integer", "example": 3 } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/{id}/finalize": { "post": { "tags": [ "Quote" ], "summary": "견적 확정", "operationId": "3085281f5b1966c8eb8a4f88215eeee0", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "$ref": "#/components/schemas/Quote" } }, "type": "object" } } } }, "400": { "description": "확정 불가 상태" } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/{id}/cancel-finalize": { "post": { "tags": [ "Quote" ], "summary": "견적 확정 취소", "operationId": "a89b46f8d6b4366d8d39583f4bc4b31c", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "$ref": "#/components/schemas/Quote" } }, "type": "object" } } } }, "400": { "description": "취소 불가 상태" } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/{id}/convert": { "post": { "tags": [ "Quote" ], "summary": "수주 전환", "operationId": "905dd95c0b3651400a6ce30a52107192", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "$ref": "#/components/schemas/Quote" } }, "type": "object" } } } }, "400": { "description": "전환 불가 상태" } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/number/preview": { "get": { "tags": [ "Quote" ], "summary": "견적번호 미리보기", "operationId": "9815bdc6b377335f8dd9b7017ff74188", "parameters": [ { "name": "product_category", "in": "query", "schema": { "type": "string", "enum": [ "SCREEN", "STEEL" ] } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "$ref": "#/components/schemas/QuoteNumberPreview" } }, "type": "object" } } } } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/calculation/schema": { "get": { "tags": [ "Quote" ], "summary": "자동산출 입력 스키마 조회", "operationId": "ad2429664e7f274203988a9cf00fee85", "parameters": [ { "name": "product_category", "in": "query", "schema": { "type": "string", "enum": [ "SCREEN", "STEEL" ] } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "description": "제품별 입력 스키마", "type": "object" } }, "type": "object" } } } } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/calculate": { "post": { "tags": [ "Quote" ], "summary": "자동산출 실행", "operationId": "a0b24ede12ae615f82cf290b39a90056", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteCalculateRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "$ref": "#/components/schemas/QuoteCalculationResult" } }, "type": "object" } } } } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/{id}/pdf": { "post": { "tags": [ "Quote" ], "summary": "견적서 PDF 생성", "operationId": "8695ae7c229ebb9457ae23635b8b41c6", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "properties": { "quote_id": { "type": "integer" }, "quote_number": { "type": "string" }, "filename": { "type": "string" }, "path": { "type": "string" }, "generated_at": { "type": "string" } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/{id}/send/email": { "post": { "tags": [ "Quote" ], "summary": "견적서 이메일 발송", "operationId": "c19c79cb7d87b69a3eb639a81b2953d3", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteSendEmailRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "properties": { "success": { "type": "boolean" }, "send_log": { "type": "object" }, "quote_status": { "type": "string" } }, "type": "object" } }, "type": "object" } } } }, "400": { "description": "수신자 정보 없음" } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/{id}/send/kakao": { "post": { "tags": [ "Quote" ], "summary": "견적서 카카오톡 발송", "operationId": "63ff336459cb8e1e26274951c44fafc8", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": false, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteSendKakaoRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "properties": { "success": { "type": "boolean" }, "send_log": { "type": "object" }, "quote_status": { "type": "string" } }, "type": "object" } }, "type": "object" } } } }, "400": { "description": "수신자 정보 없음" } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/quotes/{id}/send/history": { "get": { "tags": [ "Quote" ], "summary": "발송 이력 조회", "operationId": "30fdd2dac9a56408dc5e61e535d39bc0", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": { "properties": { "quote_id": { "type": "integer" }, "quote_number": { "type": "string" }, "history": { "type": "array", "items": { "type": "object" } } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "BearerAuth": [] } ] } }, "/api/v1/refresh": { "post": { "tags": [ "Auth" ], "summary": "토큰 갱신 (리프레시 토큰으로 새로운 액세스 토큰 발급)", "description": "리프레시 토큰을 사용하여 새로운 액세스 토큰과 리프레시 토큰을 발급받습니다. 리프레시 토큰은 사용 후 폐기되며 새로운 리프레시 토큰이 발급됩니다.", "operationId": "025d45031d3459003752d08ffa008936", "requestBody": { "required": true, "content": { "application/json": { "schema": { "required": [ "refresh_token" ], "properties": { "refresh_token": { "description": "리프레시 토큰", "type": "string", "example": "2|def456uvw789" } }, "type": "object" } } } }, "responses": { "200": { "description": "토큰 갱신 성공", "content": { "application/json": { "schema": { "properties": { "message": { "type": "string", "example": "토큰이 갱신되었습니다" }, "access_token": { "description": "새로운 액세스 토큰", "type": "string", "example": "3|ghi789rst012" }, "refresh_token": { "description": "새로운 리프레시 토큰", "type": "string", "example": "4|jkl012mno345" }, "token_type": { "description": "토큰 타입", "type": "string", "example": "Bearer" }, "expires_in": { "description": "액세스 토큰 만료 시간 (초 단위, null이면 무제한)", "type": "integer", "example": 7200, "nullable": true }, "expires_at": { "description": "액세스 토큰 만료 시각 (null이면 무제한)", "type": "string", "example": "2025-11-10 18:00:00", "nullable": true } }, "type": "object" } } } }, "401": { "description": "리프레시 토큰이 유효하지 않거나 만료됨", "content": { "application/json": { "schema": { "properties": { "error": { "type": "string", "example": "리프레시 토큰이 유효하지 않거나 만료되었습니다" }, "error_code": { "description": "에러 코드", "type": "string", "example": "TOKEN_EXPIRED" } }, "type": "object" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] } ] } }, "/api/v1/register": { "post": { "tags": [ "Auth" ], "summary": "회원가입 및 테넌트 생성", "description": "신규 회원가입과 동시에 새로운 테넌트(회사)를 생성합니다. 사용자는 자동으로 system_manager 역할이 부여되며 모든 테넌트 메뉴 권한을 갖습니다.", "operationId": "register", "requestBody": { "description": "회원가입 정보", "required": true, "content": { "application/json": { "schema": { "required": [ "user_id", "name", "email", "password", "password_confirmation", "company_name", "business_num" ], "properties": { "user_id": { "description": "사용자 아이디 (영문, 숫자, _, - 만 허용)", "type": "string", "example": "john_doe" }, "name": { "description": "사용자 이름", "type": "string", "example": "홍길동" }, "email": { "description": "이메일 주소", "type": "string", "format": "email", "example": "john@example.com" }, "phone": { "description": "전화번호 (선택)", "type": "string", "example": "010-1234-5678", "nullable": true }, "password": { "description": "비밀번호 (최소 8자)", "type": "string", "format": "password", "example": "password123!" }, "password_confirmation": { "description": "비밀번호 확인", "type": "string", "format": "password", "example": "password123!" }, "position": { "description": "직책 (선택)", "type": "string", "example": "개발팀장", "nullable": true }, "company_name": { "description": "회사명", "type": "string", "example": "(주)테크컴퍼니" }, "business_num": { "description": "사업자등록번호 (000-00-00000 형식)", "type": "string", "example": "123-45-67890" }, "company_scale": { "description": "회사 규모 (선택)", "type": "string", "example": "중소기업", "nullable": true }, "industry": { "description": "업종 (선택)", "type": "string", "example": "IT/소프트웨어", "nullable": true } }, "type": "object" } } } }, "responses": { "200": { "description": "회원가입 성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "회원가입이 완료되었습니다" }, "data": { "properties": { "user": { "properties": { "id": { "type": "integer", "example": 1 }, "user_id": { "type": "string", "example": "john_doe" }, "name": { "type": "string", "example": "홍길동" }, "email": { "type": "string", "example": "john@example.com" }, "phone": { "type": "string", "example": "010-1234-5678", "nullable": true }, "options": { "properties": { "position": { "type": "string", "example": "개발팀장" } }, "type": "object", "nullable": true } }, "type": "object" }, "tenant": { "properties": { "id": { "type": "integer", "example": 1 }, "company_name": { "type": "string", "example": "(주)테크컴퍼니" }, "business_num": { "type": "string", "example": "123-45-67890" }, "tenant_st_code": { "description": "테넌트 상태 (trial: 데모, active: 정식, none: 비활성)", "type": "string", "example": "trial" }, "options": { "properties": { "company_scale": { "type": "string", "example": "중소기업" }, "industry": { "type": "string", "example": "IT/소프트웨어" } }, "type": "object", "nullable": true } }, "type": "object" }, "menus": { "description": "생성된 테넌트의 기본 메뉴 목록 (9개: 대시보드, 기초정보관리, 제품관리, 거래처관리, BOM관리, 시스템관리, 사용자관리, 권한관리, 부서관리)", "type": "array", "items": { "properties": { "id": { "description": "메뉴 ID", "type": "integer", "example": 1 }, "parent_id": { "description": "상위 메뉴 ID (최상위 메뉴는 null)", "type": "integer", "example": null, "nullable": true }, "name": { "description": "메뉴명", "type": "string", "example": "대시보드" }, "url": { "description": "메뉴 URL", "type": "string", "example": "/dashboard" }, "icon": { "description": "메뉴 아이콘", "type": "string", "example": "dashboard" }, "sort_order": { "description": "정렬 순서", "type": "integer", "example": 1 }, "is_external": { "description": "외부 링크 여부 (0: 내부, 1: 외부)", "type": "integer", "example": 0 }, "external_url": { "description": "외부 링크 URL", "type": "string", "example": null, "nullable": true } }, "type": "object" } }, "roles": { "description": "생성된 역할 목록 (시스템 관리자 역할 1개)", "type": "array", "items": { "properties": { "id": { "description": "역할 ID", "type": "integer", "example": 1 }, "name": { "description": "역할명", "type": "string", "example": "system_manager" }, "description": { "description": "역할 설명", "type": "string", "example": "시스템 관리자" } }, "type": "object" } } }, "type": "object" } }, "type": "object" } } } }, "422": { "description": "유효성 검증 실패", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": false }, "message": { "type": "string", "example": "유효성 검증에 실패했습니다" }, "errors": { "properties": { "user_id": { "type": "array", "items": { "type": "string", "example": "이미 사용 중인 아이디입니다" } }, "business_num": { "type": "array", "items": { "type": "string", "example": "사업자등록번호 형식이 올바르지 않습니다 (000-00-00000)" } } }, "type": "object" } }, "type": "object" } } } }, "500": { "description": "서버 오류", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": false }, "message": { "type": "string", "example": "회원가입 처리 중 오류가 발생했습니다" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [] } ] } }, "/api/v1/reports/daily": { "get": { "tags": [ "Reports" ], "summary": "일일 일보 조회", "description": "매일 전일의 입출금 및 매출 매입 현황을 자동 집계합니다.", "operationId": "2b52cd3062a01d839fbd5651a6509699", "parameters": [ { "name": "date", "in": "query", "description": "기준일 (YYYY-MM-DD, 기본값: 오늘)", "required": false, "schema": { "type": "string", "format": "date", "example": "2025-01-15" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "데이터를 조회했습니다." }, "data": { "$ref": "#/components/schemas/DailyReport" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "유효성 검사 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "BearerAuth": [] }, { "ApiKeyAuth": [] } ] } }, "/api/v1/reports/daily/export": { "get": { "tags": [ "Reports" ], "summary": "일일 일보 엑셀 다운로드", "description": "일일 일보를 엑셀 파일로 다운로드합니다.", "operationId": "7d160b5be3e708fb1c92165e14b5291f", "parameters": [ { "name": "date", "in": "query", "description": "기준일 (YYYY-MM-DD, 기본값: 오늘)", "required": false, "schema": { "type": "string", "format": "date", "example": "2025-01-15" } } ], "responses": { "200": { "description": "엑셀 파일", "content": { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": { "schema": { "type": "string", "format": "binary" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "유효성 검사 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "BearerAuth": [] }, { "ApiKeyAuth": [] } ] } }, "/api/v1/reports/expense-estimate": { "get": { "tags": [ "Reports" ], "summary": "지출 예상 내역서 조회", "description": "예상 지출 금액 및 일정을 조회합니다.", "operationId": "c617a94b5734b5e3e239f3dee061a3a7", "parameters": [ { "name": "year_month", "in": "query", "description": "기준 연월 (YYYY-MM, 기본값: 이번달)", "required": false, "schema": { "type": "string", "example": "2025-01" } } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "데이터를 조회했습니다." }, "data": { "$ref": "#/components/schemas/ExpenseEstimate" } }, "type": "object" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "유효성 검사 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "BearerAuth": [] }, { "ApiKeyAuth": [] } ] } }, "/api/v1/reports/expense-estimate/export": { "get": { "tags": [ "Reports" ], "summary": "지출 예상 내역서 엑셀 다운로드", "description": "지출 예상 내역서를 엑셀 파일로 다운로드합니다.", "operationId": "a16ff50bce1523e2f152814a5680b15a", "parameters": [ { "name": "year_month", "in": "query", "description": "기준 연월 (YYYY-MM, 기본값: 이번달)", "required": false, "schema": { "type": "string", "example": "2025-01" } } ], "responses": { "200": { "description": "엑셀 파일", "content": { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": { "schema": { "type": "string", "format": "binary" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "유효성 검사 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "BearerAuth": [] }, { "ApiKeyAuth": [] } ] } }, "/api/v1/roles": { "get": { "tags": [ "Role" ], "summary": "역할 목록 조회", "description": "테넌트 범위 내 역할 목록을 페이징으로 반환합니다. (q로 이름/설명 검색)", "operationId": "2fe3440eb56182754caf817600b13375", "parameters": [ { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "example": 1 } }, { "name": "size", "in": "query", "required": false, "schema": { "type": "integer", "example": 10 } }, { "name": "q", "in": "query", "required": false, "schema": { "type": "string", "example": "read" } } ], "responses": { "200": { "description": "목록 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "per_page": { "type": "integer", "example": 10 }, "total": { "type": "integer", "example": 2 }, "data": { "$ref": "#/components/schemas/RoleList" } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Role" ], "summary": "역할 생성", "description": "새로운 역할을 생성합니다.", "operationId": "137c09897991824572c39bbef8ee85ef", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RoleCreateRequest" } } } }, "responses": { "200": { "description": "생성 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Role" } }, "type": "object" } ] } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/roles/{id}": { "get": { "tags": [ "Role" ], "summary": "역할 단건 조회", "description": "ID로 역할 상세를 조회합니다.", "operationId": "f7844d6fdc979ad0811cc55059a7aabf", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } } ], "responses": { "200": { "description": "단건 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Role" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Role" ], "summary": "역할 삭제", "description": "지정한 역할을 삭제합니다.", "operationId": "5ce8deb4dabfaeb888d86d328478f40c", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "patch": { "tags": [ "Role" ], "summary": "역할 수정", "description": "기존 역할 정보를 부분 수정합니다.", "operationId": "6e5662bbe051b78ef095bbb4885fa392", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer", "example": 3 } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RoleUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Role" } }, "type": "object" } ] } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/roles/{id}/permissions": { "get": { "tags": [ "RolePermission" ], "summary": "역할의 퍼미션 목록 조회", "description": "해당 역할에 현재 부여된 퍼미션 목록을 반환합니다.", "operationId": "06d579f4daa2119810017c03f0a55350", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 3 } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/PermissionList" } }, "type": "object" } ] } } } }, "404": { "description": "역할 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "RolePermission" ], "summary": "역할에 퍼미션 부여", "description": "퍼미션 이름 배열 또는 메뉴ID+액션 조합으로 역할에 권한을 부여합니다.", "operationId": "d0c6c69cf73d38115a7ac9a53d585fe2", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 3 } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RolePermissionGrantRequest" } } } }, "responses": { "200": { "description": "부여 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "역할/퍼미션 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "RolePermission" ], "summary": "역할에서 퍼미션 회수", "description": "퍼미션 이름 배열 또는 메뉴ID+액션 조합으로 권한을 회수합니다.", "operationId": "373fb4fa8fb9b1cffd43296fcb6a9252", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 3 } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RolePermissionRevokeRequest" } } } }, "responses": { "200": { "description": "회수 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "역할/퍼미션 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/roles/{id}/permissions/sync": { "put": { "tags": [ "RolePermission" ], "summary": "역할의 퍼미션 동기화(교체)", "description": "전달된 목록으로 역할의 권한을 완전히 교체합니다.", "operationId": "dff84cb79d7100d55cd5036d450afcf7", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 3 } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RolePermissionSyncRequest" } } } }, "responses": { "200": { "description": "동기화 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "역할/퍼미션 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/sales": { "get": { "tags": [ "Sales" ], "summary": "매출 목록 조회", "description": "매출 목록을 조회합니다.", "operationId": "4589943f22b258faef10d690dd53a47c", "parameters": [ { "name": "search", "in": "query", "description": "검색어 (매출번호, 거래처명, 적요)", "schema": { "type": "string" } }, { "name": "start_date", "in": "query", "description": "시작일", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "description": "종료일", "schema": { "type": "string", "format": "date" } }, { "name": "client_id", "in": "query", "description": "거래처 ID", "schema": { "type": "integer" } }, { "name": "status", "in": "query", "description": "상태", "schema": { "type": "string", "enum": [ "draft", "confirmed", "invoiced" ] } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "sale_date", "enum": [ "sale_date", "total_amount", "created_at" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Sale" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 50 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Sales" ], "summary": "매출 등록", "description": "새로운 매출을 등록합니다. 매출번호는 자동 생성됩니다.", "operationId": "bdaa539a642425fb4e7e247439f8af90", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SaleCreateRequest" } } } }, "responses": { "201": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Sale" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/sales/summary": { "get": { "tags": [ "Sales" ], "summary": "매출 요약 조회", "description": "기간별 매출 요약을 조회합니다.", "operationId": "a654f9f21749cf00d622ec4d74730682", "parameters": [ { "name": "start_date", "in": "query", "description": "시작일", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "description": "종료일", "schema": { "type": "string", "format": "date" } }, { "name": "client_id", "in": "query", "description": "거래처 ID", "schema": { "type": "integer" } }, { "name": "status", "in": "query", "description": "상태", "schema": { "type": "string", "enum": [ "draft", "confirmed", "invoiced" ] } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/SaleSummary" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/sales/{id}": { "get": { "tags": [ "Sales" ], "summary": "매출 상세 조회", "description": "매출 상세 정보를 조회합니다.", "operationId": "d05a641ae26c22d781f4f7bcf1b540b7", "parameters": [ { "name": "id", "in": "path", "description": "매출 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Sale" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "매출 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Sales" ], "summary": "매출 수정", "description": "매출 정보를 수정합니다. 임시저장(draft) 상태에서만 수정 가능합니다.", "operationId": "b8e8cb979b6c1364788b59a3383c99de", "parameters": [ { "name": "id", "in": "path", "description": "매출 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SaleUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Sale" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청 또는 수정 불가", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "매출 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Sales" ], "summary": "매출 삭제", "description": "매출을 삭제합니다. 임시저장(draft) 상태에서만 삭제 가능합니다. (Soft Delete)", "operationId": "0508b3f18fdace0a41b0290596523d1f", "parameters": [ { "name": "id", "in": "path", "description": "매출 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "400": { "description": "삭제 불가", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "매출 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/sales/{id}/confirm": { "post": { "tags": [ "Sales" ], "summary": "매출 확정", "description": "매출을 확정합니다. 임시저장(draft) 상태에서만 확정 가능합니다.", "operationId": "2a43041427f693a4b52a70bcd42b8bee", "parameters": [ { "name": "id", "in": "path", "description": "매출 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "확정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Sale" } }, "type": "object" } ] } } } }, "400": { "description": "확정 불가", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "매출 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/sites": { "get": { "tags": [ "Sites" ], "summary": "현장 목록 조회", "description": "현장 목록을 조회합니다.", "operationId": "0af4a0e1ae48ca6bb16f1eb900a6a200", "parameters": [ { "name": "search", "in": "query", "description": "검색어 (현장명, 주소)", "schema": { "type": "string" } }, { "name": "is_active", "in": "query", "description": "활성화 상태 필터", "schema": { "type": "boolean" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "created_at", "enum": [ "name", "created_at" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Site" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 10 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Sites" ], "summary": "현장 등록", "description": "새로운 현장을 등록합니다.", "operationId": "b3136ceb32d6b4c90c13d30712744678", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SiteCreateRequest" } } } }, "responses": { "201": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Site" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/sites/active": { "get": { "tags": [ "Sites" ], "summary": "활성화된 현장 목록 (셀렉트박스용)", "description": "활성화된 현장 목록을 간단한 형태로 조회합니다.", "operationId": "573531c7039e50448c4fe21ea3bc4b7c", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/SiteListItem" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/sites/{id}": { "get": { "tags": [ "Sites" ], "summary": "현장 상세 조회", "description": "현장 상세 정보를 조회합니다.", "operationId": "542df1ff64c7caddb1d9c7e0b4d9db12", "parameters": [ { "name": "id", "in": "path", "description": "현장 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Site" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "현장 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Sites" ], "summary": "현장 수정", "description": "현장 정보를 수정합니다.", "operationId": "06dc51031e6997d0ec728259f1f01f80", "parameters": [ { "name": "id", "in": "path", "description": "현장 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SiteUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Site" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "현장 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Sites" ], "summary": "현장 삭제", "description": "현장을 삭제합니다. (Soft Delete)", "operationId": "a56189742641b7173f0ef73f00b74db9", "parameters": [ { "name": "id", "in": "path", "description": "현장 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "현장 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/tenants/list": { "get": { "tags": [ "Tenant" ], "summary": "테넌트 목록 조회", "description": "등록된 모든 테넌트 목록을 페이징 형태로 반환합니다.", "operationId": "1da7f46bb2cc83f9ab4421da2e9e6838", "parameters": [ { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "테넌트 목록 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/TenantPagination" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/tenants": { "get": { "tags": [ "Tenant" ], "summary": "테넌트 정보 조회", "description": "활성(현재) 테넌트의 상세 정보를 조회합니다. 필요 시 쿼리로 특정 테넌트를 확장할 수 있습니다.", "operationId": "14929529f88cd0cc131becc668d844fe", "parameters": [ { "name": "tenant_id", "in": "query", "description": "조회할 테넌트 ID (없으면 활성 테넌트)", "required": false, "schema": { "type": "integer", "example": 1 } } ], "responses": { "200": { "description": "테넌트 정보 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Tenant" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Tenant" ], "summary": "테넌트 정보 수정", "description": "기존 테넌트 정보를 수정합니다.", "operationId": "c5560747dd16ee297ef5ffefb11b0206", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TenantUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "message": { "type": "string", "example": "수정 성공" }, "data": { "$ref": "#/components/schemas/TenantBrief" } }, "type": "object" } ] } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Tenant" ], "summary": "테넌트 등록", "description": "새로운 테넌트를 등록합니다.", "operationId": "885d630533eb8264b2ccee3f2df39dfb", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TenantCreateRequest" } } } }, "responses": { "200": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "message": { "type": "string", "example": "등록 성공" }, "data": { "$ref": "#/components/schemas/TenantBrief" } }, "type": "object" } ] } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Tenant" ], "summary": "테넌트 삭제(탈퇴)", "description": "테넌트를 삭제(또는 탈퇴 처리)합니다.", "operationId": "a1a8108fd51b14f6de2e5e8a86f212b8", "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "message": { "type": "string", "example": "삭제 성공" }, "data": { "type": "object", "example": null, "nullable": true } }, "type": "object" } ] } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/tenants/restore/{tenant_id}": { "put": { "tags": [ "Tenant" ], "summary": "테넌트 복구", "description": "삭제(소프트 삭제)된 테넌트를 복구합니다.", "operationId": "d2ac0484bf09348f3634cf7f689dca39", "parameters": [ { "name": "tenant_id", "in": "path", "description": "복구할 테넌트 ID", "required": true, "schema": { "type": "integer", "example": 1 } } ], "responses": { "200": { "description": "복구 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "message": { "type": "string", "example": "복구 성공" }, "data": { "type": "object", "example": null, "nullable": true } }, "type": "object" } ] } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "데이터 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/tenant-stat-fields": { "get": { "tags": [ "TenantStatField" ], "summary": "통계 필드 목록 조회", "operationId": "3b0f97a4b8570b72cbbfeb2f36095deb", "parameters": [ { "name": "size", "in": "query", "schema": { "type": "integer", "default": 20 }, "example": 20 }, { "name": "target_table", "in": "query", "schema": { "type": "string" }, "example": "products" }, { "name": "is_critical", "in": "query", "schema": { "type": "boolean" }, "example": true }, { "name": "aggregation_type", "in": "query", "schema": { "type": "string", "enum": [ "avg", "sum", "min", "max", "count" ] }, "example": "avg" } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "통계 필드를 조회했습니다." }, "data": { "$ref": "#/components/schemas/TenantStatFieldPagination" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "post": { "tags": [ "TenantStatField" ], "summary": "통계 필드 생성", "operationId": "e4d26c117590e625184e2617d0a360ab", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TenantStatFieldCreateRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "통계 필드가 생성되었습니다." }, "data": { "$ref": "#/components/schemas/TenantStatField" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/tenant-stat-fields/{id}": { "get": { "tags": [ "TenantStatField" ], "summary": "통계 필드 단건 조회", "operationId": "029ad663de43792a9f6d7a4fe5a14db4", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "통계 필드를 조회했습니다." }, "data": { "$ref": "#/components/schemas/TenantStatField" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "delete": { "tags": [ "TenantStatField" ], "summary": "통계 필드 삭제", "operationId": "8a3fb8a793e4b57b61fba24174ff7b2b", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "통계 필드가 삭제되었습니다." }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] }, "patch": { "tags": [ "TenantStatField" ], "summary": "통계 필드 수정", "operationId": "38f5701df6f813a3fb9ba2aa79fc37d1", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TenantStatFieldUpdateRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "통계 필드가 수정되었습니다." }, "data": { "$ref": "#/components/schemas/TenantStatField" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/tenant-stat-fields/reorder": { "post": { "tags": [ "TenantStatField" ], "summary": "통계 필드 정렬순서 변경", "operationId": "076b4f61dd96a6ee67a2ba23173af185", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TenantStatFieldReorderRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "통계 필드 정렬이 변경되었습니다." }, "data": { "type": "string", "example": "success" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/tenant-stat-fields/bulk-upsert": { "put": { "tags": [ "TenantStatField" ], "summary": "통계 필드 일괄 생성/수정", "operationId": "b4a3d4925fe3faf064f6e08c7a183c5e", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TenantStatFieldBulkUpsertRequest" } } } }, "responses": { "200": { "description": "성공", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "통계 필드가 일괄 저장되었습니다." }, "data": { "properties": { "created": { "type": "integer", "example": 3 }, "updated": { "type": "integer", "example": 2 } }, "type": "object" } }, "type": "object" } } } } }, "security": [ { "ApiKeyAuth": [], "BearerAuth": [] } ] } }, "/api/v1/users/me": { "get": { "tags": [ "User" ], "summary": "내 정보 조회", "description": "내 정보와 활성 테넌트 정보를 반환합니다.", "operationId": "25ef25873e2756fbdbb61949c897b075", "responses": { "200": { "description": "나의 정보 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/MeResponseData" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패 (헤더 누락, 유효하지 않은 토큰/키 등)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "User" ], "summary": "내 정보 수정", "description": "이름/연락처 등 프로필 정보를 수정합니다.", "operationId": "a6a81728b6ecc681b3dae955f2383a7f", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Member" } }, "type": "object" } ] } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/users/me/password": { "put": { "tags": [ "User" ], "summary": "비밀번호 변경", "description": "현재 비밀번호 검증 후 새 비밀번호로 변경합니다.", "operationId": "47151ae2bca6fb8efb58332da5a6475f", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PasswordChangeRequest" } } } }, "responses": { "204": { "description": "변경 성공(콘텐츠 없음)", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "변경 성공" }, "data": { "type": "object", "example": null, "nullable": true } }, "type": "object" } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/users/me/tenants": { "get": { "tags": [ "User" ], "summary": "내 테넌트 목록", "description": "사용자가 소속된 테넌트 목록을 반환합니다.", "operationId": "986c01610b0373b2c53c7aefd5e0df0b", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "properties": { "tenant_id": { "type": "integer", "example": 1 }, "tenant_name": { "type": "string", "example": "경동기업" }, "is_active": { "type": "boolean", "example": true } }, "type": "object" } } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/users/me/tenants/switch": { "patch": { "tags": [ "User" ], "summary": "활성 테넌트 전환", "description": "현재 세션/토큰의 활성 테넌트를 전환합니다.", "operationId": "b0225e29ba33d6093c6da5f2516925ae", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwitchTenantRequest" } } } }, "responses": { "204": { "description": "전환 성공(콘텐츠 없음)", "content": { "application/json": { "schema": { "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "변경 성공" }, "data": { "type": "object", "example": null, "nullable": true } }, "type": "object" } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/users/index": { "get": { "tags": [ "User" ], "summary": "회원 목록 조회", "description": "회원 목록을 페이징 형태로 반환합니다.", "operationId": "94b74f7bfac12fbd9f71ec3c84dcacf5", "parameters": [ { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "회원 목록 조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/MemberPagination" } }, "type": "object" } ] } } } }, "400": { "description": "필수 파라미터 누락", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "존재하지 않는 URI 또는 데이터", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/users/show/{user_no}": { "get": { "tags": [ "User" ], "summary": "회원 상세조회", "description": "user_no 기준으로 회원 상세 정보를 조회합니다.", "operationId": "82ca760bf7feaede190b26e443bf716e", "parameters": [ { "name": "user_no", "in": "path", "description": "회원 번호 (USER_NO)", "required": true, "schema": { "type": "integer", "example": 1 } } ], "responses": { "200": { "description": "회원 상세조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Member" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "회원 정보 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "405": { "description": "허용되지 않는 메서드", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/users/{id}/roles": { "get": { "tags": [ "UserRole" ], "summary": "사용자의 역할 목록 조회", "description": "해당 사용자에게 현재 부여된 역할 목록을 반환합니다.", "operationId": "c632d96413baf2736a38e0e35fd80e28", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/RoleBrief" } } }, "type": "object" } ] } } } }, "404": { "description": "사용자 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "UserRole" ], "summary": "사용자에게 역할 부여", "description": "role_names 또는 role_ids로 여러 역할을 부여합니다.", "operationId": "5862e4057633642f52e0a664b20c17a5", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserRoleGrantRequest" } } } }, "responses": { "200": { "description": "부여 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "사용자/역할 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "UserRole" ], "summary": "사용자의 역할 회수", "description": "role_names 또는 role_ids로 여러 역할을 회수합니다.", "operationId": "1b76cb9bd4edfce12039c39cbe111050", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserRoleRevokeRequest" } } } }, "responses": { "200": { "description": "회수 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "사용자/역할 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/users/{id}/roles/sync": { "put": { "tags": [ "UserRole" ], "summary": "사용자의 역할 동기화(교체)", "description": "전달된 목록으로 사용자의 역할을 완전히 교체합니다.", "operationId": "4d63bceda2b2693f83a0f465ce648f32", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" }, "example": 1 } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserRoleSyncRequest" } } } }, "responses": { "200": { "description": "동기화 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "404": { "description": "사용자/역할 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "검증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "권한 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/withdrawals": { "get": { "tags": [ "Withdrawals" ], "summary": "출금 목록 조회", "description": "출금 목록을 조회합니다.", "operationId": "6d10a744c6f689b6b56dd59d4c9dd6ed", "parameters": [ { "name": "search", "in": "query", "description": "검색어 (거래처명, 적요)", "schema": { "type": "string" } }, { "name": "start_date", "in": "query", "description": "시작일", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "description": "종료일", "schema": { "type": "string", "format": "date" } }, { "name": "client_id", "in": "query", "description": "거래처 ID", "schema": { "type": "integer" } }, { "name": "payment_method", "in": "query", "description": "결제수단", "schema": { "type": "string", "enum": [ "cash", "transfer", "card", "check" ] } }, { "name": "bank_account_id", "in": "query", "description": "계좌 ID", "schema": { "type": "integer" } }, { "name": "sort_by", "in": "query", "description": "정렬 기준", "schema": { "type": "string", "default": "withdrawal_date", "enum": [ "withdrawal_date", "amount", "created_at" ] } }, { "name": "sort_dir", "in": "query", "description": "정렬 방향", "schema": { "type": "string", "default": "desc", "enum": [ "asc", "desc" ] } }, { "$ref": "#/components/parameters/Page" }, { "$ref": "#/components/parameters/Size" } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Withdrawal" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 30 } }, "type": "object" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "post": { "tags": [ "Withdrawals" ], "summary": "출금 등록", "description": "새로운 출금을 등록합니다.", "operationId": "9960cabe8221ffa19afb98a13bdda054", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WithdrawalCreateRequest" } } } }, "responses": { "201": { "description": "등록 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Withdrawal" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/withdrawals/summary": { "get": { "tags": [ "Withdrawals" ], "summary": "출금 요약 조회", "description": "기간별 출금 요약을 조회합니다.", "operationId": "e0d8086dd19e0a3490f69c71472fb55a", "parameters": [ { "name": "start_date", "in": "query", "description": "시작일", "schema": { "type": "string", "format": "date" } }, { "name": "end_date", "in": "query", "description": "종료일", "schema": { "type": "string", "format": "date" } }, { "name": "client_id", "in": "query", "description": "거래처 ID", "schema": { "type": "integer" } }, { "name": "payment_method", "in": "query", "description": "결제수단", "schema": { "type": "string", "enum": [ "cash", "transfer", "card", "check" ] } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/WithdrawalSummary" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/withdrawals/{id}": { "get": { "tags": [ "Withdrawals" ], "summary": "출금 상세 조회", "description": "출금 상세 정보를 조회합니다.", "operationId": "2ceea8bd118c891938c53dbd920749b4", "parameters": [ { "name": "id", "in": "path", "description": "출금 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Withdrawal" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "출금 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "Withdrawals" ], "summary": "출금 수정", "description": "출금 정보를 수정합니다.", "operationId": "a75e277a5e031b12d40e13090c0c7249", "parameters": [ { "name": "id", "in": "path", "description": "출금 ID", "required": true, "schema": { "type": "integer" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WithdrawalUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/Withdrawal" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "출금 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "delete": { "tags": [ "Withdrawals" ], "summary": "출금 삭제", "description": "출금을 삭제합니다. (Soft Delete)", "operationId": "d8bb5c6ec6af37eaedcd4f815dd539a5", "parameters": [ { "name": "id", "in": "path", "description": "출금 ID", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "삭제 성공", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "출금 없음", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/settings/work": { "get": { "tags": [ "WorkSettings" ], "summary": "근무 설정 조회", "description": "테넌트의 근무 설정을 조회합니다. 설정이 없으면 기본값으로 자동 생성됩니다.", "operationId": "e5ded47dad2c8082b2f9cd6798039f15", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/WorkSetting" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "WorkSettings" ], "summary": "근무 설정 수정", "description": "테넌트의 근무 설정을 수정합니다.", "operationId": "dbde24c3c34f1586b465156d9ea0bb7a", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkSettingUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/WorkSetting" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } }, "/api/v1/settings/attendance": { "get": { "tags": [ "WorkSettings" ], "summary": "출퇴근 설정 조회", "description": "테넌트의 출퇴근 설정을 조회합니다. 설정이 없으면 기본값으로 자동 생성됩니다.", "operationId": "4c7e67a50672bd5eb8d511182869ec42", "responses": { "200": { "description": "조회 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/AttendanceSetting" } }, "type": "object" } ] } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] }, "put": { "tags": [ "WorkSettings" ], "summary": "출퇴근 설정 수정", "description": "테넌트의 출퇴근 설정을 수정합니다.", "operationId": "fec12d994b0feb6149b1fde853f569cb", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AttendanceSettingUpdateRequest" } } } }, "responses": { "200": { "description": "수정 성공", "content": { "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/ApiResponse" }, { "properties": { "data": { "$ref": "#/components/schemas/AttendanceSetting" } }, "type": "object" } ] } } } }, "400": { "description": "잘못된 요청", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "인증 실패", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "서버 에러", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } }, "security": [ { "ApiKeyAuth": [] }, { "BearerAuth": [] } ] } } }, "components": { "schemas": { "Approval": { "description": "결재 문서 정보", "properties": { "id": { "description": "문서 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "form_id": { "description": "양식 ID", "type": "integer", "example": 1 }, "drafter_id": { "description": "기안자 ID", "type": "integer", "example": 10 }, "doc_number": { "description": "문서번호", "type": "string", "example": "APR-2024-0001", "nullable": true }, "title": { "description": "제목", "type": "string", "example": "휴가 신청" }, "content": { "description": "문서 내용 JSON", "type": "object" }, "status": { "description": "상태", "type": "string", "enum": [ "draft", "pending", "approved", "rejected", "cancelled" ], "example": "pending" }, "current_step": { "description": "현재 결재 단계", "type": "integer", "example": 1, "nullable": true }, "submitted_at": { "description": "상신일시", "type": "string", "format": "date-time", "nullable": true }, "completed_at": { "description": "완료일시", "type": "string", "format": "date-time", "nullable": true }, "form": { "description": "결재 양식 정보", "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "품의서" }, "code": { "type": "string", "example": "REQUEST_01" } }, "type": "object", "nullable": true }, "drafter": { "description": "기안자 정보", "properties": { "id": { "type": "integer", "example": 10 }, "name": { "type": "string", "example": "홍길동" } }, "type": "object", "nullable": true }, "steps": { "description": "결재 단계", "type": "array", "items": { "$ref": "#/components/schemas/ApprovalStepDetail" } }, "created_at": { "type": "string", "format": "date-time", "example": "2024-01-01T09:00:00Z" }, "updated_at": { "type": "string", "format": "date-time", "example": "2024-01-01T09:00:00Z" } }, "type": "object" }, "ApprovalStepDetail": { "description": "결재 단계 상세 정보", "properties": { "id": { "type": "integer", "example": 1 }, "step_order": { "description": "단계 순서", "type": "integer", "example": 1 }, "type": { "description": "단계 유형", "type": "string", "enum": [ "approval", "agreement", "reference" ], "example": "approval" }, "user_id": { "description": "결재자 ID", "type": "integer", "example": 20 }, "status": { "description": "단계 상태", "type": "string", "enum": [ "pending", "approved", "rejected", "skipped" ], "example": "pending" }, "comment": { "description": "결재 의견", "type": "string", "nullable": true }, "acted_at": { "description": "결재일시", "type": "string", "format": "date-time", "nullable": true }, "is_read": { "description": "열람 여부 (참조)", "type": "boolean", "example": false }, "read_at": { "description": "열람일시", "type": "string", "format": "date-time", "nullable": true }, "user": { "description": "결재자 정보", "properties": { "id": { "type": "integer", "example": 20 }, "name": { "type": "string", "example": "김부장" } }, "type": "object", "nullable": true } }, "type": "object" }, "ApprovalStoreRequest": { "description": "결재 문서 생성/임시저장 요청", "required": [ "form_id", "title" ], "properties": { "form_id": { "description": "양식 ID", "type": "integer", "example": 1 }, "title": { "description": "제목", "type": "string", "example": "휴가 신청" }, "content": { "description": "문서 내용 JSON", "type": "object" }, "steps": { "description": "결재 단계 (임시저장 시 선택)", "type": "array", "items": { "properties": { "type": { "type": "string", "enum": [ "approval", "agreement", "reference" ], "example": "approval" }, "user_id": { "type": "integer", "example": 20 } }, "type": "object" } } }, "type": "object" }, "ApprovalUpdateRequest": { "description": "결재 문서 수정 요청 (임시저장 상태만 가능)", "properties": { "title": { "description": "제목", "type": "string", "example": "휴가 신청 (수정)" }, "content": { "description": "문서 내용 JSON", "type": "object" }, "steps": { "description": "결재 단계", "type": "array", "items": { "type": "object" } } }, "type": "object" }, "ApprovalSubmitRequest": { "description": "결재 상신 요청", "required": [ "steps" ], "properties": { "steps": { "description": "결재 단계 (필수)", "type": "array", "items": { "properties": { "type": { "type": "string", "enum": [ "approval", "agreement", "reference" ], "example": "approval" }, "user_id": { "type": "integer", "example": 20 } }, "type": "object" } } }, "type": "object" }, "ApprovalSummary": { "description": "결재 현황 요약", "properties": { "draft": { "description": "임시저장", "type": "integer", "example": 3 }, "pending": { "description": "진행중", "type": "integer", "example": 5 }, "approved": { "description": "승인완료", "type": "integer", "example": 10 }, "rejected": { "description": "반려", "type": "integer", "example": 2 } }, "type": "object" }, "InboxSummary": { "description": "결재함 현황 요약", "properties": { "requested": { "description": "결재 요청", "type": "integer", "example": 3 }, "scheduled": { "description": "결재 예정", "type": "integer", "example": 2 }, "completed": { "description": "결재 완료", "type": "integer", "example": 15 }, "rejected": { "description": "반려", "type": "integer", "example": 1 } }, "type": "object" }, "ApprovalForm": { "description": "결재 양식 정보", "properties": { "id": { "description": "양식 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "name": { "description": "양식명", "type": "string", "example": "품의서" }, "code": { "description": "양식 코드", "type": "string", "example": "REQUEST_01" }, "category": { "description": "카테고리", "type": "string", "enum": [ "request", "expense", "expense_estimate" ], "example": "request", "nullable": true }, "template": { "description": "템플릿 JSON", "properties": { "fields": { "type": "array", "items": { "properties": { "name": { "type": "string", "example": "title" }, "type": { "type": "string", "example": "text" }, "label": { "type": "string", "example": "제목" }, "required": { "type": "boolean", "example": true } }, "type": "object" } } }, "type": "object" }, "is_active": { "description": "활성 여부", "type": "boolean", "example": true }, "creator": { "description": "생성자 정보", "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "관리자" } }, "type": "object", "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2024-01-01T09:00:00Z" }, "updated_at": { "type": "string", "format": "date-time", "example": "2024-01-01T09:00:00Z" } }, "type": "object" }, "ApprovalFormCreateRequest": { "description": "결재 양식 생성 요청", "required": [ "name", "code", "template" ], "properties": { "name": { "description": "양식명", "type": "string", "example": "품의서" }, "code": { "description": "양식 코드 (영문, 숫자, _, -)", "type": "string", "example": "REQUEST_01" }, "category": { "description": "카테고리", "type": "string", "enum": [ "request", "expense", "expense_estimate" ], "example": "request" }, "template": { "description": "템플릿 JSON", "properties": { "fields": { "type": "array", "items": { "type": "object" } } }, "type": "object" }, "is_active": { "description": "활성 여부", "type": "boolean", "example": true } }, "type": "object" }, "ApprovalFormUpdateRequest": { "description": "결재 양식 수정 요청", "properties": { "name": { "description": "양식명", "type": "string", "example": "품의서" }, "code": { "description": "양식 코드", "type": "string", "example": "REQUEST_01" }, "category": { "description": "카테고리", "type": "string", "enum": [ "request", "expense", "expense_estimate" ] }, "template": { "description": "템플릿 JSON", "type": "object" }, "is_active": { "description": "활성 여부", "type": "boolean" } }, "type": "object" }, "ApprovalLine": { "description": "결재선 템플릿 정보", "properties": { "id": { "description": "결재선 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "name": { "description": "결재선명", "type": "string", "example": "기본 결재선" }, "steps": { "description": "결재 단계", "type": "array", "items": { "properties": { "type": { "description": "단계 유형", "type": "string", "enum": [ "approval", "agreement", "reference" ], "example": "approval" }, "user_id": { "description": "결재자 ID", "type": "integer", "example": 10 } }, "type": "object" } }, "is_default": { "description": "기본 결재선 여부", "type": "boolean", "example": false }, "step_count": { "description": "단계 수", "type": "integer", "example": 3 }, "creator": { "description": "생성자 정보", "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "관리자" } }, "type": "object", "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2024-01-01T09:00:00Z" }, "updated_at": { "type": "string", "format": "date-time", "example": "2024-01-01T09:00:00Z" } }, "type": "object" }, "ApprovalLineCreateRequest": { "description": "결재선 생성 요청", "required": [ "name", "steps" ], "properties": { "name": { "description": "결재선명", "type": "string", "example": "기본 결재선" }, "steps": { "description": "결재 단계", "type": "array", "items": { "properties": { "type": { "description": "단계 유형", "type": "string", "enum": [ "approval", "agreement", "reference" ], "example": "approval" }, "user_id": { "description": "결재자 ID", "type": "integer", "example": 10 } }, "type": "object" } }, "is_default": { "description": "기본 결재선 여부", "type": "boolean", "example": false } }, "type": "object" }, "ApprovalLineUpdateRequest": { "description": "결재선 수정 요청", "properties": { "name": { "description": "결재선명", "type": "string", "example": "기본 결재선" }, "steps": { "description": "결재 단계", "type": "array", "items": { "type": "object" } }, "is_default": { "description": "기본 결재선 여부", "type": "boolean" } }, "type": "object" }, "Attendance": { "description": "근태 정보", "properties": { "id": { "description": "근태 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "user_id": { "description": "사용자 ID", "type": "integer", "example": 10 }, "base_date": { "description": "기준일", "type": "string", "format": "date", "example": "2024-01-15" }, "status": { "description": "근태 상태", "type": "string", "enum": [ "onTime", "late", "absent", "vacation", "businessTrip", "fieldWork", "overtime", "remote" ], "example": "onTime" }, "remarks": { "description": "비고", "type": "string", "example": "외근으로 인한 지각", "nullable": true }, "check_in": { "description": "출근 시간", "type": "string", "example": "09:00:00", "nullable": true }, "check_out": { "description": "퇴근 시간", "type": "string", "example": "18:00:00", "nullable": true }, "work_minutes": { "description": "근무 시간(분)", "type": "integer", "example": 540, "nullable": true }, "overtime_minutes": { "description": "초과 근무 시간(분)", "type": "integer", "example": 60, "nullable": true }, "late_minutes": { "description": "지각 시간(분)", "type": "integer", "example": 15, "nullable": true }, "user": { "description": "사용자 정보", "properties": { "id": { "type": "integer", "example": 10 }, "name": { "type": "string", "example": "홍길동" }, "email": { "type": "string", "example": "hong@company.com" } }, "type": "object", "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2024-01-15T09:00:00Z" }, "updated_at": { "type": "string", "format": "date-time", "example": "2024-01-15T18:00:00Z" } }, "type": "object" }, "AttendanceCreateRequest": { "description": "근태 등록 요청", "required": [ "user_id", "base_date" ], "properties": { "user_id": { "description": "사용자 ID", "type": "integer", "example": 10 }, "base_date": { "description": "기준일", "type": "string", "format": "date", "example": "2024-01-15" }, "status": { "description": "근태 상태", "type": "string", "enum": [ "onTime", "late", "absent", "vacation", "businessTrip", "fieldWork", "overtime", "remote" ], "example": "onTime" }, "remarks": { "description": "비고", "type": "string", "example": "외근으로 인한 지각" }, "check_in": { "description": "출근 시간", "type": "string", "example": "09:00:00" }, "check_out": { "description": "퇴근 시간", "type": "string", "example": "18:00:00" }, "work_minutes": { "description": "근무 시간(분)", "type": "integer", "example": 540 }, "overtime_minutes": { "description": "초과 근무 시간(분)", "type": "integer", "example": 60 }, "vacation_type": { "description": "휴가 유형", "type": "string", "example": "annual" } }, "type": "object" }, "AttendanceUpdateRequest": { "description": "근태 수정 요청", "properties": { "status": { "description": "근태 상태", "type": "string", "enum": [ "onTime", "late", "absent", "vacation", "businessTrip", "fieldWork", "overtime", "remote" ], "example": "onTime" }, "remarks": { "description": "비고", "type": "string", "example": "수정된 비고" }, "check_in": { "description": "출근 시간", "type": "string", "example": "09:00:00" }, "check_out": { "description": "퇴근 시간", "type": "string", "example": "18:00:00" }, "work_minutes": { "description": "근무 시간(분)", "type": "integer", "example": 540 } }, "type": "object" }, "AttendanceMonthlyStats": { "description": "월간 근태 통계", "properties": { "year": { "type": "integer", "example": 2024 }, "month": { "type": "integer", "example": 1 }, "total_days": { "description": "총 기록 일수", "type": "integer", "example": 22 }, "by_status": { "description": "상태별 일수", "properties": { "onTime": { "type": "integer", "example": 18 }, "late": { "type": "integer", "example": 2 }, "absent": { "type": "integer", "example": 0 }, "vacation": { "type": "integer", "example": 2 }, "businessTrip": { "type": "integer", "example": 0 }, "fieldWork": { "type": "integer", "example": 0 }, "overtime": { "type": "integer", "example": 0 }, "remote": { "type": "integer", "example": 0 } }, "type": "object" }, "total_work_minutes": { "description": "총 근무 시간(분)", "type": "integer", "example": 11880 }, "total_overtime_minutes": { "description": "총 초과 근무 시간(분)", "type": "integer", "example": 300 } }, "type": "object" }, "SignupRequest": { "required": [ "user_id", "name", "email", "password" ], "properties": { "user_id": { "description": "로그인 ID (고유)", "type": "string", "maxLength": 255, "example": "userId" }, "name": { "type": "string", "maxLength": 255, "example": "Kent" }, "email": { "type": "string", "maxLength": 100, "example": "codebridge@gmail.com" }, "phone": { "type": "string", "maxLength": 30, "example": "010-4820-9104", "nullable": true }, "password": { "type": "string", "maxLength": 64, "minLength": 8, "example": "StrongPass!1234" } }, "type": "object" }, "SignupResponseData": { "properties": { "user": { "$ref": "#/components/schemas/Member" } }, "type": "object" }, "MemberBrief": { "description": "회원 요약 정보(회원가입 응답용)", "required": [ "id", "user_id", "name", "email", "phone" ], "properties": { "id": { "type": "integer", "example": 6 }, "user_id": { "type": "string", "example": "userId" }, "name": { "type": "string", "example": "Kent" }, "email": { "type": "string", "example": "codebridge1@gmail.com" }, "phone": { "type": "string", "example": "010-4820-9104" } }, "type": "object" }, "BankAccount": { "description": "계좌 정보", "properties": { "id": { "description": "계좌 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "bank_code": { "description": "은행 코드", "type": "string", "example": "088" }, "bank_name": { "description": "은행명", "type": "string", "example": "신한은행" }, "account_number": { "description": "계좌번호", "type": "string", "example": "110-123-456789" }, "account_holder": { "description": "예금주", "type": "string", "example": "주식회사 샘" }, "account_name": { "description": "계좌 별칭", "type": "string", "example": "운영계좌" }, "status": { "description": "상태", "type": "string", "enum": [ "active", "inactive" ], "example": "active" }, "assigned_user_id": { "description": "담당자 ID", "type": "integer", "example": 1, "nullable": true }, "assigned_user": { "description": "담당자 정보", "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "홍길동" } }, "type": "object", "nullable": true }, "is_primary": { "description": "대표계좌 여부", "type": "boolean", "example": true }, "created_by": { "description": "생성자 ID", "type": "integer", "example": 1, "nullable": true }, "updated_by": { "description": "수정자 ID", "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "BankAccountCreateRequest": { "description": "계좌 등록 요청", "required": [ "bank_code", "bank_name", "account_number", "account_holder", "account_name" ], "properties": { "bank_code": { "description": "은행 코드", "type": "string", "maxLength": 10, "example": "088" }, "bank_name": { "description": "은행명", "type": "string", "maxLength": 50, "example": "신한은행" }, "account_number": { "description": "계좌번호", "type": "string", "maxLength": 30, "example": "110-123-456789" }, "account_holder": { "description": "예금주", "type": "string", "maxLength": 50, "example": "주식회사 샘" }, "account_name": { "description": "계좌 별칭", "type": "string", "maxLength": 100, "example": "운영계좌" }, "status": { "description": "상태", "type": "string", "enum": [ "active", "inactive" ], "example": "active" }, "assigned_user_id": { "description": "담당자 ID", "type": "integer", "example": 1, "nullable": true }, "is_primary": { "description": "대표계좌 여부", "type": "boolean", "example": false } }, "type": "object" }, "BankAccountUpdateRequest": { "description": "계좌 수정 요청", "properties": { "bank_code": { "description": "은행 코드", "type": "string", "maxLength": 10, "example": "088" }, "bank_name": { "description": "은행명", "type": "string", "maxLength": 50, "example": "신한은행" }, "account_number": { "description": "계좌번호", "type": "string", "maxLength": 30, "example": "110-123-456789" }, "account_holder": { "description": "예금주", "type": "string", "maxLength": 50, "example": "주식회사 샘" }, "account_name": { "description": "계좌 별칭", "type": "string", "maxLength": 100, "example": "운영계좌" }, "status": { "description": "상태", "type": "string", "enum": [ "active", "inactive" ], "example": "active" }, "assigned_user_id": { "description": "담당자 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "BankAccountListItem": { "description": "계좌 목록 아이템 (셀렉트박스용)", "properties": { "id": { "description": "계좌 ID", "type": "integer", "example": 1 }, "account_name": { "description": "계좌 별칭", "type": "string", "example": "운영계좌" }, "bank_name": { "description": "은행명", "type": "string", "example": "신한은행" }, "display_number": { "description": "마스킹된 계좌번호", "type": "string", "example": "*****6789" }, "is_primary": { "description": "대표계좌 여부", "type": "boolean", "example": true } }, "type": "object" }, "Board": { "required": [ "id", "board_code", "name" ], "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID (시스템 게시판은 null)", "type": "integer", "example": 1, "nullable": true }, "is_system": { "description": "시스템 게시판 여부", "type": "boolean", "example": false }, "board_type": { "description": "게시판 유형 (notice, qna, faq 등)", "type": "string", "example": "notice", "nullable": true }, "board_code": { "description": "게시판 코드", "type": "string", "example": "NOTICE" }, "name": { "description": "게시판명", "type": "string", "example": "공지사항" }, "description": { "description": "설명", "type": "string", "example": "전사 공지사항 게시판", "nullable": true }, "editor_type": { "description": "에디터 타입", "type": "string", "enum": [ "wysiwyg", "markdown", "text" ], "example": "wysiwyg" }, "allow_files": { "description": "파일 첨부 허용", "type": "boolean", "example": true }, "max_file_count": { "description": "최대 파일 수", "type": "integer", "example": 5 }, "max_file_size": { "description": "최대 파일 크기 (KB)", "type": "integer", "example": 20480 }, "extra_settings": { "description": "추가 설정", "type": "object", "nullable": true }, "is_active": { "description": "활성 여부", "type": "boolean", "example": true }, "created_at": { "type": "string", "example": "2025-01-01 12:00:00" }, "updated_at": { "type": "string", "example": "2025-01-01 12:00:00" } }, "type": "object" }, "BoardField": { "properties": { "id": { "type": "integer", "example": 1 }, "board_id": { "type": "integer", "example": 1 }, "field_key": { "description": "필드 키", "type": "string", "example": "category" }, "field_label": { "description": "필드 라벨", "type": "string", "example": "카테고리" }, "field_type": { "description": "필드 타입", "type": "string", "example": "select" }, "is_required": { "type": "boolean", "example": false }, "sort_order": { "type": "integer", "example": 1 }, "options": { "type": "object", "nullable": true } }, "type": "object" }, "BoardCreateRequest": { "required": [ "board_code", "name" ], "properties": { "board_code": { "type": "string", "maxLength": 50, "example": "NOTICE" }, "board_type": { "type": "string", "maxLength": 50, "example": "notice", "nullable": true }, "name": { "type": "string", "maxLength": 100, "example": "공지사항" }, "description": { "type": "string", "maxLength": 500, "nullable": true }, "editor_type": { "type": "string", "enum": [ "wysiwyg", "markdown", "text" ], "example": "wysiwyg" }, "allow_files": { "type": "boolean", "example": true }, "max_file_count": { "type": "integer", "example": 5 }, "max_file_size": { "type": "integer", "example": 20480 }, "extra_settings": { "type": "object", "nullable": true }, "is_active": { "type": "boolean", "example": true } }, "type": "object" }, "BoardUpdateRequest": { "properties": { "board_code": { "type": "string", "maxLength": 50 }, "board_type": { "type": "string", "maxLength": 50, "nullable": true }, "name": { "type": "string", "maxLength": 100 }, "description": { "type": "string", "maxLength": 500, "nullable": true }, "editor_type": { "type": "string", "enum": [ "wysiwyg", "markdown", "text" ] }, "allow_files": { "type": "boolean" }, "max_file_count": { "type": "integer" }, "max_file_size": { "type": "integer" }, "extra_settings": { "type": "object", "nullable": true }, "is_active": { "type": "boolean" } }, "type": "object" }, "EstimateParametersResponse": { "required": [ "success", "message", "data" ], "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "견적 파라미터를 성공적으로 조회했습니다." }, "data": { "properties": { "model_info": { "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "스크린셔터 표준형" }, "version": { "type": "string", "example": "v1.0" }, "bom_template_id": { "type": "integer", "example": 1 } }, "type": "object" }, "company_info": { "properties": { "company_type": { "type": "string", "example": "경동기업" }, "formula_version": { "type": "string", "example": "v2.0" }, "requested_company": { "type": "string", "example": "경동기업" } }, "type": "object" }, "parameters": { "properties": { "required_parameters": { "type": "array", "items": { "properties": { "key": { "type": "string", "example": "W0" }, "label": { "type": "string", "example": "오픈사이즈 가로(mm)" }, "type": { "type": "string", "example": "integer" }, "required": { "type": "boolean", "example": true }, "min": { "type": "integer", "example": 500 }, "max": { "type": "integer", "example": 15000 } }, "type": "object" } } }, "type": "object" } }, "type": "object" } }, "type": "object" }, "CalculateBomRequest": { "required": [ "parameters" ], "properties": { "parameters": { "properties": { "W0": { "type": "integer", "example": 3000 }, "H0": { "type": "integer", "example": 2500 }, "product_type": { "type": "string", "example": "screen" } }, "type": "object" }, "company_name": { "type": "string", "example": "경동기업" } }, "type": "object" }, "CalculateBomResponse": { "required": [ "success", "message", "data" ], "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "BOM 계산이 완료되었습니다." }, "data": { "properties": { "bom_template": { "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "Main" }, "company_type": { "type": "string", "example": "경동기업" }, "formula_version": { "type": "string", "example": "v2.0" } }, "type": "object" }, "input_parameters": { "properties": { "W0": { "type": "integer", "example": 3000 }, "H0": { "type": "integer", "example": 2500 }, "product_type": { "type": "string", "example": "screen" } }, "type": "object" }, "calculated_values": { "properties": { "W1": { "type": "integer", "example": 3160 }, "H1": { "type": "integer", "example": 2850 }, "area": { "type": "number", "format": "float", "example": 9.006 }, "weight": { "type": "number", "format": "float", "example": 60.42 } }, "type": "object" }, "bom_items": { "type": "array", "items": { "properties": { "item_id": { "type": "integer", "example": 1 }, "ref_type": { "type": "string", "example": "MATERIAL" }, "ref_id": { "type": "integer", "example": 101 }, "original_qty": { "type": "integer", "example": 1 }, "calculated_qty": { "type": "integer", "example": 2 }, "is_calculated": { "type": "boolean", "example": true }, "calculation_formula": { "type": "string", "example": "bracket_quantity" } }, "type": "object" } } }, "type": "object" } }, "type": "object" }, "CompanyFormulasResponse": { "required": [ "success", "message", "data" ], "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "업체 산출식 목록을 조회했습니다." }, "data": { "properties": { "company_name": { "type": "string", "example": "경동기업" }, "total_formulas": { "type": "integer", "example": 5 }, "formulas": { "type": "array", "items": { "properties": { "type": { "type": "string", "example": "manufacturing_size" }, "version": { "type": "string", "example": "v2.0" }, "description": { "type": "string", "example": "제작사이즈 계산식" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-09-22T15:30:00Z" } }, "type": "object" } } }, "type": "object" } }, "type": "object" }, "SaveFormulaRequest": { "required": [ "formula_expression", "parameters" ], "properties": { "formula_expression": { "type": "string", "example": "bracket_quantity" }, "parameters": { "type": "array", "items": { "type": "string" }, "example": [ "W1", "H1" ] }, "conditions": { "type": "array", "items": { "type": "string" }, "example": [ "product_type=screen" ] }, "validation_rules": { "type": "array", "items": { "type": "string" }, "example": [ "W1>0", "H1>0" ] }, "description": { "type": "string", "example": "브라켓 수량 계산식" } }, "type": "object" }, "FormulaTestRequest": { "required": [ "formula_expression", "test_parameters" ], "properties": { "formula_expression": { "type": "string", "example": "bracket_quantity" }, "test_parameters": { "properties": { "W1": { "type": "integer", "example": 3000 } }, "type": "object" } }, "type": "object" }, "FormulaTestResponse": { "required": [ "success", "message", "data" ], "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string", "example": "계산식 테스트가 완료되었습니다." }, "data": { "properties": { "formula_expression": { "type": "string", "example": "bracket_quantity" }, "input_parameters": { "properties": { "W1": { "type": "integer", "example": 3000 } }, "type": "object" }, "result": { "properties": { "result": { "type": "integer", "example": 2 } }, "type": "object" }, "execution_time_ms": { "type": "number", "format": "float", "example": 1.5 } }, "type": "object" } }, "type": "object" }, "Card": { "description": "카드 정보", "properties": { "id": { "description": "카드 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "card_company": { "description": "카드사", "type": "string", "example": "삼성카드" }, "card_number_last4": { "description": "카드번호 끝 4자리", "type": "string", "example": "1234" }, "expiry_date": { "description": "유효기간 (MM/YY)", "type": "string", "example": "12/25" }, "card_name": { "description": "카드 별칭", "type": "string", "example": "법인카드 1" }, "status": { "description": "상태", "type": "string", "enum": [ "active", "inactive" ], "example": "active" }, "assigned_user_id": { "description": "담당자 ID", "type": "integer", "example": 1, "nullable": true }, "assigned_user": { "description": "담당자 정보", "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "홍길동" } }, "type": "object", "nullable": true }, "created_by": { "description": "생성자 ID", "type": "integer", "example": 1, "nullable": true }, "updated_by": { "description": "수정자 ID", "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "CardCreateRequest": { "description": "카드 등록 요청", "required": [ "card_company", "card_number", "expiry_date", "card_name" ], "properties": { "card_company": { "description": "카드사", "type": "string", "maxLength": 50, "example": "삼성카드" }, "card_number": { "description": "카드번호 (13-19자리)", "type": "string", "example": "1234567890123456" }, "expiry_date": { "description": "유효기간 (MM/YY)", "type": "string", "pattern": "^(0[1-9]|1[0-2])/\\\\d{2}$", "example": "12/25" }, "card_password": { "description": "비밀번호 앞 2자리 (선택)", "type": "string", "maxLength": 2, "example": "12" }, "card_name": { "description": "카드 별칭", "type": "string", "maxLength": 100, "example": "법인카드 1" }, "status": { "description": "상태", "type": "string", "enum": [ "active", "inactive" ], "example": "active" }, "assigned_user_id": { "description": "담당자 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "CardUpdateRequest": { "description": "카드 수정 요청", "properties": { "card_company": { "description": "카드사", "type": "string", "maxLength": 50, "example": "삼성카드" }, "card_number": { "description": "카드번호 (변경 시)", "type": "string", "example": "1234567890123456" }, "expiry_date": { "description": "유효기간 (MM/YY)", "type": "string", "pattern": "^(0[1-9]|1[0-2])/\\\\d{2}$", "example": "12/25" }, "card_password": { "description": "비밀번호 앞 2자리", "type": "string", "maxLength": 2, "example": "12" }, "card_name": { "description": "카드 별칭", "type": "string", "maxLength": 100, "example": "법인카드 1" }, "status": { "description": "상태", "type": "string", "enum": [ "active", "inactive" ], "example": "active" }, "assigned_user_id": { "description": "담당자 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "CardListItem": { "description": "카드 목록 아이템 (셀렉트박스용)", "properties": { "id": { "description": "카드 ID", "type": "integer", "example": 1 }, "card_name": { "description": "카드 별칭", "type": "string", "example": "법인카드 1" }, "card_company": { "description": "카드사", "type": "string", "example": "삼성카드" }, "display_number": { "description": "마스킹된 카드번호", "type": "string", "example": "****-1234" } }, "type": "object" }, "Category": { "required": [ "id", "name" ], "properties": { "id": { "type": "integer", "example": 12 }, "tenant_id": { "type": "integer", "example": 1 }, "parent_id": { "type": "integer", "example": null, "nullable": true }, "code": { "type": "string", "example": "ELC", "nullable": true }, "name": { "type": "string", "example": "전자" }, "description": { "type": "string", "example": null, "nullable": true }, "is_active": { "type": "integer", "example": 1 }, "sort_order": { "type": "integer", "example": 10 }, "created_at": { "type": "string", "example": "2025-08-22 10:00:00" }, "updated_at": { "type": "string", "example": "2025-08-22 10:10:00" } }, "type": "object" }, "CategoryPagination": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Category" } }, "first_page_url": { "type": "string", "example": "/api/v1/categories?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 3 }, "last_page_url": { "type": "string", "example": "/api/v1/categories?page=3" }, "links": { "type": "array", "items": { "properties": { "url": { "type": "string", "example": null, "nullable": true }, "label": { "type": "string", "example": "« Previous" }, "active": { "type": "boolean", "example": false } }, "type": "object" } }, "next_page_url": { "type": "string", "example": "/api/v1/categories?page=2", "nullable": true }, "path": { "type": "string", "example": "/api/v1/categories" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 60 } }, "type": "object" }, "CategoryCreateRequest": { "required": [ "name" ], "properties": { "parent_id": { "type": "integer", "nullable": true }, "code": { "type": "string", "maxLength": 50, "nullable": true }, "name": { "type": "string", "maxLength": 100 }, "description": { "type": "string", "maxLength": 255, "nullable": true }, "is_active": { "type": "boolean", "example": true }, "sort_order": { "type": "integer", "example": 0 } }, "type": "object" }, "CategoryUpdateRequest": { "properties": { "parent_id": { "type": "integer", "nullable": true }, "code": { "type": "string", "maxLength": 50, "nullable": true }, "name": { "type": "string", "maxLength": 100 }, "description": { "type": "string", "maxLength": 255, "nullable": true }, "is_active": { "type": "boolean" }, "sort_order": { "type": "integer" } }, "type": "object" }, "CategoryTreeNode": { "properties": { "id": { "type": "integer", "example": 1 }, "code": { "type": "string", "example": "ELC", "nullable": true }, "name": { "type": "string", "example": "전자" }, "is_active": { "type": "integer", "example": 1 }, "sort_order": { "type": "integer", "example": 0 }, "children": { "type": "array", "items": { "$ref": "#/components/schemas/CategoryTreeNode" } } }, "type": "object" }, "CategoryField": { "required": [ "id", "tenant_id", "category_id", "field_key", "field_name", "field_type" ], "properties": { "id": { "type": "integer", "example": 11 }, "tenant_id": { "type": "integer", "example": 1 }, "category_id": { "type": "integer", "example": 7 }, "field_key": { "type": "string", "example": "width" }, "field_name": { "type": "string", "example": "폭(mm)" }, "field_type": { "type": "string", "example": "number" }, "is_required": { "type": "boolean", "example": false }, "sort_order": { "type": "integer", "example": 1 }, "default_value": { "type": "string", "example": null, "nullable": true }, "options": { "description": "선택지(콤보박스 등)", "type": "object", "example": { "units": [ "mm", "cm", "m" ] }, "nullable": true }, "description": { "type": "string", "example": null, "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-08-25 10:00:00" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-08-25 10:20:00" } }, "type": "object" }, "CategoryFieldPagination": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/CategoryField" } }, "per_page": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 3 } }, "type": "object" }, "CategoryFieldCreateRequest": { "required": [ "field_key", "field_name", "field_type" ], "properties": { "field_key": { "type": "string", "example": "height" }, "field_name": { "type": "string", "example": "높이(mm)" }, "field_type": { "type": "string", "example": "number" }, "is_required": { "type": "string", "enum": [ "Y", "N" ], "example": "N" }, "sort_order": { "type": "integer", "example": 2 }, "default_value": { "type": "string", "example": null, "nullable": true }, "options": { "type": "object", "example": { "min": 0, "max": 9999, "step": 1 }, "nullable": true }, "description": { "type": "string", "example": "선택 입력", "nullable": true } }, "type": "object" }, "CategoryFieldUpdateRequest": { "properties": { "field_key": { "type": "string", "example": "height" }, "field_name": { "type": "string", "example": "높이(mm)" }, "field_type": { "type": "string", "example": "number" }, "is_required": { "type": "string", "enum": [ "Y", "N" ], "example": "Y" }, "sort_order": { "type": "integer", "example": 1 }, "default_value": { "type": "string", "example": null, "nullable": true }, "options": { "type": "object", "example": { "min": 0, "max": 9999, "step": 1 }, "nullable": true }, "description": { "type": "string", "example": null, "nullable": true } }, "type": "object" }, "CategoryFieldReorderRequest": { "type": "array", "items": { "required": [ "id", "sort_order" ], "properties": { "id": { "type": "integer", "example": 11 }, "sort_order": { "type": "integer", "example": 1 } }, "type": "object" } }, "CategoryFieldBulkUpsertRequest": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "properties": { "id": { "type": "integer", "example": null, "nullable": true }, "field_key": { "type": "string", "example": "thickness" }, "field_name": { "type": "string", "example": "두께(mm)" }, "field_type": { "type": "string", "example": "number" }, "is_required": { "type": "string", "enum": [ "Y", "N" ], "example": "N" }, "sort_order": { "type": "integer", "example": 3 }, "default_value": { "type": "string", "example": null, "nullable": true }, "options": { "type": "object", "example": { "unit": "mm" }, "nullable": true }, "description": { "type": "string", "example": null, "nullable": true } }, "type": "object" } } }, "type": "object" }, "CategoryTemplate": { "required": [ "id", "tenant_id", "category_id", "version_no", "template_json", "applied_at" ], "properties": { "id": { "type": "integer", "example": 1001 }, "tenant_id": { "type": "integer", "example": 1 }, "category_id": { "type": "integer", "example": 7 }, "version_no": { "type": "integer", "example": 3 }, "template_json": { "description": "템플릿 스냅샷", "type": "object", "example": { "fields": [ { "key": "width", "type": "number", "required": true } ] } }, "applied_at": { "type": "string", "format": "date-time", "example": "2025-08-25 11:00:00" }, "remarks": { "type": "string", "example": "높이 필드 추가", "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-08-25 10:50:00" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-08-25 11:05:00" } }, "type": "object" }, "CategoryTemplateCreateRequest": { "required": [ "version_no", "template_json", "applied_at" ], "properties": { "version_no": { "type": "integer", "example": 4 }, "template_json": { "type": "object", "example": { "fields": [ { "key": "width", "type": "number", "required": true }, { "key": "height", "type": "number", "required": false } ] } }, "applied_at": { "type": "string", "format": "date-time", "example": "2025-08-25 13:00:00" }, "remarks": { "type": "string", "example": "높이 추가 버전", "nullable": true } }, "type": "object" }, "CategoryTemplateUpdateRequest": { "properties": { "template_json": { "type": "object", "example": { "fields": [ { "key": "width", "type": "number" } ] } }, "applied_at": { "type": "string", "format": "date-time", "example": "2025-08-26 09:00:00" }, "remarks": { "type": "string", "example": "비고 수정", "nullable": true } }, "type": "object" }, "CategoryLog": { "required": [ "id", "tenant_id", "category_id", "action", "changed_at" ], "properties": { "id": { "type": "integer", "example": 501 }, "tenant_id": { "type": "integer", "example": 1 }, "category_id": { "type": "integer", "example": 7 }, "action": { "type": "string", "example": "update" }, "changed_by": { "type": "integer", "example": 1, "nullable": true }, "changed_at": { "type": "string", "format": "date-time", "example": "2025-08-25 14:00:00" }, "before_json": { "type": "object", "example": { "name": "old" }, "nullable": true }, "after_json": { "type": "object", "example": { "name": "new" }, "nullable": true }, "remarks": { "type": "string", "example": null, "nullable": true } }, "type": "object" }, "Classification": { "required": [ "id", "group", "name" ], "properties": { "id": { "type": "integer", "example": 11 }, "tenant_id": { "type": "integer", "example": 1 }, "group": { "type": "string", "example": "product_type" }, "code": { "type": "string", "example": "OUTER", "nullable": true }, "name": { "type": "string", "example": "아우터" }, "description": { "type": "string", "example": null, "nullable": true }, "is_active": { "type": "integer", "example": 1 }, "sort_order": { "type": "integer", "example": 10 }, "created_at": { "type": "string", "example": "2025-08-22 10:00:00" }, "updated_at": { "type": "string", "example": "2025-08-22 10:10:00" } }, "type": "object" }, "ClassificationPagination": { "description": "라라벨 LengthAwarePaginator 기본 구조", "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Classification" } }, "first_page_url": { "type": "string", "example": "/api/v1/classifications?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 3 }, "last_page_url": { "type": "string", "example": "/api/v1/classifications?page=3" }, "links": { "type": "array", "items": { "properties": { "url": { "type": "string", "example": null, "nullable": true }, "label": { "type": "string", "example": "« Previous" }, "active": { "type": "boolean", "example": false } }, "type": "object" } }, "next_page_url": { "type": "string", "example": "/api/v1/classifications?page=2", "nullable": true }, "path": { "type": "string", "example": "/api/v1/classifications" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 60 } }, "type": "object" }, "ClassificationCreateRequest": { "required": [ "group", "name" ], "properties": { "group": { "type": "string", "maxLength": 50, "example": "product_type" }, "code": { "type": "string", "maxLength": 50, "example": "OUTER", "nullable": true }, "name": { "type": "string", "maxLength": 100, "example": "아우터" }, "description": { "type": "string", "maxLength": 255, "nullable": true }, "is_active": { "type": "boolean", "example": true }, "sort_order": { "type": "integer", "example": 0 } }, "type": "object" }, "ClassificationUpdateRequest": { "properties": { "group": { "type": "string", "maxLength": 50 }, "code": { "type": "string", "maxLength": 50, "nullable": true }, "name": { "type": "string", "maxLength": 100 }, "description": { "type": "string", "maxLength": 255, "nullable": true }, "is_active": { "type": "boolean" }, "sort_order": { "type": "integer" } }, "type": "object" }, "Client": { "required": [ "id", "client_code", "name" ], "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "client_group_id": { "description": "고객 그룹 ID", "type": "integer", "example": 1, "nullable": true }, "client_code": { "type": "string", "example": "CLIENT_001" }, "name": { "type": "string", "example": "거래처명" }, "client_type": { "description": "거래처 유형", "type": "string", "enum": [ "매입", "매출", "매입매출" ], "example": "매입" }, "contact_person": { "type": "string", "example": "홍길동", "nullable": true }, "phone": { "type": "string", "example": "02-1234-5678", "nullable": true }, "mobile": { "description": "모바일 번호", "type": "string", "example": "010-1234-5678", "nullable": true }, "fax": { "description": "팩스 번호", "type": "string", "example": "02-1234-5679", "nullable": true }, "email": { "type": "string", "example": "client@example.com", "nullable": true }, "address": { "type": "string", "example": "서울시 강남구", "nullable": true }, "manager_name": { "description": "담당자명", "type": "string", "example": "김담당", "nullable": true }, "manager_tel": { "description": "담당자 전화", "type": "string", "example": "010-9876-5432", "nullable": true }, "system_manager": { "description": "시스템 관리자", "type": "string", "example": "박시스템", "nullable": true }, "account_id": { "description": "계정 ID", "type": "string", "example": "user123", "nullable": true }, "purchase_payment_day": { "description": "매입 결제일", "type": "string", "example": "매월 25일", "nullable": true }, "sales_payment_day": { "description": "매출 결제일", "type": "string", "example": "매월 말일", "nullable": true }, "business_no": { "description": "사업자등록번호", "type": "string", "maxLength": 20, "example": "123-45-67890", "nullable": true }, "business_type": { "description": "업태", "type": "string", "maxLength": 50, "example": "제조업", "nullable": true }, "business_item": { "description": "업종", "type": "string", "maxLength": 100, "example": "전자부품", "nullable": true }, "tax_agreement": { "description": "세금 약정 여부", "type": "boolean", "example": false }, "tax_amount": { "description": "약정 금액", "type": "number", "format": "float", "example": 1000000, "nullable": true }, "tax_start_date": { "description": "약정 시작일", "type": "string", "format": "date", "example": "2025-01-01", "nullable": true }, "tax_end_date": { "description": "약정 종료일", "type": "string", "format": "date", "example": "2025-12-31", "nullable": true }, "bad_debt": { "description": "악성채권 여부", "type": "boolean", "example": false }, "bad_debt_amount": { "description": "악성채권 금액", "type": "number", "format": "float", "example": 500000, "nullable": true }, "bad_debt_receive_date": { "description": "채권 발생일", "type": "string", "format": "date", "example": "2024-06-01", "nullable": true }, "bad_debt_end_date": { "description": "채권 만료일", "type": "string", "format": "date", "example": "2025-06-01", "nullable": true }, "bad_debt_progress": { "description": "진행 상태", "type": "string", "enum": [ "협의중", "소송중", "회수완료", "대손처리" ], "nullable": true }, "memo": { "description": "메모", "type": "string", "example": "특이사항 메모", "nullable": true }, "is_active": { "description": "활성 여부", "type": "boolean", "example": true }, "created_at": { "type": "string", "example": "2025-10-01 12:00:00" }, "updated_at": { "type": "string", "example": "2025-10-01 12:00:00" } }, "type": "object" }, "ClientPagination": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Client" } }, "first_page_url": { "type": "string", "example": "/api/v1/clients?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 3 }, "last_page_url": { "type": "string", "example": "/api/v1/clients?page=3" }, "links": { "type": "array", "items": { "properties": { "url": { "type": "string", "example": null, "nullable": true }, "label": { "type": "string", "example": "« Previous" }, "active": { "type": "boolean", "example": false } }, "type": "object" } }, "next_page_url": { "type": "string", "example": "/api/v1/clients?page=2", "nullable": true }, "path": { "type": "string", "example": "/api/v1/clients" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 50 } }, "type": "object" }, "ClientCreateRequest": { "required": [ "client_code", "name" ], "properties": { "client_group_id": { "description": "고객 그룹 ID", "type": "integer", "example": 1, "nullable": true }, "client_code": { "type": "string", "maxLength": 50, "example": "CLIENT_001" }, "name": { "type": "string", "maxLength": 100, "example": "거래처명" }, "client_type": { "description": "거래처 유형", "type": "string", "enum": [ "매입", "매출", "매입매출" ], "example": "매입", "nullable": true }, "contact_person": { "type": "string", "maxLength": 100, "example": "홍길동", "nullable": true }, "phone": { "type": "string", "maxLength": 20, "example": "02-1234-5678", "nullable": true }, "mobile": { "description": "모바일 번호", "type": "string", "maxLength": 20, "example": "010-1234-5678", "nullable": true }, "fax": { "description": "팩스 번호", "type": "string", "maxLength": 20, "example": "02-1234-5679", "nullable": true }, "email": { "type": "string", "maxLength": 100, "example": "client@example.com", "nullable": true }, "address": { "type": "string", "maxLength": 255, "example": "서울시 강남구", "nullable": true }, "manager_name": { "description": "담당자명", "type": "string", "maxLength": 50, "example": "김담당", "nullable": true }, "manager_tel": { "description": "담당자 전화", "type": "string", "maxLength": 20, "example": "010-9876-5432", "nullable": true }, "system_manager": { "description": "시스템 관리자", "type": "string", "maxLength": 50, "example": "박시스템", "nullable": true }, "account_id": { "description": "계정 ID", "type": "string", "maxLength": 50, "example": "user123", "nullable": true }, "account_password": { "description": "계정 비밀번호", "type": "string", "maxLength": 255, "example": "password123", "nullable": true }, "purchase_payment_day": { "description": "매입 결제일", "type": "string", "maxLength": 20, "example": "매월 25일", "nullable": true }, "sales_payment_day": { "description": "매출 결제일", "type": "string", "maxLength": 20, "example": "매월 말일", "nullable": true }, "business_no": { "description": "사업자등록번호", "type": "string", "maxLength": 20, "example": "123-45-67890", "nullable": true }, "business_type": { "description": "업태", "type": "string", "maxLength": 50, "example": "제조업", "nullable": true }, "business_item": { "description": "업종", "type": "string", "maxLength": 100, "example": "전자부품", "nullable": true }, "tax_agreement": { "description": "세금 약정 여부", "type": "boolean", "example": false, "nullable": true }, "tax_amount": { "description": "약정 금액", "type": "number", "format": "float", "example": 1000000, "nullable": true }, "tax_start_date": { "description": "약정 시작일", "type": "string", "format": "date", "example": "2025-01-01", "nullable": true }, "tax_end_date": { "description": "약정 종료일", "type": "string", "format": "date", "example": "2025-12-31", "nullable": true }, "bad_debt": { "description": "악성채권 여부", "type": "boolean", "example": false, "nullable": true }, "bad_debt_amount": { "description": "악성채권 금액", "type": "number", "format": "float", "example": 500000, "nullable": true }, "bad_debt_receive_date": { "description": "채권 발생일", "type": "string", "format": "date", "example": "2024-06-01", "nullable": true }, "bad_debt_end_date": { "description": "채권 만료일", "type": "string", "format": "date", "example": "2025-06-01", "nullable": true }, "bad_debt_progress": { "description": "진행 상태", "type": "string", "enum": [ "협의중", "소송중", "회수완료", "대손처리" ], "nullable": true }, "memo": { "description": "메모", "type": "string", "example": "특이사항 메모", "nullable": true }, "is_active": { "description": "활성 여부", "type": "boolean", "example": true } }, "type": "object" }, "ClientUpdateRequest": { "properties": { "client_group_id": { "description": "고객 그룹 ID", "type": "integer", "example": 1, "nullable": true }, "client_code": { "type": "string", "maxLength": 50 }, "name": { "type": "string", "maxLength": 100 }, "client_type": { "description": "거래처 유형", "type": "string", "enum": [ "매입", "매출", "매입매출" ], "nullable": true }, "contact_person": { "type": "string", "maxLength": 100, "nullable": true }, "phone": { "type": "string", "maxLength": 20, "nullable": true }, "mobile": { "description": "모바일 번호", "type": "string", "maxLength": 20, "nullable": true }, "fax": { "description": "팩스 번호", "type": "string", "maxLength": 20, "nullable": true }, "email": { "type": "string", "maxLength": 100, "nullable": true }, "address": { "type": "string", "maxLength": 255, "nullable": true }, "manager_name": { "description": "담당자명", "type": "string", "maxLength": 50, "nullable": true }, "manager_tel": { "description": "담당자 전화", "type": "string", "maxLength": 20, "nullable": true }, "system_manager": { "description": "시스템 관리자", "type": "string", "maxLength": 50, "nullable": true }, "account_id": { "description": "계정 ID", "type": "string", "maxLength": 50, "nullable": true }, "account_password": { "description": "계정 비밀번호", "type": "string", "maxLength": 255, "nullable": true }, "purchase_payment_day": { "description": "매입 결제일", "type": "string", "maxLength": 20, "nullable": true }, "sales_payment_day": { "description": "매출 결제일", "type": "string", "maxLength": 20, "nullable": true }, "business_no": { "description": "사업자등록번호", "type": "string", "maxLength": 20, "nullable": true }, "business_type": { "description": "업태", "type": "string", "maxLength": 50, "nullable": true }, "business_item": { "description": "업종", "type": "string", "maxLength": 100, "nullable": true }, "tax_agreement": { "description": "세금 약정 여부", "type": "boolean", "nullable": true }, "tax_amount": { "description": "약정 금액", "type": "number", "format": "float", "nullable": true }, "tax_start_date": { "description": "약정 시작일", "type": "string", "format": "date", "nullable": true }, "tax_end_date": { "description": "약정 종료일", "type": "string", "format": "date", "nullable": true }, "bad_debt": { "description": "악성채권 여부", "type": "boolean", "nullable": true }, "bad_debt_amount": { "description": "악성채권 금액", "type": "number", "format": "float", "nullable": true }, "bad_debt_receive_date": { "description": "채권 발생일", "type": "string", "format": "date", "nullable": true }, "bad_debt_end_date": { "description": "채권 만료일", "type": "string", "format": "date", "nullable": true }, "bad_debt_progress": { "description": "진행 상태", "type": "string", "enum": [ "협의중", "소송중", "회수완료", "대손처리" ], "nullable": true }, "memo": { "description": "메모", "type": "string", "nullable": true }, "is_active": { "description": "활성 여부", "type": "boolean" } }, "type": "object" }, "ClientGroup": { "required": [ "id", "group_code", "group_name", "price_rate" ], "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "group_code": { "type": "string", "example": "VIP" }, "group_name": { "type": "string", "example": "VIP 고객" }, "price_rate": { "description": "가격 배율 (1.0=기준가, 0.9=90%, 1.1=110%)", "type": "number", "format": "decimal", "example": 0.9 }, "is_active": { "type": "boolean", "example": true }, "created_at": { "type": "string", "example": "2025-10-01 12:00:00" }, "updated_at": { "type": "string", "example": "2025-10-01 12:00:00" } }, "type": "object" }, "ClientGroupPagination": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/ClientGroup" } }, "first_page_url": { "type": "string", "example": "/api/v1/client-groups?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 3 }, "last_page_url": { "type": "string", "example": "/api/v1/client-groups?page=3" }, "links": { "type": "array", "items": { "properties": { "url": { "type": "string", "example": null, "nullable": true }, "label": { "type": "string", "example": "« Previous" }, "active": { "type": "boolean", "example": false } }, "type": "object" } }, "next_page_url": { "type": "string", "example": "/api/v1/client-groups?page=2", "nullable": true }, "path": { "type": "string", "example": "/api/v1/client-groups" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 50 } }, "type": "object" }, "ClientGroupCreateRequest": { "required": [ "group_code", "group_name", "price_rate" ], "properties": { "group_code": { "description": "그룹 코드", "type": "string", "maxLength": 30, "example": "VIP" }, "group_name": { "description": "그룹명", "type": "string", "maxLength": 100, "example": "VIP 고객" }, "price_rate": { "description": "가격 배율 (1.0=기준가)", "type": "number", "format": "decimal", "example": 0.9 }, "is_active": { "description": "활성 여부", "type": "boolean", "example": true } }, "type": "object" }, "ClientGroupUpdateRequest": { "properties": { "group_code": { "type": "string", "maxLength": 30 }, "group_name": { "type": "string", "maxLength": 100 }, "price_rate": { "type": "number", "format": "decimal" }, "is_active": { "type": "boolean" } }, "type": "object" }, "ApiResponse": { "properties": { "success": { "description": "전역 재사용 컴포넌트 정의만 모아둔 파일입니다.", "type": "boolean", "example": true }, "message": { "type": "string", "example": "요청 성공" }, "data": { "nullable": true } }, "type": "object" }, "PaginationMeta": { "properties": { "page": { "type": "integer", "example": 1 }, "size": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 126 }, "last_page": { "type": "integer", "example": 7 } }, "type": "object" }, "User": { "required": [ "id", "name", "email" ], "properties": { "id": { "type": "integer", "example": 101 }, "tenant_id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "홍길동" }, "email": { "type": "string", "example": "hong@kdcorp.co.kr" }, "phone": { "type": "string", "example": "010-1234-5678", "nullable": true }, "is_active": { "type": "boolean", "example": true }, "roles": { "type": "array", "items": { "type": "string" }, "example": [ "admin", "manager" ] }, "created_at": { "type": "string", "example": "2025-07-20 10:22:33" }, "updated_at": { "type": "string", "example": "2025-08-01 15:00:10" } }, "type": "object" }, "LoginRequest": { "required": [ "email", "password" ], "properties": { "email": { "type": "string", "example": "hong@kdcorp.co.kr" }, "password": { "type": "string", "example": "secret1234!" } }, "type": "object" }, "TokenResponse": { "properties": { "access_token": { "type": "string", "example": "eyJhbGciOi..." }, "token_type": { "type": "string", "example": "Bearer" }, "expires_in": { "type": "integer", "example": 3600 } }, "type": "object" }, "ErrorResponse": { "description": "공통 에러 응답 포맷", "properties": { "success": { "type": "boolean", "example": false }, "message": { "type": "string", "example": "요청 실패" }, "error": { "properties": { "code": { "type": "integer", "example": 400 }, "details": { "example": null, "nullable": true } }, "type": "object" } }, "type": "object" }, "Department": { "description": "부서 상세", "required": [ "id", "name" ], "properties": { "id": { "type": "integer", "example": 7 }, "tenant_id": { "type": "integer", "example": 1 }, "code": { "type": "string", "example": "OPS", "nullable": true }, "name": { "type": "string", "example": "운영팀" }, "description": { "type": "string", "example": "서비스 운영 총괄", "nullable": true }, "is_active": { "type": "integer", "example": 1 }, "sort_order": { "type": "integer", "example": 10 }, "created_at": { "type": "string", "format": "date-time", "example": "2025-08-16 10:00:00" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-08-16 10:00:00" } }, "type": "object" }, "DepartmentBrief": { "description": "부서 요약", "required": [ "id", "name" ], "properties": { "id": { "type": "integer", "example": 7 }, "code": { "type": "string", "example": "OPS", "nullable": true }, "name": { "type": "string", "example": "운영팀" }, "is_active": { "type": "integer", "example": 1 }, "sort_order": { "type": "integer", "example": 10 } }, "type": "object" }, "DepartmentList": { "type": "array", "items": { "$ref": "#/components/schemas/DepartmentBrief" } }, "DepartmentCreateRequest": { "required": [ "name" ], "properties": { "code": { "type": "string", "example": "OPS", "nullable": true }, "name": { "type": "string", "example": "운영팀" }, "description": { "type": "string", "example": "서비스 운영 총괄", "nullable": true }, "is_active": { "type": "integer", "enum": [ 0, 1 ], "example": 1 }, "sort_order": { "type": "integer", "example": 0 } }, "type": "object" }, "DepartmentUpdateRequest": { "properties": { "code": { "type": "string", "example": "OPS2", "nullable": true }, "name": { "type": "string", "example": "운영기획팀" }, "description": { "type": "string", "example": "운영 기획/성과 관리", "nullable": true }, "is_active": { "type": "integer", "enum": [ 0, 1 ], "example": 1 }, "sort_order": { "type": "integer", "example": 5 } }, "type": "object" }, "DepartmentUserAttachRequest": { "required": [ "user_id" ], "properties": { "user_id": { "type": "integer", "example": 12 }, "is_primary": { "type": "integer", "enum": [ 0, 1 ], "example": 0, "nullable": true }, "joined_at": { "type": "string", "format": "date-time", "example": "2025-08-21 10:00:00", "nullable": true } }, "type": "object" }, "UserBrief": { "description": "부서원 요약", "required": [ "id", "name", "email" ], "properties": { "id": { "type": "integer", "example": 12 }, "name": { "type": "string", "example": "홍길동" }, "email": { "type": "string", "format": "email", "example": "hong@example.com" }, "phone": { "type": "string", "example": "010-1234-5678", "nullable": true }, "is_active": { "type": "integer", "example": 1 } }, "type": "object" }, "DepartmentPermissionUpsertSingle": { "required": [ "permission_id" ], "properties": { "permission_id": { "type": "integer", "example": 25 }, "is_allowed": { "description": "1=ALLOW, 0=DENY(차단)", "type": "integer", "enum": [ 0, 1 ], "example": 1 } }, "type": "object" }, "DepartmentPermissionUpsertMany": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/DepartmentPermissionUpsertSingle" } } }, "type": "object" }, "DepartmentPermissionRevokeSingle": { "required": [ "permission_id" ], "properties": { "permission_id": { "type": "integer", "example": 25 } }, "type": "object" }, "DepartmentPermissionRevokeMany": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/DepartmentPermissionRevokeSingle" } } }, "type": "object" }, "Deposit": { "description": "입금 정보", "properties": { "id": { "description": "입금 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "deposit_date": { "description": "입금일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1, "nullable": true }, "client_name": { "description": "비회원 거래처명", "type": "string", "example": "홍길동", "nullable": true }, "bank_account_id": { "description": "입금 계좌 ID", "type": "integer", "example": 1, "nullable": true }, "amount": { "description": "금액", "type": "number", "format": "float", "example": 1000000 }, "payment_method": { "description": "결제수단", "type": "string", "enum": [ "cash", "transfer", "card", "check" ], "example": "transfer" }, "account_code": { "description": "계정과목", "type": "string", "example": "401", "nullable": true }, "description": { "description": "적요", "type": "string", "example": "1월 매출 입금", "nullable": true }, "reference_type": { "description": "참조 유형", "type": "string", "example": "sales", "nullable": true }, "reference_id": { "description": "참조 ID", "type": "integer", "example": 1, "nullable": true }, "client": { "description": "거래처 정보", "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "(주)테스트" } }, "type": "object", "nullable": true }, "bank_account": { "description": "계좌 정보", "properties": { "id": { "type": "integer", "example": 1 }, "bank_name": { "type": "string", "example": "국민은행" }, "account_name": { "type": "string", "example": "법인통장" } }, "type": "object", "nullable": true }, "created_by": { "description": "생성자 ID", "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "DepositCreateRequest": { "description": "입금 등록 요청", "required": [ "deposit_date", "amount", "payment_method" ], "properties": { "deposit_date": { "description": "입금일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1, "nullable": true }, "client_name": { "description": "비회원 거래처명", "type": "string", "maxLength": 100, "example": "홍길동", "nullable": true }, "bank_account_id": { "description": "입금 계좌 ID", "type": "integer", "example": 1, "nullable": true }, "amount": { "description": "금액", "type": "number", "format": "float", "example": 1000000 }, "payment_method": { "description": "결제수단", "type": "string", "enum": [ "cash", "transfer", "card", "check" ], "example": "transfer" }, "account_code": { "description": "계정과목", "type": "string", "maxLength": 20, "example": "401", "nullable": true }, "description": { "description": "적요", "type": "string", "maxLength": 1000, "example": "1월 매출 입금", "nullable": true }, "reference_type": { "description": "참조 유형", "type": "string", "maxLength": 50, "example": "sales", "nullable": true }, "reference_id": { "description": "참조 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "DepositUpdateRequest": { "description": "입금 수정 요청", "properties": { "deposit_date": { "description": "입금일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1, "nullable": true }, "client_name": { "description": "비회원 거래처명", "type": "string", "maxLength": 100, "example": "홍길동", "nullable": true }, "bank_account_id": { "description": "입금 계좌 ID", "type": "integer", "example": 1, "nullable": true }, "amount": { "description": "금액", "type": "number", "format": "float", "example": 1000000 }, "payment_method": { "description": "결제수단", "type": "string", "enum": [ "cash", "transfer", "card", "check" ], "example": "transfer" }, "account_code": { "description": "계정과목", "type": "string", "maxLength": 20, "example": "401", "nullable": true }, "description": { "description": "적요", "type": "string", "maxLength": 1000, "example": "1월 매출 입금", "nullable": true }, "reference_type": { "description": "참조 유형", "type": "string", "maxLength": 50, "example": "sales", "nullable": true }, "reference_id": { "description": "참조 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "DepositSummary": { "description": "입금 요약", "properties": { "total_amount": { "description": "총 입금액", "type": "number", "format": "float", "example": 5000000 }, "total_count": { "description": "총 건수", "type": "integer", "example": 10 }, "by_payment_method": { "description": "결제수단별 합계", "properties": { "cash": { "properties": { "total": { "type": "number", "example": 1000000 }, "count": { "type": "integer", "example": 2 } }, "type": "object" }, "transfer": { "properties": { "total": { "type": "number", "example": 4000000 }, "count": { "type": "integer", "example": 8 } }, "type": "object" } }, "type": "object" } }, "type": "object" }, "DesignBomItemDiffRow": { "properties": { "ref_type": { "type": "string", "example": "MATERIAL" }, "ref_id": { "type": "integer" }, "qty": { "type": "number" }, "waste_rate": { "type": "number" }, "uom_id": { "type": "integer", "nullable": true }, "notes": { "type": "string", "nullable": true }, "sort_order": { "type": "integer" } }, "type": "object" }, "DesignModel": { "required": [ "id", "tenant_id", "code", "name" ], "properties": { "id": { "type": "integer", "example": 101 }, "tenant_id": { "type": "integer", "example": 1 }, "code": { "type": "string", "example": "KSS01" }, "name": { "type": "string", "example": "KSS 표준 모델" }, "category_id": { "type": "integer", "example": 12, "nullable": true }, "lifecycle": { "type": "string", "example": "ACTIVE", "nullable": true }, "description": { "type": "string", "example": "롤러 구조 표준 설계", "nullable": true }, "is_active": { "type": "boolean", "example": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-09-05 10:11:12" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-09-05 10:11:12" }, "deleted_at": { "type": "string", "format": "date-time", "example": null, "nullable": true } }, "type": "object" }, "DesignModelPagination": { "description": "라라벨 LengthAwarePaginator", "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/DesignModel" } }, "first_page_url": { "type": "string", "example": "/api/v1/design/models?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 5 }, "last_page_url": { "type": "string", "example": "/api/v1/design/models?page=5" }, "links": { "type": "array", "items": { "properties": { "url": { "type": "string", "example": null, "nullable": true }, "label": { "type": "string", "example": "« Previous" }, "active": { "type": "boolean", "example": false } }, "type": "object" } }, "next_page_url": { "type": "string", "example": "/api/v1/design/models?page=2", "nullable": true }, "path": { "type": "string", "example": "/api/v1/design/models" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 92 } }, "type": "object" }, "ModelVersion": { "required": [ "id", "tenant_id", "model_id", "version_no", "status" ], "properties": { "id": { "type": "integer", "example": 201 }, "tenant_id": { "type": "integer", "example": 1 }, "model_id": { "type": "integer", "example": 101 }, "version_no": { "type": "integer", "example": 1 }, "status": { "type": "string", "example": "RELEASED" }, "effective_from": { "type": "string", "format": "date-time", "example": "2025-09-05 11:00:00", "nullable": true }, "effective_to": { "type": "string", "format": "date-time", "example": null, "nullable": true }, "notes": { "type": "string", "example": "초도 릴리즈", "nullable": true }, "is_active": { "type": "boolean", "example": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" }, "deleted_at": { "type": "string", "format": "date-time", "example": null, "nullable": true } }, "type": "object" }, "BomTemplate": { "required": [ "id", "tenant_id", "model_version_id", "name" ], "properties": { "id": { "type": "integer", "example": 301 }, "tenant_id": { "type": "integer", "example": 1 }, "model_version_id": { "type": "integer", "example": 201 }, "name": { "type": "string", "example": "Main" }, "is_primary": { "type": "boolean", "example": true }, "notes": { "type": "string", "example": "표준 템플릿", "nullable": true }, "items_count": { "description": "withCount(items) 사용 시", "type": "integer", "example": 3 }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" }, "deleted_at": { "type": "string", "format": "date-time", "example": null, "nullable": true } }, "type": "object" }, "BomTemplateItem": { "required": [ "id", "tenant_id", "bom_template_id", "ref_type", "ref_id", "qty" ], "properties": { "id": { "type": "integer", "example": 401 }, "tenant_id": { "type": "integer", "example": 1 }, "bom_template_id": { "type": "integer", "example": 301 }, "ref_type": { "type": "string", "enum": [ "MATERIAL", "PRODUCT" ], "example": "MATERIAL" }, "ref_id": { "type": "integer", "example": 10101 }, "qty": { "type": "number", "format": "double", "example": 2 }, "waste_rate": { "type": "number", "format": "double", "example": 0 }, "uom_id": { "type": "integer", "example": null, "nullable": true }, "notes": { "type": "string", "example": "프레임용", "nullable": true }, "sort_order": { "type": "integer", "example": 10 }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "BomTemplateItemReplaceRequest": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "required": [ "ref_type", "ref_id", "qty" ], "properties": { "ref_type": { "type": "string", "enum": [ "MATERIAL", "PRODUCT" ], "example": "MATERIAL" }, "ref_id": { "type": "integer", "example": 101 }, "qty": { "type": "number", "format": "double", "example": 2 }, "waste_rate": { "type": "number", "format": "double", "example": 0, "nullable": true }, "uom_id": { "type": "integer", "example": null, "nullable": true }, "notes": { "type": "string", "example": "프레임용", "nullable": true }, "sort_order": { "type": "integer", "example": 10 } }, "type": "object" } } }, "type": "object" }, "Employee": { "description": "사원 정보", "properties": { "id": { "description": "사원 프로필 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "user_id": { "description": "사용자 ID", "type": "integer", "example": 10 }, "name": { "description": "이름", "type": "string", "example": "홍길동" }, "email": { "description": "이메일", "type": "string", "example": "hong@company.com" }, "phone": { "description": "연락처", "type": "string", "example": "010-1234-5678" }, "department_id": { "description": "부서 ID", "type": "integer", "example": 5, "nullable": true }, "department_name": { "description": "부서명", "type": "string", "example": "개발팀", "nullable": true }, "position_key": { "description": "직급 키", "type": "string", "example": "manager", "nullable": true }, "job_title_key": { "description": "직책 키", "type": "string", "example": "developer", "nullable": true }, "work_location_key": { "description": "근무지 키", "type": "string", "example": "seoul_hq", "nullable": true }, "employment_type_key": { "description": "고용형태 키", "type": "string", "example": "fulltime", "nullable": true }, "employee_status": { "description": "고용상태", "type": "string", "enum": [ "active", "leave", "resigned" ], "example": "active" }, "manager_user_id": { "description": "상급자 ID", "type": "integer", "example": 5, "nullable": true }, "display_name": { "description": "표시명", "type": "string", "example": "홍길동 매니저", "nullable": true }, "profile_photo_path": { "description": "프로필 사진 경로", "type": "string", "example": "/photos/hong.jpg", "nullable": true }, "employee_code": { "description": "사원번호", "type": "string", "example": "EMP-001", "nullable": true }, "hire_date": { "description": "입사일", "type": "string", "format": "date", "example": "2020-03-15", "nullable": true }, "rank": { "description": "호봉", "type": "string", "example": "G3", "nullable": true }, "work_type": { "description": "근무형태", "type": "string", "enum": [ "regular", "daily", "temporary", "external" ], "example": "regular", "nullable": true }, "has_account": { "description": "시스템 계정 보유 여부", "type": "boolean", "example": true }, "is_active": { "description": "활성 상태", "type": "boolean", "example": true }, "created_at": { "type": "string", "format": "date-time", "example": "2020-03-15T09:00:00Z" }, "updated_at": { "type": "string", "format": "date-time", "example": "2024-01-10T14:30:00Z" } }, "type": "object" }, "EmployeeCreateRequest": { "description": "사원 등록 요청", "required": [ "name", "email" ], "properties": { "user_id": { "description": "사용자 ID (로그인 ID)", "type": "string", "example": "hong001" }, "name": { "description": "이름", "type": "string", "example": "홍길동" }, "email": { "description": "이메일", "type": "string", "format": "email", "example": "hong@company.com" }, "phone": { "description": "연락처", "type": "string", "example": "010-1234-5678" }, "password": { "description": "초기 비밀번호 (미입력시 계정 미생성)", "type": "string", "example": "Password123!" }, "is_active": { "description": "활성 상태", "type": "boolean", "example": true }, "department_id": { "description": "부서 ID", "type": "integer", "example": 5 }, "position_key": { "description": "직급 키", "type": "string", "example": "manager" }, "job_title_key": { "description": "직책 키", "type": "string", "example": "developer" }, "work_location_key": { "description": "근무지 키", "type": "string", "example": "seoul_hq" }, "employment_type_key": { "description": "고용형태 키", "type": "string", "example": "fulltime" }, "employee_status": { "description": "고용상태", "type": "string", "enum": [ "active", "leave", "resigned" ], "example": "active" }, "manager_user_id": { "description": "상급자 ID", "type": "integer", "example": 5 }, "display_name": { "description": "표시명", "type": "string", "example": "홍길동 매니저" }, "employee_code": { "description": "사원번호", "type": "string", "example": "EMP-001" }, "resident_number": { "description": "주민번호 (암호화)", "type": "string", "example": "encrypted_value" }, "gender": { "description": "성별", "type": "string", "enum": [ "male", "female" ], "example": "male" }, "address": { "properties": { "zipCode": { "type": "string", "example": "06234" }, "address1": { "type": "string", "example": "서울시 강남구 테헤란로 123" }, "address2": { "type": "string", "example": "10층 1001호" } }, "type": "object" }, "salary": { "description": "연봉", "type": "number", "format": "float", "example": 50000000 }, "hire_date": { "description": "입사일", "type": "string", "format": "date", "example": "2020-03-15" }, "rank": { "description": "호봉", "type": "string", "example": "G3" }, "bank_account": { "properties": { "bankName": { "type": "string", "example": "국민은행" }, "accountNumber": { "type": "string", "example": "123-456-789012" }, "accountHolder": { "type": "string", "example": "홍길동" } }, "type": "object" }, "work_type": { "description": "근무형태", "type": "string", "enum": [ "regular", "daily", "temporary", "external" ], "example": "regular" }, "contract_info": { "properties": { "start_date": { "type": "string", "format": "date", "example": "2024-01-01" }, "end_date": { "type": "string", "format": "date", "example": "2024-12-31" }, "external_company": { "type": "string", "example": "파트너사" } }, "type": "object" } }, "type": "object" }, "EmployeeUpdateRequest": { "description": "사원 수정 요청", "properties": { "name": { "type": "string", "example": "홍길동" }, "email": { "type": "string", "format": "email", "example": "hong@company.com" }, "phone": { "type": "string", "example": "010-1234-5678" }, "is_active": { "type": "boolean", "example": true }, "department_id": { "type": "integer", "example": 5 }, "position_key": { "type": "string", "example": "manager" }, "job_title_key": { "type": "string", "example": "developer" }, "work_location_key": { "type": "string", "example": "seoul_hq" }, "employment_type_key": { "type": "string", "example": "fulltime" }, "employee_status": { "type": "string", "enum": [ "active", "leave", "resigned" ], "example": "active" }, "manager_user_id": { "type": "integer", "example": 5 }, "display_name": { "type": "string", "example": "홍길동 매니저" }, "employee_code": { "type": "string", "example": "EMP-001" }, "hire_date": { "type": "string", "format": "date", "example": "2020-03-15" }, "rank": { "type": "string", "example": "G3" }, "work_type": { "type": "string", "enum": [ "regular", "daily", "temporary", "external" ], "example": "regular" } }, "type": "object" }, "EmployeeStats": { "description": "사원 통계", "properties": { "total": { "description": "전체 사원 수", "type": "integer", "example": 150 }, "active": { "description": "재직 중", "type": "integer", "example": 140 }, "leave": { "description": "휴직 중", "type": "integer", "example": 5 }, "resigned": { "description": "퇴직", "type": "integer", "example": 5 }, "has_account": { "description": "시스템 계정 보유", "type": "integer", "example": 130 }, "no_account": { "description": "시스템 계정 미보유", "type": "integer", "example": 20 } }, "type": "object" }, "EntityRelationship": { "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "group_id": { "description": "그룹 ID (1: 품목관리)", "type": "integer", "example": 1 }, "parent_type": { "type": "string", "enum": [ "page", "section" ], "example": "page" }, "parent_id": { "type": "integer", "example": 1 }, "child_type": { "type": "string", "enum": [ "section", "field", "bom" ], "example": "section" }, "child_id": { "type": "integer", "example": 1 }, "order_no": { "type": "integer", "example": 0 }, "metadata": { "type": "object", "example": null, "nullable": true }, "created_at": { "type": "string", "example": "2025-11-26 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-26 10:00:00" } }, "type": "object" }, "LinkEntityRequest": { "required": [ "child_id" ], "properties": { "child_id": { "description": "연결할 엔티티 ID", "type": "integer", "example": 1 }, "order_no": { "description": "정렬 순서", "type": "integer", "example": 0 } }, "type": "object" }, "ReorderRelationshipsRequest": { "required": [ "parent_type", "parent_id", "ordered_items" ], "properties": { "parent_type": { "type": "string", "enum": [ "page", "section" ], "example": "page" }, "parent_id": { "type": "integer", "example": 1 }, "ordered_items": { "type": "array", "items": { "properties": { "child_type": { "type": "string", "example": "section" }, "child_id": { "type": "integer", "example": 1 } }, "type": "object" } } }, "type": "object" }, "PageStructure": { "properties": { "page": { "$ref": "#/components/schemas/ItemPage" }, "sections": { "type": "array", "items": { "properties": { "section": { "$ref": "#/components/schemas/ItemSection" }, "order_no": { "type": "integer", "example": 0 }, "fields": { "type": "array", "items": { "type": "object" } }, "bom_items": { "type": "array", "items": { "type": "object" } } }, "type": "object" } }, "direct_fields": { "type": "array", "items": { "properties": { "field": { "$ref": "#/components/schemas/ItemField" }, "order_no": { "type": "integer", "example": 0 } }, "type": "object" } } }, "type": "object" }, "FieldEffective": { "description": "전역정의 + 테넌트설정이 merge된 필드 효과값", "required": [ "field_key", "label", "data_type", "input_type", "enabled" ], "properties": { "field_key": { "description": "Fields(효과값/설정) 스키마", "type": "string", "example": "position" }, "label": { "type": "string", "example": "직급" }, "data_type": { "type": "string", "example": "string" }, "input_type": { "type": "string", "example": "select" }, "option_source": { "type": "string", "example": "tenant_list", "nullable": true }, "option_payload": { "type": "object", "nullable": true }, "storage_area": { "type": "string", "example": "tenant_profile" }, "storage_key": { "type": "string", "example": "position_key" }, "is_core": { "type": "boolean", "example": false }, "enabled": { "type": "boolean", "example": true }, "required": { "type": "boolean", "example": false }, "sort_order": { "type": "integer", "example": 10 }, "option_group_id": { "type": "integer", "example": 5, "nullable": true }, "code_group": { "type": "string", "example": "employment_type", "nullable": true } }, "type": "object" }, "FieldSettingUpdateRequest": { "properties": { "enabled": { "type": "boolean", "example": true }, "required": { "type": "boolean", "example": false }, "sort_order": { "type": "integer", "example": 20 }, "option_group_id": { "type": "integer", "example": 5, "nullable": true }, "code_group": { "type": "string", "example": "department", "nullable": true } }, "type": "object" }, "FieldSettingBulkItem": { "required": [ "field_key" ], "properties": { "field_key": { "type": "string", "example": "position" }, "enabled": { "type": "boolean", "example": true }, "required": { "type": "boolean", "example": false }, "sort_order": { "type": "integer", "example": 10 }, "option_group_id": { "type": "integer", "example": 5, "nullable": true }, "code_group": { "type": "string", "example": "employment_type", "nullable": true } }, "type": "object" }, "FieldSettingBulkRequest": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/FieldSettingBulkItem" } } }, "type": "object" }, "OptionGroup": { "required": [ "id", "group_key", "name" ], "properties": { "id": { "description": "Option Group/Value 스키마", "type": "integer", "example": 3 }, "tenant_id": { "type": "integer", "example": 1 }, "group_key": { "type": "string", "example": "position" }, "name": { "type": "string", "example": "직급표(2025)" }, "description": { "type": "string", "example": "본사 기준", "nullable": true } }, "type": "object" }, "OptionGroupCreateRequest": { "required": [ "group_key", "name" ], "properties": { "group_key": { "type": "string", "example": "job_title" }, "name": { "type": "string", "example": "직책" }, "description": { "type": "string", "example": "영업조직용", "nullable": true } }, "type": "object" }, "OptionGroupUpdateRequest": { "properties": { "group_key": { "type": "string", "example": "job_title" }, "name": { "type": "string", "example": "직책(개정)" }, "description": { "type": "string", "example": "영업/CS 통합", "nullable": true } }, "type": "object" }, "OptionValue": { "required": [ "id", "group_id", "value_key", "value_label" ], "properties": { "id": { "type": "integer", "example": 10 }, "group_id": { "type": "integer", "example": 3 }, "value_key": { "type": "string", "example": "manager" }, "value_label": { "type": "string", "example": "과장" }, "sort_order": { "type": "integer", "example": 30 }, "is_active": { "type": "boolean", "example": true } }, "type": "object" }, "OptionValueCreateRequest": { "required": [ "value_key", "value_label" ], "properties": { "value_key": { "type": "string", "example": "director" }, "value_label": { "type": "string", "example": "이사" }, "sort_order": { "type": "integer", "example": 40 }, "is_active": { "type": "boolean", "example": true } }, "type": "object" }, "OptionValueUpdateRequest": { "properties": { "value_key": { "type": "string", "example": "director" }, "value_label": { "type": "string", "example": "이사" }, "sort_order": { "type": "integer", "example": 45 }, "is_active": { "type": "boolean", "example": false } }, "type": "object" }, "OptionValueReorderRequest": { "required": [ "items" ], "properties": { "items": { "description": "정렬 대상 목록", "type": "array", "items": { "required": [ "id", "sort_order" ], "properties": { "id": { "type": "integer", "example": 10 }, "sort_order": { "type": "integer", "example": 100 } }, "type": "object" } } }, "type": "object" }, "Profile": { "description": "테넌트별 사용자 프로필", "required": [ "tenant_id", "user_id" ], "properties": { "id": { "description": "Profiles 스키마", "type": "integer", "example": 101 }, "tenant_id": { "type": "integer", "example": 1 }, "user_id": { "type": "integer", "example": 55 }, "department_id": { "type": "integer", "example": 12, "nullable": true }, "position_key": { "type": "string", "example": "manager", "nullable": true }, "job_title_key": { "type": "string", "example": "lead_pm", "nullable": true }, "work_location_key": { "type": "string", "example": "seoul_hq", "nullable": true }, "employment_type_key": { "type": "string", "example": "regular", "nullable": true }, "manager_user_id": { "type": "integer", "example": 77, "nullable": true }, "display_name": { "type": "string", "example": "김철수(영업1팀)", "nullable": true }, "profile_photo_path": { "type": "string", "example": "/uploads/tenant/1/avatar/55.png", "nullable": true }, "json_extra": { "type": "object", "example": { "employee_no": "A-001", "entry_date": "2023-01-02", "work_type": "hybrid" }, "nullable": true } }, "type": "object" }, "ProfileUpdateRequest": { "description": "프로필 수정 시, field_key: value 형태", "type": "object", "example": { "position": "manager", "employee_no": "A-001", "entry_date": "2023-01-02", "work_type": "hybrid" } }, "ProfilePagination": { "description": "LengthAwarePaginator 구조", "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Profile" } }, "total": { "type": "integer", "example": 3 }, "per_page": { "type": "integer", "example": 20 }, "path": { "type": "string", "example": "/api/v1/profiles" } }, "type": "object" }, "File": { "description": "파일 모델", "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "display_name": { "description": "사용자에게 표시되는 파일명", "type": "string", "example": "계약서.pdf" }, "stored_name": { "description": "실제 저장된 파일명", "type": "string", "example": "a1b2c3d4e5f6g7h8.pdf" }, "folder_id": { "type": "integer", "example": 1, "nullable": true }, "is_temp": { "type": "boolean", "example": false }, "file_path": { "type": "string", "example": "1/product/2025/01/a1b2c3d4e5f6g7h8.pdf" }, "file_size": { "description": "파일 크기 (bytes)", "type": "integer", "example": 1024000 }, "mime_type": { "type": "string", "example": "application/pdf" }, "file_type": { "type": "string", "enum": [ "document", "image", "excel", "archive" ], "example": "document" }, "document_id": { "type": "integer", "example": null, "nullable": true }, "document_type": { "type": "string", "example": null, "nullable": true }, "uploaded_by": { "type": "integer", "example": 1 }, "deleted_by": { "type": "integer", "example": null, "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-01-01T00:00:00Z" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-01-01T00:00:00Z" }, "deleted_at": { "type": "string", "format": "date-time", "example": null, "nullable": true } }, "type": "object" }, "FileShareLink": { "description": "파일 공유 링크", "properties": { "token": { "description": "64자 공유 토큰", "type": "string", "example": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" }, "url": { "type": "string", "example": "http://api.sam.kr/api/v1/files/share/a1b2c3d4" }, "expires_at": { "type": "string", "format": "date-time", "example": "2025-01-02T00:00:00Z" } }, "type": "object" }, "StorageUsage": { "description": "저장소 사용량 정보", "properties": { "storage_limit": { "description": "저장소 한도 (bytes)", "type": "integer", "example": 10737418240 }, "storage_used": { "description": "사용 중인 용량 (bytes)", "type": "integer", "example": 5368709120 }, "storage_used_formatted": { "type": "string", "example": "5.00 GB" }, "storage_limit_formatted": { "type": "string", "example": "10.00 GB" }, "usage_percentage": { "type": "number", "format": "float", "example": 50 }, "file_count": { "type": "integer", "example": 150 }, "folder_breakdown": { "description": "폴더별 사용량", "type": "object", "example": { "product": 2147483648, "quality": 1073741824, "accounting": 536870912 } } }, "type": "object" }, "Folder": { "description": "폴더 모델", "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "folder_key": { "description": "폴더 키 (영문 소문자, 숫자, 하이픈, 언더스코어만 허용)", "type": "string", "example": "product" }, "folder_name": { "description": "폴더 표시명", "type": "string", "example": "생산관리" }, "description": { "type": "string", "maxLength": 500, "example": "생산 관련 문서", "nullable": true }, "display_order": { "description": "정렬 순서", "type": "integer", "example": 1 }, "is_active": { "type": "boolean", "example": true }, "icon": { "type": "string", "maxLength": 50, "example": "icon-production", "nullable": true }, "color": { "description": "색상 코드 (#RRGGBB 형식)", "type": "string", "example": "#3B82F6", "nullable": true }, "created_by": { "type": "integer", "example": 1 }, "updated_by": { "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-01-01T00:00:00Z" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-01-01T00:00:00Z" } }, "type": "object" }, "FolderStoreRequest": { "description": "폴더 생성 요청", "required": [ "folder_key", "folder_name" ], "properties": { "folder_key": { "description": "폴더 키 (영문 소문자, 숫자, 하이픈, 언더스코어만)", "type": "string", "maxLength": 50, "pattern": "^[a-z0-9_-]+$", "example": "accounting" }, "folder_name": { "description": "폴더 표시명", "type": "string", "maxLength": 100, "example": "회계" }, "description": { "type": "string", "maxLength": 500, "example": "회계 관련 문서", "nullable": true }, "display_order": { "description": "정렬 순서 (미지정 시 자동)", "type": "integer", "minimum": 0, "example": 10, "nullable": true }, "is_active": { "type": "boolean", "example": true, "nullable": true }, "icon": { "type": "string", "maxLength": 50, "example": "icon-accounting", "nullable": true }, "color": { "type": "string", "pattern": "^#[0-9A-Fa-f]{6}$", "example": "#10B981", "nullable": true } }, "type": "object" }, "FolderUpdateRequest": { "description": "폴더 수정 요청", "properties": { "folder_key": { "type": "string", "maxLength": 50, "pattern": "^[a-z0-9_-]+$", "example": "accounting" }, "folder_name": { "type": "string", "maxLength": 100, "example": "회계" }, "description": { "type": "string", "maxLength": 500, "example": "회계 관련 문서", "nullable": true }, "display_order": { "type": "integer", "minimum": 0, "example": 5 }, "is_active": { "type": "boolean", "example": true }, "icon": { "type": "string", "maxLength": 50, "example": "icon-accounting", "nullable": true }, "color": { "type": "string", "pattern": "^#[0-9A-Fa-f]{6}$", "example": "#10B981", "nullable": true } }, "type": "object" }, "FolderReorderRequest": { "description": "폴더 순서 변경 요청", "required": [ "orders" ], "properties": { "orders": { "description": "폴더 ID와 순서 배열", "type": "array", "items": { "required": [ "id", "display_order" ], "properties": { "id": { "type": "integer", "example": 1 }, "display_order": { "type": "integer", "example": 0 } }, "type": "object" }, "example": [ { "id": 1, "display_order": 0 }, { "id": 2, "display_order": 1 }, { "id": 3, "display_order": 2 } ] } }, "type": "object" }, "ItemPage": { "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "page_name": { "type": "string", "example": "기본 정보" }, "item_type": { "type": "string", "enum": [ "FG", "PT", "SM", "RM", "CS" ], "example": "FG" }, "absolute_path": { "type": "string", "example": "/items/fg/basic", "nullable": true }, "is_active": { "type": "boolean", "example": true }, "created_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "sections": { "type": "array", "items": { "$ref": "#/components/schemas/ItemSection" } } }, "type": "object" }, "ItemSection": { "description": "엔티티 - 관계는 entity_relationships로 관리", "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "group_id": { "description": "계층번호", "type": "integer", "example": 1, "nullable": true }, "title": { "type": "string", "example": "제품 상세" }, "type": { "type": "string", "enum": [ "fields", "bom" ], "example": "fields" }, "order_no": { "type": "integer", "example": 0 }, "is_template": { "description": "템플릿 여부", "type": "boolean", "example": false }, "is_default": { "description": "기본 템플릿 여부", "type": "boolean", "example": false }, "is_locked": { "description": "연결 잠금 여부 (init API 응답 시 포함)", "type": "boolean", "example": false }, "description": { "type": "string", "example": "섹션 설명", "nullable": true }, "created_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "fields": { "type": "array", "items": { "$ref": "#/components/schemas/ItemField" } }, "bom_items": { "type": "array", "items": { "$ref": "#/components/schemas/ItemBomItem" } } }, "type": "object" }, "ItemField": { "description": "엔티티 - 관계는 entity_relationships로 관리", "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "group_id": { "description": "계층번호", "type": "integer", "example": 1, "nullable": true }, "field_name": { "type": "string", "example": "제품명" }, "field_key": { "description": "필드 고유 키 ({ID}_{key} 형식)", "type": "string", "example": "81_itemNum", "nullable": true }, "field_type": { "type": "string", "enum": [ "textbox", "number", "dropdown", "checkbox", "date", "textarea" ], "example": "textbox" }, "order_no": { "type": "integer", "example": 0 }, "is_required": { "type": "boolean", "example": true }, "is_locked": { "description": "엔티티 잠금 여부", "type": "boolean", "example": false }, "locked_by": { "description": "잠금 설정자 ID", "type": "integer", "example": null, "nullable": true }, "locked_at": { "description": "잠금 설정 일시", "type": "string", "example": null, "nullable": true }, "default_value": { "type": "string", "example": null, "nullable": true }, "placeholder": { "type": "string", "example": "제품명을 입력하세요", "nullable": true }, "display_condition": { "type": "object", "example": null, "nullable": true }, "validation_rules": { "type": "object", "example": null, "nullable": true }, "options": { "type": "object", "example": null, "nullable": true }, "properties": { "type": "object", "example": null, "nullable": true }, "category": { "description": "필드 카테고리", "type": "string", "example": "basic", "nullable": true }, "description": { "type": "string", "example": "필드 설명", "nullable": true }, "is_common": { "description": "공통 필드 여부", "type": "boolean", "example": false }, "created_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-20 10:00:00" } }, "type": "object" }, "ItemBomItem": { "description": "엔티티 - 관계는 entity_relationships로 관리", "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "group_id": { "description": "계층번호", "type": "integer", "example": 1, "nullable": true }, "item_code": { "type": "string", "example": "ITEM001", "nullable": true }, "item_name": { "type": "string", "example": "부품 A" }, "quantity": { "type": "number", "format": "float", "example": 1.5 }, "unit": { "type": "string", "example": "EA", "nullable": true }, "unit_price": { "type": "number", "format": "float", "example": 10000, "nullable": true }, "total_price": { "type": "number", "format": "float", "example": 15000, "nullable": true }, "spec": { "type": "string", "example": "규격 정보", "nullable": true }, "note": { "type": "string", "example": "비고", "nullable": true }, "is_locked": { "description": "연결 잠금 여부 (init API 응답 시 포함)", "type": "boolean", "example": false }, "created_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-20 10:00:00" } }, "type": "object" }, "SectionTemplate": { "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "title": { "type": "string", "example": "기본 템플릿" }, "type": { "type": "string", "enum": [ "fields", "bom" ], "example": "fields" }, "description": { "type": "string", "example": "설명", "nullable": true }, "is_default": { "type": "boolean", "example": false }, "created_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-20 10:00:00" } }, "type": "object" }, "CustomTab": { "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "label": { "type": "string", "example": "커스텀 탭" }, "icon": { "type": "string", "example": "icon-name", "nullable": true }, "is_default": { "type": "boolean", "example": false }, "order_no": { "type": "integer", "example": 0 }, "created_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "columnSetting": { "type": "object", "nullable": true } }, "type": "object" }, "UnitOption": { "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "label": { "type": "string", "example": "개" }, "value": { "type": "string", "example": "EA" }, "created_at": { "type": "string", "example": "2025-11-20 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-20 10:00:00" } }, "type": "object" }, "ItemPageStoreRequest": { "required": [ "page_name", "item_type" ], "properties": { "page_name": { "type": "string", "maxLength": 255, "example": "기본 정보" }, "item_type": { "type": "string", "enum": [ "FG", "PT", "SM", "RM", "CS" ], "example": "FG" }, "absolute_path": { "type": "string", "maxLength": 500, "example": "/items/fg/basic", "nullable": true } }, "type": "object" }, "ItemPageUpdateRequest": { "properties": { "page_name": { "type": "string", "maxLength": 255, "example": "기본 정보" }, "absolute_path": { "type": "string", "maxLength": 500, "example": "/items/fg/basic", "nullable": true } }, "type": "object" }, "ItemSectionStoreRequest": { "required": [ "title", "type" ], "properties": { "group_id": { "description": "계층번호", "type": "integer", "example": 1, "nullable": true }, "title": { "type": "string", "maxLength": 255, "example": "제품 상세" }, "type": { "type": "string", "enum": [ "fields", "bom" ], "example": "fields" } }, "type": "object" }, "IndependentSectionStoreRequest": { "required": [ "title", "type" ], "properties": { "group_id": { "description": "계층번호", "type": "integer", "example": 1, "nullable": true }, "title": { "type": "string", "maxLength": 255, "example": "섹션" }, "type": { "type": "string", "enum": [ "fields", "bom" ], "example": "fields" }, "is_template": { "type": "boolean", "example": false }, "is_default": { "type": "boolean", "example": false }, "description": { "type": "string", "example": "섹션 설명", "nullable": true } }, "type": "object" }, "IndependentFieldStoreRequest": { "required": [ "field_name", "field_type" ], "properties": { "group_id": { "description": "계층번호", "type": "integer", "example": 1, "nullable": true }, "field_name": { "type": "string", "maxLength": 255, "example": "제품명" }, "field_key": { "description": "필드 고유 키 (영문+숫자+언더스코어, 저장 시 {ID}_{key} 형식으로 변환)", "type": "string", "maxLength": 80, "example": "itemNum", "nullable": true }, "field_type": { "type": "string", "enum": [ "textbox", "number", "dropdown", "checkbox", "date", "textarea" ], "example": "textbox" }, "is_required": { "type": "boolean", "example": false }, "default_value": { "type": "string", "example": null, "nullable": true }, "placeholder": { "type": "string", "maxLength": 255, "example": "입력하세요", "nullable": true }, "display_condition": { "type": "object", "example": null, "nullable": true }, "validation_rules": { "type": "object", "example": null, "nullable": true }, "options": { "type": "object", "example": null, "nullable": true }, "properties": { "type": "object", "example": null, "nullable": true }, "is_locked": { "description": "잠금 여부", "type": "boolean", "example": false, "nullable": true } }, "type": "object" }, "IndependentBomItemStoreRequest": { "required": [ "item_name" ], "properties": { "group_id": { "description": "계층번호", "type": "integer", "example": 1, "nullable": true }, "item_code": { "type": "string", "maxLength": 100, "example": "ITEM001", "nullable": true }, "item_name": { "type": "string", "maxLength": 255, "example": "부품 A" }, "quantity": { "type": "number", "format": "float", "example": 1 }, "unit": { "type": "string", "maxLength": 50, "example": "EA", "nullable": true }, "unit_price": { "type": "number", "format": "float", "example": 10000, "nullable": true }, "total_price": { "type": "number", "format": "float", "example": 10000, "nullable": true }, "spec": { "type": "string", "example": "규격", "nullable": true }, "note": { "type": "string", "example": "비고", "nullable": true } }, "type": "object" }, "SectionUsageResponse": { "description": "섹션 사용처 응답 (entity_relationships 기반)", "properties": { "section_id": { "type": "integer", "example": 1 }, "linked_pages": { "type": "array", "items": { "type": "object" } }, "total_usage_count": { "type": "integer", "example": 2 } }, "type": "object" }, "FieldUsageResponse": { "description": "필드 사용처 응답 (entity_relationships 기반)", "properties": { "field_id": { "type": "integer", "example": 1 }, "linked_sections": { "type": "array", "items": { "type": "object" } }, "linked_pages": { "type": "array", "items": { "type": "object" } }, "total_usage_count": { "type": "integer", "example": 3 } }, "type": "object" }, "ItemSectionUpdateRequest": { "properties": { "title": { "type": "string", "maxLength": 255, "example": "제품 상세" } }, "type": "object" }, "ItemFieldStoreRequest": { "required": [ "field_name", "field_type" ], "properties": { "group_id": { "description": "계층번호", "type": "integer", "example": 1, "nullable": true }, "field_name": { "type": "string", "maxLength": 255, "example": "제품명" }, "field_key": { "description": "필드 고유 키 (영문+숫자+언더스코어, 저장 시 {ID}_{key} 형식으로 변환)", "type": "string", "maxLength": 80, "example": "itemNum", "nullable": true }, "field_type": { "type": "string", "enum": [ "textbox", "number", "dropdown", "checkbox", "date", "textarea" ], "example": "textbox" }, "is_required": { "type": "boolean", "example": true }, "default_value": { "type": "string", "example": null, "nullable": true }, "placeholder": { "type": "string", "maxLength": 255, "example": "제품명을 입력하세요", "nullable": true }, "display_condition": { "type": "object", "example": null, "nullable": true }, "validation_rules": { "type": "object", "example": null, "nullable": true }, "options": { "type": "object", "example": null, "nullable": true }, "properties": { "type": "object", "example": null, "nullable": true }, "is_locked": { "description": "잠금 여부", "type": "boolean", "example": false, "nullable": true } }, "type": "object" }, "ItemFieldUpdateRequest": { "properties": { "field_name": { "type": "string", "maxLength": 255, "example": "제품명" }, "field_key": { "description": "필드 고유 키 (영문+숫자+언더스코어)", "type": "string", "maxLength": 80, "example": "itemNum", "nullable": true }, "field_type": { "type": "string", "enum": [ "textbox", "number", "dropdown", "checkbox", "date", "textarea" ], "example": "textbox" }, "is_required": { "type": "boolean", "example": true }, "default_value": { "type": "string", "example": null, "nullable": true }, "placeholder": { "type": "string", "maxLength": 255, "example": "제품명을 입력하세요", "nullable": true }, "display_condition": { "type": "object", "example": null, "nullable": true }, "validation_rules": { "type": "object", "example": null, "nullable": true }, "options": { "type": "object", "example": null, "nullable": true }, "properties": { "type": "object", "example": null, "nullable": true }, "is_locked": { "description": "잠금 여부", "type": "boolean", "example": false, "nullable": true } }, "type": "object" }, "ItemBomItemStoreRequest": { "required": [ "item_name" ], "properties": { "group_id": { "description": "계층번호", "type": "integer", "example": 1, "nullable": true }, "item_code": { "type": "string", "maxLength": 100, "example": "ITEM001", "nullable": true }, "item_name": { "type": "string", "maxLength": 255, "example": "부품 A" }, "quantity": { "type": "number", "format": "float", "example": 1.5 }, "unit": { "type": "string", "maxLength": 50, "example": "EA", "nullable": true }, "unit_price": { "type": "number", "format": "float", "example": 10000, "nullable": true }, "total_price": { "type": "number", "format": "float", "example": 15000, "nullable": true }, "spec": { "type": "string", "example": "규격 정보", "nullable": true }, "note": { "type": "string", "example": "비고", "nullable": true } }, "type": "object" }, "ItemBomItemUpdateRequest": { "properties": { "item_code": { "type": "string", "maxLength": 100, "example": "ITEM001", "nullable": true }, "item_name": { "type": "string", "maxLength": 255, "example": "부품 A" }, "quantity": { "type": "number", "format": "float", "example": 1.5 }, "unit": { "type": "string", "maxLength": 50, "example": "EA", "nullable": true }, "unit_price": { "type": "number", "format": "float", "example": 10000, "nullable": true }, "total_price": { "type": "number", "format": "float", "example": 15000, "nullable": true }, "spec": { "type": "string", "example": "규격 정보", "nullable": true }, "note": { "type": "string", "example": "비고", "nullable": true } }, "type": "object" }, "SectionTemplateStoreRequest": { "required": [ "title", "type" ], "properties": { "page_id": { "description": "연결할 페이지 ID (선택, 있으면 즉시 링크 연결)", "type": "integer", "example": 1, "nullable": true }, "title": { "type": "string", "maxLength": 255, "example": "기본 섹션" }, "type": { "type": "string", "enum": [ "fields", "bom" ], "example": "fields" }, "description": { "type": "string", "example": "설명", "nullable": true }, "is_default": { "type": "boolean", "example": false } }, "type": "object" }, "SectionTemplateUpdateRequest": { "properties": { "title": { "type": "string", "maxLength": 255, "example": "기본 템플릿" }, "type": { "type": "string", "enum": [ "fields", "bom" ], "example": "fields" }, "description": { "type": "string", "example": "설명", "nullable": true }, "is_default": { "type": "boolean", "example": false } }, "type": "object" }, "CustomTabStoreRequest": { "required": [ "label" ], "properties": { "label": { "type": "string", "maxLength": 255, "example": "커스텀 탭" }, "icon": { "type": "string", "maxLength": 100, "example": "icon-name", "nullable": true }, "is_default": { "type": "boolean", "example": false } }, "type": "object" }, "CustomTabUpdateRequest": { "properties": { "label": { "type": "string", "maxLength": 255, "example": "커스텀 탭" }, "icon": { "type": "string", "maxLength": 100, "example": "icon-name", "nullable": true }, "is_default": { "type": "boolean", "example": false } }, "type": "object" }, "UnitOptionStoreRequest": { "required": [ "label", "value" ], "properties": { "label": { "type": "string", "maxLength": 100, "example": "개" }, "value": { "type": "string", "maxLength": 50, "example": "EA" } }, "type": "object" }, "ReorderRequest": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "required": [ "id", "order_no" ], "properties": { "id": { "type": "integer", "example": 1 }, "order_no": { "type": "integer", "example": 0 } }, "type": "object" }, "example": [ { "id": 1, "order_no": 0 }, { "id": 2, "order_no": 1 } ] } }, "type": "object" }, "ItemMasterInitResponse": { "properties": { "pages": { "description": "페이지 목록 (linkedSections 기반)", "type": "array", "items": { "$ref": "#/components/schemas/ItemPage" } }, "sections": { "description": "모든 섹션 목록 (재사용 가능)", "type": "array", "items": { "$ref": "#/components/schemas/ItemSection" } }, "fields": { "description": "모든 필드 목록 (재사용 가능)", "type": "array", "items": { "$ref": "#/components/schemas/ItemField" } }, "customTabs": { "type": "array", "items": { "$ref": "#/components/schemas/CustomTab" } }, "unitOptions": { "type": "array", "items": { "$ref": "#/components/schemas/UnitOption" } } }, "type": "object" }, "Item": { "required": [ "id", "code", "name", "item_type", "unit" ], "properties": { "id": { "type": "integer", "example": 1 }, "code": { "type": "string", "example": "P-001" }, "name": { "type": "string", "example": "스크린 제품 A" }, "item_type": { "description": "품목 유형 (FG|PT|SM|RM|CS)", "type": "string", "example": "FG" }, "type_code": { "description": "품목 유형 코드", "type": "string", "example": "FG" }, "unit": { "type": "string", "example": "EA" }, "category_id": { "type": "integer", "example": 1, "nullable": true }, "specification": { "description": "규격 (Material 전용)", "type": "string", "example": "1.2T x 1219 x 2438", "nullable": true }, "description": { "type": "string", "example": "제품 설명", "nullable": true }, "is_sellable": { "type": "boolean", "example": true }, "is_purchasable": { "type": "boolean", "example": false }, "is_producible": { "type": "boolean", "example": false }, "safety_stock": { "type": "integer", "example": 10, "nullable": true }, "lead_time": { "type": "integer", "example": 7, "nullable": true }, "is_variable_size": { "type": "boolean", "example": false }, "product_category": { "type": "string", "example": "SCREEN", "nullable": true }, "part_type": { "type": "string", "example": "ASSEMBLY", "nullable": true }, "item_name": { "description": "품명 (Material 전용)", "type": "string", "example": "철판", "nullable": true }, "is_inspection": { "description": "검수 여부 (Material 전용)", "type": "string", "example": "Y", "nullable": true }, "search_tag": { "description": "검색 태그 (Material 전용)", "type": "string", "example": "철판,원자재,1.2T", "nullable": true }, "remarks": { "description": "비고 (Material 전용)", "type": "string", "example": "비고", "nullable": true }, "created_at": { "type": "string", "example": "2025-11-14 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-14 10:10:00" }, "deleted_at": { "description": "삭제일시 (soft delete)", "type": "string", "example": null, "nullable": true }, "files": { "description": "첨부 파일 (field_key별 그룹핑)", "type": "object", "example": { "bending_diagram": [ { "id": 1, "file_name": "벤딩도.pdf", "file_path": "/uploads/items/1/bending_diagram.pdf" } ], "specification": [ { "id": 2, "file_name": "규격서.pdf", "file_path": "/uploads/items/1/specification.pdf" } ] }, "nullable": true, "additionalProperties": { "type": "array", "items": { "$ref": "#/components/schemas/ItemFile" }, "property": null } } }, "type": "object" }, "ItemCreateRequest": { "required": [ "code", "name", "product_type", "unit" ], "properties": { "code": { "type": "string", "maxLength": 50, "example": "P-001" }, "name": { "type": "string", "maxLength": 255, "example": "스크린 제품 A" }, "product_type": { "description": "품목 유형 (FG|PT|SM|RM|CS)", "type": "string", "example": "FG" }, "unit": { "type": "string", "maxLength": 20, "example": "EA" }, "category_id": { "type": "integer", "example": 1, "nullable": true }, "description": { "type": "string", "example": "제품 설명", "nullable": true }, "is_sellable": { "type": "boolean", "example": true, "nullable": true }, "is_purchasable": { "type": "boolean", "example": false, "nullable": true }, "is_producible": { "type": "boolean", "example": false, "nullable": true }, "safety_stock": { "type": "integer", "example": 10, "nullable": true }, "lead_time": { "type": "integer", "example": 7, "nullable": true }, "is_variable_size": { "type": "boolean", "example": false, "nullable": true }, "product_category": { "type": "string", "example": "SCREEN", "nullable": true }, "part_type": { "type": "string", "example": "ASSEMBLY", "nullable": true }, "attributes": { "description": "동적 속성 (JSON)", "type": "object", "nullable": true }, "material_code": { "description": "Material 코드 (Material 전용)", "type": "string", "maxLength": 50, "example": "M-001", "nullable": true }, "item_name": { "description": "품명 (Material 전용)", "type": "string", "maxLength": 255, "example": "철판", "nullable": true }, "specification": { "description": "규격 (Material 전용)", "type": "string", "maxLength": 255, "example": "1.2T x 1219 x 2438", "nullable": true }, "is_inspection": { "description": "검수 여부 Y|N (Material 전용)", "type": "string", "example": "Y", "nullable": true }, "search_tag": { "description": "검색 태그 (Material 전용)", "type": "string", "maxLength": 255, "example": "철판,원자재", "nullable": true }, "remarks": { "description": "비고 (Material 전용)", "type": "string", "example": "비고", "nullable": true }, "options": { "description": "옵션 (Material 전용)", "type": "object", "nullable": true } }, "type": "object" }, "ItemUpdateRequest": { "required": [ "item_type" ], "properties": { "item_type": { "description": "품목 유형 (필수, FG|PT|SM|RM|CS)", "type": "string", "example": "FG" }, "code": { "type": "string", "maxLength": 50, "example": "P-001" }, "name": { "type": "string", "maxLength": 255, "example": "스크린 제품 A" }, "product_type": { "description": "FG|PT|SM|RM|CS", "type": "string", "example": "FG" }, "unit": { "type": "string", "maxLength": 20, "example": "EA" }, "category_id": { "type": "integer", "example": 1, "nullable": true }, "description": { "type": "string", "example": "제품 설명", "nullable": true }, "is_sellable": { "type": "boolean", "example": true, "nullable": true }, "is_purchasable": { "type": "boolean", "example": false, "nullable": true }, "is_producible": { "type": "boolean", "example": false, "nullable": true }, "safety_stock": { "type": "integer", "example": 10, "nullable": true }, "lead_time": { "type": "integer", "example": 7, "nullable": true }, "is_variable_size": { "type": "boolean", "example": false, "nullable": true }, "product_category": { "type": "string", "example": "SCREEN", "nullable": true }, "part_type": { "type": "string", "example": "ASSEMBLY", "nullable": true }, "attributes": { "description": "동적 속성 (JSON)", "type": "object", "nullable": true }, "material_code": { "description": "Material 코드 (Material 전용)", "type": "string", "maxLength": 50, "example": "M-001", "nullable": true }, "item_name": { "description": "품명 (Material 전용)", "type": "string", "maxLength": 255, "example": "철판", "nullable": true }, "specification": { "description": "규격 (Material 전용)", "type": "string", "maxLength": 255, "example": "1.2T x 1219 x 2438", "nullable": true }, "is_inspection": { "description": "검수 여부 Y|N (Material 전용)", "type": "string", "example": "Y", "nullable": true }, "search_tag": { "description": "검색 태그 (Material 전용)", "type": "string", "maxLength": 255, "example": "철판,원자재", "nullable": true }, "remarks": { "description": "비고 (Material 전용)", "type": "string", "example": "비고", "nullable": true }, "options": { "description": "옵션 (Material 전용)", "type": "object", "nullable": true } }, "type": "object" }, "ItemBatchDeleteRequest": { "required": [ "item_type", "ids" ], "properties": { "item_type": { "description": "품목 유형 (필수, FG|PT|SM|RM|CS)", "type": "string", "example": "FG" }, "ids": { "description": "삭제할 품목 ID 목록", "type": "array", "items": { "type": "integer" }, "example": [ 1, 2, 3 ] } }, "type": "object" }, "BOMLine": { "required": [ "id", "ref_type", "ref_id", "quantity" ], "properties": { "id": { "type": "integer", "example": 1 }, "ref_type": { "description": "PRODUCT|MATERIAL", "type": "string", "example": "PRODUCT" }, "ref_id": { "type": "integer", "example": 10 }, "code": { "type": "string", "example": "P-001" }, "name": { "type": "string", "example": "가이드레일" }, "quantity": { "type": "number", "example": 2.5 }, "sort_order": { "type": "integer", "example": 1 }, "category_id": { "type": "integer", "example": 1, "nullable": true }, "category_name": { "type": "string", "example": "조립품", "nullable": true }, "quantity_formula": { "description": "수량 계산 수식", "type": "string", "example": "W * 2", "nullable": true }, "condition": { "description": "조건부 BOM", "type": "string", "example": "MOTOR='Y'", "nullable": true } }, "type": "object" }, "BOMTree": { "properties": { "type": { "type": "string", "example": "PRODUCT" }, "id": { "type": "integer", "example": 1 }, "code": { "type": "string", "example": "P-001" }, "name": { "type": "string", "example": "스크린 세트" }, "quantity": { "type": "number", "example": 1 }, "depth": { "type": "integer", "example": 0 }, "children": { "type": "array", "items": { "$ref": "#/components/schemas/BOMTree" } } }, "type": "object" }, "BOMCreateRequest": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "required": [ "ref_type", "ref_id", "quantity" ], "properties": { "id": { "description": "기존 라인 ID (업데이트 시)", "type": "integer", "example": 1, "nullable": true }, "ref_type": { "description": "PRODUCT|MATERIAL", "type": "string", "example": "PRODUCT" }, "ref_id": { "type": "integer", "example": 10 }, "quantity": { "type": "number", "example": 2.5 }, "sort_order": { "type": "integer", "example": 1, "nullable": true }, "quantity_formula": { "type": "string", "example": "W * 2", "nullable": true }, "condition": { "type": "string", "example": "MOTOR='Y'", "nullable": true } }, "type": "object" } } }, "type": "object" }, "BOMUpdateRequest": { "properties": { "ref_type": { "description": "PRODUCT|MATERIAL", "type": "string", "example": "PRODUCT" }, "ref_id": { "type": "integer", "example": 10 }, "quantity": { "type": "number", "example": 2.5 }, "sort_order": { "type": "integer", "example": 1 }, "quantity_formula": { "type": "string", "example": "W * 2", "nullable": true }, "condition": { "type": "string", "example": "MOTOR='Y'", "nullable": true } }, "type": "object" }, "ItemFile": { "required": [ "id", "file_name", "file_path" ], "properties": { "id": { "description": "파일 ID", "type": "integer", "example": 123 }, "file_name": { "description": "파일명", "type": "string", "example": "도면_v1.pdf" }, "file_path": { "description": "파일 경로", "type": "string", "example": "1/items/2025/12/a1b2c3d4.pdf" }, "file_url": { "description": "다운로드 URL", "type": "string", "format": "uri", "example": "https://api.sam.kr/api/v1/files/download/..." }, "file_size": { "description": "파일 크기 (bytes)", "type": "integer", "example": 102400 }, "mime_type": { "description": "MIME 타입", "type": "string", "example": "application/pdf" }, "field_key": { "description": "필드 키", "type": "string", "example": "drawing" }, "created_at": { "description": "생성일시", "type": "string", "format": "date-time", "example": "2025-12-12 10:00:00" } }, "type": "object" }, "ItemFilesGrouped": { "description": "field_key별 그룹핑된 파일 목록", "type": "object", "example": { "drawing": [ { "id": 10, "file_name": "도면1.pdf", "file_path": "..." }, { "id": 11, "file_name": "도면2.pdf", "file_path": "..." } ], "certificate": [ { "id": 12, "file_name": "인증서.pdf", "file_path": "..." } ] } }, "ItemFileUploadRequest": { "required": [ "field_key", "file" ], "properties": { "field_key": { "description": "필드 키 (자유롭게 지정)", "type": "string", "example": "drawing" }, "file": { "description": "업로드할 파일 (최대 20MB)", "type": "string", "format": "binary" }, "file_id": { "description": "기존 파일 ID (있으면 교체, 없으면 추가)", "type": "integer", "example": 123, "nullable": true } }, "type": "object" }, "ItemFileUploadResponse": { "required": [ "file_id", "field_key", "file_url", "file_path", "file_name" ], "properties": { "file_id": { "description": "파일 ID", "type": "integer", "example": 123 }, "field_key": { "description": "필드 키", "type": "string", "example": "drawing" }, "file_url": { "description": "다운로드 URL", "type": "string", "format": "uri", "example": "https://api.sam.kr/api/v1/files/download/..." }, "file_path": { "description": "파일 경로", "type": "string", "example": "1/items/2025/12/a1b2c3d4.pdf" }, "file_name": { "description": "원본 파일명", "type": "string", "example": "도면_v1.pdf" }, "file_size": { "description": "파일 크기 (bytes)", "type": "integer", "example": 102400 }, "mime_type": { "description": "MIME 타입", "type": "string", "example": "application/pdf" }, "replaced": { "description": "기존 파일 교체 여부", "type": "boolean", "example": false } }, "type": "object" }, "ItemFileDeleteResponse": { "required": [ "file_id", "deleted" ], "properties": { "file_id": { "description": "삭제된 파일 ID", "type": "integer", "example": 123 }, "deleted": { "description": "삭제 성공 여부", "type": "boolean", "example": true } }, "type": "object" }, "Leave": { "description": "휴가 정보", "properties": { "id": { "description": "휴가 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "user_id": { "description": "신청자 ID", "type": "integer", "example": 10 }, "leave_type": { "description": "휴가 유형", "type": "string", "enum": [ "annual", "half_am", "half_pm", "sick", "family", "maternity", "parental" ], "example": "annual" }, "start_date": { "description": "시작일", "type": "string", "format": "date", "example": "2024-01-15" }, "end_date": { "description": "종료일", "type": "string", "format": "date", "example": "2024-01-17" }, "days": { "description": "사용일수", "type": "number", "format": "float", "example": 3 }, "reason": { "description": "휴가 사유", "type": "string", "example": "개인 사유", "nullable": true }, "status": { "description": "상태", "type": "string", "enum": [ "pending", "approved", "rejected", "cancelled" ], "example": "pending" }, "approved_by": { "description": "승인자 ID", "type": "integer", "example": 5, "nullable": true }, "approved_at": { "description": "승인/반려 일시", "type": "string", "format": "date-time", "example": "2024-01-14T10:00:00Z", "nullable": true }, "reject_reason": { "description": "반려 사유", "type": "string", "example": "인원 부족", "nullable": true }, "user": { "description": "신청자 정보", "properties": { "id": { "type": "integer", "example": 10 }, "name": { "type": "string", "example": "홍길동" }, "email": { "type": "string", "example": "hong@company.com" } }, "type": "object", "nullable": true }, "approver": { "description": "승인자 정보", "properties": { "id": { "type": "integer", "example": 5 }, "name": { "type": "string", "example": "김부장" } }, "type": "object", "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2024-01-13T09:00:00Z" }, "updated_at": { "type": "string", "format": "date-time", "example": "2024-01-14T10:00:00Z" } }, "type": "object" }, "LeaveCreateRequest": { "description": "휴가 신청 요청", "required": [ "leave_type", "start_date", "end_date", "days" ], "properties": { "leave_type": { "description": "휴가 유형", "type": "string", "enum": [ "annual", "half_am", "half_pm", "sick", "family", "maternity", "parental" ], "example": "annual" }, "start_date": { "description": "시작일", "type": "string", "format": "date", "example": "2024-01-15" }, "end_date": { "description": "종료일", "type": "string", "format": "date", "example": "2024-01-17" }, "days": { "description": "사용일수", "type": "number", "format": "float", "maximum": 365, "minimum": 0.5, "example": 3 }, "reason": { "description": "휴가 사유", "type": "string", "example": "개인 사유" } }, "type": "object" }, "LeaveUpdateRequest": { "description": "휴가 수정 요청", "properties": { "leave_type": { "description": "휴가 유형", "type": "string", "enum": [ "annual", "half_am", "half_pm", "sick", "family", "maternity", "parental" ], "example": "annual" }, "start_date": { "description": "시작일", "type": "string", "format": "date", "example": "2024-01-15" }, "end_date": { "description": "종료일", "type": "string", "format": "date", "example": "2024-01-17" }, "days": { "description": "사용일수", "type": "number", "format": "float", "example": 3 }, "reason": { "description": "휴가 사유", "type": "string", "example": "개인 사유" } }, "type": "object" }, "LeaveBalance": { "description": "휴가 잔여일수 정보", "properties": { "id": { "description": "ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "user_id": { "description": "사용자 ID", "type": "integer", "example": 10 }, "year": { "description": "연도", "type": "integer", "example": 2024 }, "total_days": { "description": "연간 부여일수", "type": "number", "format": "float", "example": 15 }, "used_days": { "description": "사용일수", "type": "number", "format": "float", "example": 5 }, "remaining_days": { "description": "잔여일수", "type": "number", "format": "float", "example": 10 }, "user": { "description": "사용자 정보", "properties": { "id": { "type": "integer", "example": 10 }, "name": { "type": "string", "example": "홍길동" } }, "type": "object", "nullable": true } }, "type": "object" }, "LeaveBalanceSetRequest": { "description": "휴가 잔여일수 설정 요청", "required": [ "user_id", "year", "total_days" ], "properties": { "user_id": { "description": "사용자 ID", "type": "integer", "example": 10 }, "year": { "description": "연도", "type": "integer", "maximum": 2099, "minimum": 2020, "example": 2024 }, "total_days": { "description": "연간 부여일수", "type": "number", "format": "float", "maximum": 365, "minimum": 0, "example": 15 } }, "type": "object" }, "Menu": { "description": "메뉴 상세", "required": [ "id", "name" ], "properties": { "id": { "type": "integer", "example": 12 }, "tenant_id": { "description": "null=공용", "type": "integer", "example": 1, "nullable": true }, "parent_id": { "type": "integer", "example": null, "nullable": true }, "name": { "type": "string", "example": "메뉴 관리" }, "slug": { "type": "string", "example": "menu.manage", "nullable": true }, "url": { "type": "string", "example": "/admin/menus", "nullable": true }, "is_active": { "type": "integer", "example": 1 }, "sort_order": { "type": "integer", "example": 10 }, "hidden": { "type": "integer", "example": 0 }, "is_external": { "type": "integer", "example": 0 }, "external_url": { "type": "string", "example": null, "nullable": true }, "icon": { "type": "string", "example": "list", "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-08-15 10:00:00" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-08-15 10:00:00" }, "deleted_at": { "type": "string", "format": "date-time", "example": null, "nullable": true } }, "type": "object" }, "MenuBrief": { "description": "메뉴 요약", "required": [ "id", "name" ], "properties": { "id": { "type": "integer", "example": 12 }, "parent_id": { "type": "integer", "example": null, "nullable": true }, "name": { "type": "string", "example": "메뉴 관리" }, "slug": { "type": "string", "example": "menu.manage", "nullable": true }, "url": { "type": "string", "example": "/admin/menus", "nullable": true }, "is_active": { "type": "integer", "example": 1 }, "sort_order": { "type": "integer", "example": 10 }, "hidden": { "type": "integer", "example": 0 }, "is_external": { "type": "integer", "example": 0 }, "external_url": { "type": "string", "example": null, "nullable": true }, "icon": { "type": "string", "example": "list", "nullable": true } }, "type": "object" }, "MenuList": { "type": "array", "items": { "$ref": "#/components/schemas/MenuBrief" } }, "MenuCreateRequest": { "required": [ "name" ], "properties": { "parent_id": { "description": "상위 메뉴 ID", "type": "integer", "example": null, "nullable": true }, "name": { "description": "메뉴명", "type": "string", "example": "새 메뉴" }, "slug": { "description": "권한 키로도 활용", "type": "string", "example": "menu.new", "nullable": true }, "url": { "type": "string", "example": "/admin/new", "nullable": true }, "is_active": { "type": "boolean", "example": true }, "sort_order": { "type": "integer", "example": 0 }, "hidden": { "type": "boolean", "example": false }, "is_external": { "type": "boolean", "example": false }, "external_url": { "type": "string", "example": null, "nullable": true }, "icon": { "type": "string", "example": "plus", "nullable": true } }, "type": "object" }, "MenuUpdateRequest": { "properties": { "parent_id": { "type": "integer", "example": null, "nullable": true }, "name": { "type": "string", "example": "메뉴명 변경" }, "slug": { "type": "string", "example": "menu.changed", "nullable": true }, "url": { "type": "string", "example": "/admin/changed", "nullable": true }, "is_active": { "type": "boolean", "example": true }, "sort_order": { "type": "integer", "example": 5 }, "hidden": { "type": "boolean", "example": false }, "is_external": { "type": "boolean", "example": false }, "external_url": { "type": "string", "example": null, "nullable": true }, "icon": { "type": "string", "example": "edit", "nullable": true } }, "type": "object" }, "MenuMatrixAction": { "properties": { "permission_id": { "type": "integer", "example": 1 }, "permission_code": { "type": "string", "example": "menu:16.view" }, "guard_name": { "type": "string", "example": "api" }, "state": { "type": "string", "enum": [ "allow", "deny", "none" ], "example": "allow" }, "is_allowed": { "type": "integer", "enum": [ 0, 1 ], "example": 1 } }, "type": "object" }, "MenuMatrixNode": { "properties": { "menu_id": { "type": "integer", "example": 16 }, "parent_id": { "type": "integer", "example": 10, "nullable": true }, "name": { "type": "string", "example": "스크린 작업" }, "path": { "type": "string", "example": "/tenant/production/screen_work.php" }, "type": { "type": "string", "example": "workflow" }, "actions": { "properties": { "view": { "$ref": "#/components/schemas/MenuMatrixAction" }, "create": { "$ref": "#/components/schemas/MenuMatrixAction" }, "update": { "$ref": "#/components/schemas/MenuMatrixAction" }, "delete": { "$ref": "#/components/schemas/MenuMatrixAction" }, "approve": { "$ref": "#/components/schemas/MenuMatrixAction" } }, "type": "object" }, "children": { "type": "array", "items": { "$ref": "#/components/schemas/MenuMatrixNode" } } }, "type": "object" }, "MenuMatrixPayload": { "properties": { "actions": { "type": "array", "items": { "type": "string", "example": "view" } }, "tree": { "type": "array", "items": { "$ref": "#/components/schemas/MenuMatrixNode" } } }, "type": "object" }, "Post": { "required": [ "id", "board_id", "title" ], "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "board_id": { "type": "integer", "example": 1 }, "user_id": { "description": "작성자 ID", "type": "integer", "example": 1 }, "title": { "description": "제목", "type": "string", "example": "공지사항 제목" }, "content": { "description": "내용", "type": "string", "example": "공지사항 내용입니다." }, "editor_type": { "type": "string", "enum": [ "wysiwyg", "markdown", "text" ], "example": "wysiwyg" }, "ip_address": { "type": "string", "example": "127.0.0.1", "nullable": true }, "is_notice": { "description": "공지 여부", "type": "boolean", "example": false }, "is_secret": { "description": "비밀글 여부", "type": "boolean", "example": false }, "views": { "description": "조회수", "type": "integer", "example": 0 }, "status": { "type": "string", "enum": [ "draft", "published", "hidden" ], "example": "published" }, "created_at": { "type": "string", "example": "2025-01-01 12:00:00" }, "updated_at": { "type": "string", "example": "2025-01-01 12:00:00" }, "board": { "$ref": "#/components/schemas/Board" }, "files": { "type": "array", "items": { "type": "object" } } }, "type": "object" }, "PostPagination": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Post" } }, "first_page_url": { "type": "string" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 3 }, "last_page_url": { "type": "string" }, "next_page_url": { "type": "string", "nullable": true }, "path": { "type": "string" }, "per_page": { "type": "integer", "example": 15 }, "prev_page_url": { "type": "string", "nullable": true }, "to": { "type": "integer", "example": 15 }, "total": { "type": "integer", "example": 50 } }, "type": "object" }, "PostCreateRequest": { "required": [ "title", "content" ], "properties": { "title": { "type": "string", "maxLength": 200, "example": "게시글 제목" }, "content": { "type": "string", "example": "게시글 내용입니다." }, "editor_type": { "type": "string", "enum": [ "wysiwyg", "markdown", "text" ], "example": "wysiwyg" }, "is_notice": { "type": "boolean", "example": false }, "is_secret": { "type": "boolean", "example": false }, "status": { "type": "string", "enum": [ "draft", "published", "hidden" ], "example": "published" }, "custom_fields": { "description": "커스텀 필드 값 (field_id: value)", "type": "object", "nullable": true } }, "type": "object" }, "PostUpdateRequest": { "properties": { "title": { "type": "string", "maxLength": 200 }, "content": { "type": "string" }, "editor_type": { "type": "string", "enum": [ "wysiwyg", "markdown", "text" ] }, "is_notice": { "type": "boolean" }, "is_secret": { "type": "boolean" }, "status": { "type": "string", "enum": [ "draft", "published", "hidden" ] }, "custom_fields": { "type": "object", "nullable": true } }, "type": "object" }, "Comment": { "properties": { "id": { "type": "integer", "example": 1 }, "post_id": { "type": "integer", "example": 1 }, "user_id": { "type": "integer", "example": 1 }, "parent_id": { "description": "부모 댓글 ID (대댓글인 경우)", "type": "integer", "nullable": true }, "content": { "type": "string", "example": "댓글 내용" }, "status": { "type": "string", "enum": [ "active", "deleted" ], "example": "active" }, "created_at": { "type": "string", "example": "2025-01-01 12:00:00" }, "replies": { "type": "array", "items": { "$ref": "#/components/schemas/Comment" } } }, "type": "object" }, "CommentCreateRequest": { "required": [ "content" ], "properties": { "content": { "type": "string", "maxLength": 2000, "example": "댓글 내용" }, "parent_id": { "description": "대댓글인 경우 부모 댓글 ID", "type": "integer", "nullable": true } }, "type": "object" }, "Price": { "description": "단가 마스터", "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "item_type_code": { "description": "품목 유형", "type": "string", "enum": [ "PRODUCT", "MATERIAL" ], "example": "PRODUCT" }, "item_id": { "description": "품목 ID", "type": "integer", "example": 10 }, "client_group_id": { "description": "고객그룹 ID (NULL=기본가)", "type": "integer", "example": 1, "nullable": true }, "purchase_price": { "description": "매입단가 (표준원가)", "type": "number", "format": "decimal", "example": 10000, "nullable": true }, "processing_cost": { "description": "가공비", "type": "number", "format": "decimal", "example": 2000, "nullable": true }, "loss_rate": { "description": "LOSS율 (%)", "type": "number", "format": "decimal", "example": 5, "nullable": true }, "margin_rate": { "description": "마진율 (%)", "type": "number", "format": "decimal", "example": 25, "nullable": true }, "sales_price": { "description": "판매단가", "type": "number", "format": "decimal", "example": 15800, "nullable": true }, "rounding_rule": { "description": "반올림 규칙", "type": "string", "enum": [ "round", "ceil", "floor" ], "example": "round" }, "rounding_unit": { "description": "반올림 단위 (1,10,100,1000)", "type": "integer", "example": 100 }, "supplier": { "description": "공급업체", "type": "string", "example": "ABC공급", "nullable": true }, "effective_from": { "description": "적용 시작일", "type": "string", "format": "date", "example": "2025-01-01" }, "effective_to": { "description": "적용 종료일", "type": "string", "format": "date", "example": "2025-12-31", "nullable": true }, "note": { "description": "비고", "type": "string", "example": "2025년 상반기 가격", "nullable": true }, "status": { "description": "상태", "type": "string", "enum": [ "draft", "active", "inactive", "finalized" ], "example": "active" }, "is_final": { "description": "최종 확정 여부", "type": "boolean", "example": false }, "finalized_at": { "description": "확정 일시", "type": "string", "format": "datetime", "example": "2025-01-15 10:30:00", "nullable": true }, "finalized_by": { "description": "확정자 ID", "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "example": "2025-01-01 12:00:00" }, "updated_at": { "type": "string", "example": "2025-01-01 12:00:00" }, "client_group": { "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "VIP 고객" } }, "type": "object", "nullable": true } }, "type": "object" }, "PricePagination": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Price" } }, "first_page_url": { "type": "string", "example": "/api/v1/pricing?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 3 }, "last_page_url": { "type": "string", "example": "/api/v1/pricing?page=3" }, "links": { "type": "array", "items": { "properties": { "url": { "type": "string", "nullable": true }, "label": { "type": "string" }, "active": { "type": "boolean" } }, "type": "object" } }, "next_page_url": { "type": "string", "nullable": true }, "path": { "type": "string", "example": "/api/v1/pricing" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 50 } }, "type": "object" }, "PriceRevision": { "description": "단가 변경 이력", "properties": { "id": { "type": "integer", "example": 1 }, "price_id": { "type": "integer", "example": 1 }, "revision_number": { "description": "리비전 번호", "type": "integer", "example": 1 }, "changed_at": { "description": "변경 일시", "type": "string", "format": "datetime", "example": "2025-01-01 12:00:00" }, "changed_by": { "description": "변경자 ID", "type": "integer", "example": 1 }, "change_reason": { "description": "변경 사유", "type": "string", "example": "2025년 단가 인상", "nullable": true }, "before_snapshot": { "description": "변경 전 데이터", "type": "object", "nullable": true }, "after_snapshot": { "description": "변경 후 데이터", "type": "object" }, "changed_by_user": { "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "홍길동" } }, "type": "object", "nullable": true } }, "type": "object" }, "PriceStoreRequest": { "required": [ "item_type_code", "item_id", "effective_from" ], "properties": { "item_type_code": { "type": "string", "enum": [ "PRODUCT", "MATERIAL" ], "example": "PRODUCT" }, "item_id": { "type": "integer", "example": 10 }, "client_group_id": { "type": "integer", "example": 1, "nullable": true }, "purchase_price": { "type": "number", "example": 10000, "nullable": true }, "processing_cost": { "type": "number", "example": 2000, "nullable": true }, "loss_rate": { "type": "number", "example": 5, "nullable": true }, "margin_rate": { "type": "number", "example": 25, "nullable": true }, "sales_price": { "type": "number", "example": 15800, "nullable": true }, "rounding_rule": { "type": "string", "enum": [ "round", "ceil", "floor" ], "example": "round" }, "rounding_unit": { "type": "integer", "enum": [ 1, 10, 100, 1000 ], "example": 100 }, "supplier": { "type": "string", "example": "ABC공급", "nullable": true }, "effective_from": { "type": "string", "format": "date", "example": "2025-01-01" }, "effective_to": { "type": "string", "format": "date", "example": "2025-12-31", "nullable": true }, "note": { "type": "string", "example": "2025년 상반기 가격", "nullable": true }, "status": { "type": "string", "enum": [ "draft", "active", "inactive" ], "example": "draft" } }, "type": "object" }, "PriceUpdateRequest": { "properties": { "item_type_code": { "type": "string", "enum": [ "PRODUCT", "MATERIAL" ], "example": "PRODUCT" }, "item_id": { "type": "integer", "example": 10 }, "client_group_id": { "type": "integer", "example": 1, "nullable": true }, "purchase_price": { "type": "number", "example": 10000, "nullable": true }, "processing_cost": { "type": "number", "example": 2000, "nullable": true }, "loss_rate": { "type": "number", "example": 5, "nullable": true }, "margin_rate": { "type": "number", "example": 25, "nullable": true }, "sales_price": { "type": "number", "example": 15800, "nullable": true }, "rounding_rule": { "type": "string", "enum": [ "round", "ceil", "floor" ], "example": "round" }, "rounding_unit": { "type": "integer", "enum": [ 1, 10, 100, 1000 ], "example": 100 }, "supplier": { "type": "string", "example": "ABC공급", "nullable": true }, "effective_from": { "type": "string", "format": "date", "example": "2025-01-01" }, "effective_to": { "type": "string", "format": "date", "example": "2025-12-31", "nullable": true }, "note": { "type": "string", "example": "2025년 상반기 가격", "nullable": true }, "status": { "type": "string", "enum": [ "draft", "active", "inactive" ], "example": "active" }, "change_reason": { "description": "변경 사유 (리비전 기록용)", "type": "string", "example": "단가 인상", "nullable": true } }, "type": "object" }, "PriceByItemsRequest": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "properties": { "item_type_code": { "type": "string", "enum": [ "PRODUCT", "MATERIAL" ], "example": "PRODUCT" }, "item_id": { "type": "integer", "example": 10 } }, "type": "object" } }, "client_group_id": { "type": "integer", "example": 1, "nullable": true }, "date": { "type": "string", "format": "date", "example": "2025-01-15", "nullable": true } }, "type": "object" }, "PriceByItemsResult": { "type": "array", "items": { "properties": { "item_type_code": { "type": "string", "example": "PRODUCT" }, "item_id": { "type": "integer", "example": 10 }, "price": { "oneOf": [ { "$ref": "#/components/schemas/Price" } ], "nullable": true }, "has_price": { "type": "boolean", "example": true } }, "type": "object" } }, "PriceCostResult": { "properties": { "item_type_code": { "type": "string", "example": "MATERIAL" }, "item_id": { "type": "integer", "example": 123 }, "date": { "type": "string", "format": "date", "example": "2025-01-15" }, "cost_source": { "description": "원가 출처", "type": "string", "enum": [ "receipt", "standard", "not_found" ], "example": "receipt" }, "purchase_price": { "type": "number", "example": 10500, "nullable": true }, "receipt_id": { "description": "수입검사 ID (cost_source=receipt일 때)", "type": "integer", "example": 456, "nullable": true }, "receipt_date": { "type": "string", "format": "date", "example": "2025-01-10", "nullable": true }, "price_id": { "description": "단가 ID (cost_source=standard일 때)", "type": "integer", "example": null, "nullable": true } }, "type": "object" }, "Purchase": { "description": "매입 정보", "properties": { "id": { "description": "매입 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "purchase_number": { "description": "매입번호", "type": "string", "example": "PU202501150001" }, "purchase_date": { "description": "매입일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1 }, "supply_amount": { "description": "공급가액", "type": "number", "format": "float", "example": 1000000 }, "tax_amount": { "description": "세액", "type": "number", "format": "float", "example": 100000 }, "total_amount": { "description": "합계", "type": "number", "format": "float", "example": 1100000 }, "description": { "description": "적요", "type": "string", "example": "1월 매입", "nullable": true }, "status": { "description": "상태", "type": "string", "enum": [ "draft", "confirmed" ], "example": "draft" }, "withdrawal_id": { "description": "출금 연결 ID", "type": "integer", "example": 1, "nullable": true }, "client": { "description": "거래처 정보", "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "(주)공급사" } }, "type": "object", "nullable": true }, "created_by": { "description": "생성자 ID", "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "PurchaseCreateRequest": { "description": "매입 등록 요청", "required": [ "purchase_date", "client_id", "supply_amount", "tax_amount", "total_amount" ], "properties": { "purchase_date": { "description": "매입일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1 }, "supply_amount": { "description": "공급가액", "type": "number", "format": "float", "example": 1000000 }, "tax_amount": { "description": "세액", "type": "number", "format": "float", "example": 100000 }, "total_amount": { "description": "합계", "type": "number", "format": "float", "example": 1100000 }, "description": { "description": "적요", "type": "string", "maxLength": 1000, "example": "1월 매입", "nullable": true }, "withdrawal_id": { "description": "출금 연결 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "PurchaseUpdateRequest": { "description": "매입 수정 요청", "properties": { "purchase_date": { "description": "매입일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1 }, "supply_amount": { "description": "공급가액", "type": "number", "format": "float", "example": 1000000 }, "tax_amount": { "description": "세액", "type": "number", "format": "float", "example": 100000 }, "total_amount": { "description": "합계", "type": "number", "format": "float", "example": 1100000 }, "description": { "description": "적요", "type": "string", "maxLength": 1000, "example": "1월 매입", "nullable": true }, "withdrawal_id": { "description": "출금 연결 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "PurchaseSummary": { "description": "매입 요약", "properties": { "total_supply_amount": { "description": "총 공급가액", "type": "number", "format": "float", "example": 10000000 }, "total_tax_amount": { "description": "총 세액", "type": "number", "format": "float", "example": 1000000 }, "total_amount": { "description": "총 합계", "type": "number", "format": "float", "example": 11000000 }, "total_count": { "description": "총 건수", "type": "integer", "example": 10 }, "by_status": { "description": "상태별 합계", "properties": { "draft": { "properties": { "total": { "type": "number", "example": 5500000 }, "count": { "type": "integer", "example": 5 } }, "type": "object" }, "confirmed": { "properties": { "total": { "type": "number", "example": 5500000 }, "count": { "type": "integer", "example": 5 } }, "type": "object" } }, "type": "object" } }, "type": "object" }, "Quote": { "required": [ "id", "quote_number" ], "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "quote_number": { "description": "견적번호", "type": "string", "example": "KD-SC-251204-01" }, "registration_date": { "description": "등록일", "type": "string", "format": "date", "example": "2025-12-04" }, "receipt_date": { "description": "접수일", "type": "string", "format": "date", "example": "2025-12-05", "nullable": true }, "author": { "description": "작성자", "type": "string", "example": "홍길동", "nullable": true }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1, "nullable": true }, "client_name": { "description": "발주처명", "type": "string", "example": "ABC건설", "nullable": true }, "manager": { "description": "담당자", "type": "string", "example": "김담당", "nullable": true }, "contact": { "description": "연락처", "type": "string", "example": "010-1234-5678", "nullable": true }, "site_id": { "description": "현장 ID", "type": "integer", "example": 1, "nullable": true }, "site_name": { "description": "현장명", "type": "string", "example": "강남현장", "nullable": true }, "site_code": { "description": "현장코드", "type": "string", "example": "SITE-001", "nullable": true }, "product_category": { "description": "제품 카테고리", "type": "string", "enum": [ "SCREEN", "STEEL" ], "example": "SCREEN" }, "product_id": { "description": "제품 ID", "type": "integer", "example": 1, "nullable": true }, "product_code": { "description": "제품코드", "type": "string", "example": "SCR-001", "nullable": true }, "product_name": { "description": "제품명", "type": "string", "example": "전동스크린", "nullable": true }, "open_size_width": { "description": "개구부 폭(mm)", "type": "number", "format": "float", "example": 3000, "nullable": true }, "open_size_height": { "description": "개구부 높이(mm)", "type": "number", "format": "float", "example": 2500, "nullable": true }, "quantity": { "description": "수량", "type": "integer", "example": 1 }, "unit_symbol": { "description": "단위", "type": "string", "example": "EA", "nullable": true }, "floors": { "description": "층수", "type": "string", "example": "1F~3F", "nullable": true }, "material_cost": { "description": "자재비", "type": "number", "format": "float", "example": 500000 }, "labor_cost": { "description": "인건비", "type": "number", "format": "float", "example": 100000 }, "install_cost": { "description": "설치비", "type": "number", "format": "float", "example": 50000 }, "subtotal": { "description": "소계", "type": "number", "format": "float", "example": 650000 }, "discount_rate": { "description": "할인율(%)", "type": "number", "format": "float", "example": 10 }, "discount_amount": { "description": "할인금액", "type": "number", "format": "float", "example": 65000 }, "total_amount": { "description": "합계금액", "type": "number", "format": "float", "example": 585000 }, "status": { "description": "상태", "type": "string", "enum": [ "draft", "sent", "approved", "rejected", "finalized", "converted" ], "example": "draft" }, "current_revision": { "description": "현재 리비전", "type": "integer", "example": 0 }, "is_final": { "description": "확정 여부", "type": "boolean", "example": false }, "finalized_at": { "description": "확정일시", "type": "string", "format": "date-time", "nullable": true }, "finalized_by": { "description": "확정자 ID", "type": "integer", "nullable": true }, "completion_date": { "description": "완료예정일", "type": "string", "format": "date", "nullable": true }, "remarks": { "description": "비고", "type": "string", "nullable": true }, "memo": { "description": "메모", "type": "string", "nullable": true }, "notes": { "description": "참고사항", "type": "string", "nullable": true }, "calculation_inputs": { "description": "자동산출 입력값", "type": "object", "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-12-04 10:00:00" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-12-04 10:00:00" }, "items": { "description": "견적 품목", "type": "array", "items": { "$ref": "#/components/schemas/QuoteItem" } } }, "type": "object" }, "QuoteItem": { "properties": { "id": { "type": "integer", "example": 1 }, "quote_id": { "type": "integer", "example": 1 }, "item_id": { "description": "품목 ID", "type": "integer", "example": 1, "nullable": true }, "item_code": { "description": "품목코드", "type": "string", "example": "SCR-FABRIC-001" }, "item_name": { "description": "품목명", "type": "string", "example": "스크린 원단" }, "specification": { "description": "규격", "type": "string", "example": "3100 x 2650 mm", "nullable": true }, "unit": { "description": "단위", "type": "string", "example": "m²" }, "base_quantity": { "description": "기본수량", "type": "number", "format": "float", "example": 1 }, "calculated_quantity": { "description": "산출수량", "type": "number", "format": "float", "example": 8.215 }, "unit_price": { "description": "단가", "type": "number", "format": "float", "example": 25000 }, "total_price": { "description": "금액", "type": "number", "format": "float", "example": 205375 }, "formula": { "description": "수량 수식", "type": "string", "example": "AREA * QTY", "nullable": true }, "formula_result": { "description": "수식 결과", "type": "string", "nullable": true }, "formula_source": { "description": "수식 출처", "type": "string", "nullable": true }, "formula_category": { "description": "비용 카테고리", "type": "string", "example": "material", "nullable": true }, "note": { "description": "비고", "type": "string", "nullable": true }, "sort_order": { "description": "정렬순서", "type": "integer", "example": 0 } }, "type": "object" }, "QuotePagination": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Quote" } }, "first_page_url": { "type": "string", "example": "/api/v1/quotes?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 3 }, "last_page_url": { "type": "string", "example": "/api/v1/quotes?page=3" }, "next_page_url": { "type": "string", "example": "/api/v1/quotes?page=2", "nullable": true }, "path": { "type": "string", "example": "/api/v1/quotes" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 50 } }, "type": "object" }, "QuoteCreateRequest": { "properties": { "quote_number": { "description": "견적번호(미입력시 자동생성)", "type": "string", "maxLength": 50, "nullable": true }, "registration_date": { "type": "string", "format": "date", "example": "2025-12-04", "nullable": true }, "receipt_date": { "type": "string", "format": "date", "nullable": true }, "author": { "type": "string", "maxLength": 50, "nullable": true }, "client_id": { "type": "integer", "nullable": true }, "client_name": { "type": "string", "maxLength": 100, "nullable": true }, "manager": { "type": "string", "maxLength": 50, "nullable": true }, "contact": { "type": "string", "maxLength": 50, "nullable": true }, "site_id": { "type": "integer", "nullable": true }, "site_name": { "type": "string", "maxLength": 100, "nullable": true }, "site_code": { "type": "string", "maxLength": 50, "nullable": true }, "product_category": { "type": "string", "enum": [ "SCREEN", "STEEL" ], "nullable": true }, "product_id": { "type": "integer", "nullable": true }, "product_code": { "type": "string", "maxLength": 50, "nullable": true }, "product_name": { "type": "string", "maxLength": 100, "nullable": true }, "open_size_width": { "type": "number", "format": "float", "nullable": true }, "open_size_height": { "type": "number", "format": "float", "nullable": true }, "quantity": { "type": "integer", "minimum": 1, "nullable": true }, "unit_symbol": { "type": "string", "maxLength": 10, "nullable": true }, "floors": { "type": "string", "maxLength": 50, "nullable": true }, "material_cost": { "type": "number", "format": "float", "nullable": true }, "labor_cost": { "type": "number", "format": "float", "nullable": true }, "install_cost": { "type": "number", "format": "float", "nullable": true }, "discount_rate": { "type": "number", "format": "float", "maximum": 100, "minimum": 0, "nullable": true }, "total_amount": { "type": "number", "format": "float", "nullable": true }, "completion_date": { "type": "string", "format": "date", "nullable": true }, "remarks": { "type": "string", "maxLength": 500, "nullable": true }, "memo": { "type": "string", "nullable": true }, "notes": { "type": "string", "nullable": true }, "calculation_inputs": { "type": "object", "nullable": true }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/QuoteItemRequest" }, "nullable": true } }, "type": "object" }, "QuoteUpdateRequest": { "properties": { "receipt_date": { "type": "string", "format": "date", "nullable": true }, "author": { "type": "string", "maxLength": 50, "nullable": true }, "client_id": { "type": "integer", "nullable": true }, "client_name": { "type": "string", "maxLength": 100, "nullable": true }, "manager": { "type": "string", "maxLength": 50, "nullable": true }, "contact": { "type": "string", "maxLength": 50, "nullable": true }, "site_id": { "type": "integer", "nullable": true }, "site_name": { "type": "string", "maxLength": 100, "nullable": true }, "site_code": { "type": "string", "maxLength": 50, "nullable": true }, "product_category": { "type": "string", "enum": [ "SCREEN", "STEEL" ], "nullable": true }, "product_id": { "type": "integer", "nullable": true }, "product_code": { "type": "string", "maxLength": 50, "nullable": true }, "product_name": { "type": "string", "maxLength": 100, "nullable": true }, "open_size_width": { "type": "number", "format": "float", "nullable": true }, "open_size_height": { "type": "number", "format": "float", "nullable": true }, "quantity": { "type": "integer", "minimum": 1, "nullable": true }, "unit_symbol": { "type": "string", "maxLength": 10, "nullable": true }, "floors": { "type": "string", "maxLength": 50, "nullable": true }, "material_cost": { "type": "number", "format": "float", "nullable": true }, "labor_cost": { "type": "number", "format": "float", "nullable": true }, "install_cost": { "type": "number", "format": "float", "nullable": true }, "discount_rate": { "type": "number", "format": "float", "maximum": 100, "minimum": 0, "nullable": true }, "total_amount": { "type": "number", "format": "float", "nullable": true }, "completion_date": { "type": "string", "format": "date", "nullable": true }, "remarks": { "type": "string", "maxLength": 500, "nullable": true }, "memo": { "type": "string", "nullable": true }, "notes": { "type": "string", "nullable": true }, "calculation_inputs": { "type": "object", "nullable": true }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/QuoteItemRequest" }, "nullable": true } }, "type": "object" }, "QuoteItemRequest": { "properties": { "item_id": { "type": "integer", "nullable": true }, "item_code": { "type": "string", "maxLength": 50, "nullable": true }, "item_name": { "type": "string", "maxLength": 100, "nullable": true }, "specification": { "type": "string", "maxLength": 200, "nullable": true }, "unit": { "type": "string", "maxLength": 20, "nullable": true }, "base_quantity": { "type": "number", "format": "float", "nullable": true }, "calculated_quantity": { "type": "number", "format": "float", "nullable": true }, "unit_price": { "type": "number", "format": "float", "nullable": true }, "total_price": { "type": "number", "format": "float", "nullable": true }, "formula": { "type": "string", "maxLength": 500, "nullable": true }, "formula_result": { "type": "string", "nullable": true }, "formula_source": { "type": "string", "nullable": true }, "formula_category": { "type": "string", "maxLength": 50, "nullable": true }, "note": { "type": "string", "maxLength": 500, "nullable": true }, "sort_order": { "type": "integer", "nullable": true } }, "type": "object" }, "QuoteCalculateRequest": { "properties": { "product_category": { "description": "제품 카테고리", "type": "string", "enum": [ "SCREEN", "STEEL" ], "nullable": true }, "W0": { "description": "개구부 폭(mm)", "type": "number", "format": "float", "example": 3000 }, "H0": { "description": "개구부 높이(mm)", "type": "number", "format": "float", "example": 2500 }, "QTY": { "description": "수량", "type": "integer", "example": 1 }, "INSTALL_TYPE": { "description": "설치유형(스크린)", "type": "string", "enum": [ "wall", "ceiling", "floor" ], "nullable": true }, "MOTOR_TYPE": { "description": "모터유형(스크린)", "type": "string", "enum": [ "standard", "heavy" ], "nullable": true }, "CONTROL_TYPE": { "description": "제어방식(스크린)", "type": "string", "enum": [ "switch", "remote", "smart" ], "nullable": true }, "MATERIAL": { "description": "재질(철재)", "type": "string", "enum": [ "ss304", "ss316", "galvanized" ], "nullable": true }, "THICKNESS": { "description": "두께(철재)", "type": "number", "format": "float", "nullable": true }, "FINISH": { "description": "표면처리(철재)", "type": "string", "enum": [ "hairline", "mirror", "matte" ], "nullable": true }, "WELDING": { "description": "용접방식(철재)", "type": "string", "enum": [ "tig", "mig", "spot" ], "nullable": true } }, "type": "object" }, "QuoteCalculationResult": { "properties": { "inputs": { "description": "입력 파라미터", "type": "object" }, "outputs": { "description": "산출값 (W1, H1, AREA, WEIGHT 등)", "type": "object" }, "items": { "description": "산출된 품목", "type": "array", "items": { "$ref": "#/components/schemas/QuoteItem" } }, "costs": { "properties": { "material_cost": { "type": "number", "format": "float" }, "labor_cost": { "type": "number", "format": "float" }, "install_cost": { "type": "number", "format": "float" }, "subtotal": { "type": "number", "format": "float" } }, "type": "object" }, "errors": { "type": "array", "items": { "type": "string" } } }, "type": "object" }, "QuoteSendEmailRequest": { "properties": { "email": { "description": "수신자 이메일", "type": "string", "format": "email", "nullable": true }, "name": { "description": "수신자명", "type": "string", "maxLength": 100, "nullable": true }, "subject": { "description": "제목", "type": "string", "maxLength": 200, "nullable": true }, "message": { "description": "본문", "type": "string", "maxLength": 2000, "nullable": true }, "cc": { "description": "참조", "type": "array", "items": { "type": "string", "format": "email" }, "nullable": true }, "attach_pdf": { "description": "PDF 첨부 여부", "type": "boolean", "example": true } }, "type": "object" }, "QuoteSendKakaoRequest": { "properties": { "phone": { "description": "수신자 전화번호", "type": "string", "maxLength": 20, "nullable": true }, "name": { "description": "수신자명", "type": "string", "maxLength": 100, "nullable": true }, "template_code": { "description": "템플릿 코드", "type": "string", "maxLength": 50, "nullable": true }, "view_url": { "description": "조회 URL", "type": "string", "format": "uri", "nullable": true } }, "type": "object" }, "QuoteNumberPreview": { "properties": { "quote_number": { "type": "string", "example": "KD-SC-251204-01" }, "product_category": { "type": "string", "example": "SCREEN" }, "generated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "DailyReport": { "description": "일일 일보", "properties": { "date": { "description": "기준일", "type": "string", "format": "date", "example": "2025-01-15" }, "previous_balance": { "description": "전일 잔액", "type": "number", "format": "float", "example": 10000000 }, "daily_deposit": { "description": "당일 입금액", "type": "number", "format": "float", "example": 5000000 }, "daily_withdrawal": { "description": "당일 출금액", "type": "number", "format": "float", "example": 3000000 }, "current_balance": { "description": "당일 잔액", "type": "number", "format": "float", "example": 12000000 }, "details": { "description": "상세 내역", "type": "array", "items": { "properties": { "type": { "description": "유형", "type": "string", "enum": [ "deposit", "withdrawal" ] }, "type_label": { "description": "유형 라벨", "type": "string", "example": "입금" }, "client_name": { "description": "거래처명", "type": "string", "example": "(주)테스트" }, "account_code": { "description": "계정과목", "type": "string", "example": "401" }, "deposit_amount": { "description": "입금액", "type": "number", "format": "float", "example": 1000000 }, "withdrawal_amount": { "description": "출금액", "type": "number", "format": "float", "example": 0 }, "description": { "description": "적요", "type": "string", "example": "1월 매출 입금" }, "payment_method": { "description": "결제수단", "type": "string", "example": "transfer" } }, "type": "object" } } }, "type": "object" }, "ExpenseEstimate": { "description": "지출 예상 내역서", "properties": { "year_month": { "description": "기준 연월", "type": "string", "example": "2025-01" }, "total_estimate": { "description": "예상 지출 합계", "type": "number", "format": "float", "example": 15000000 }, "account_balance": { "description": "계좌 잔액", "type": "number", "format": "float", "example": 20000000 }, "expected_balance": { "description": "예상 잔액", "type": "number", "format": "float", "example": 5000000 }, "items": { "description": "지출 예상 내역", "type": "array", "items": { "properties": { "id": { "description": "매입 ID", "type": "integer", "example": 1 }, "expected_date": { "description": "예상 지급일", "type": "string", "format": "date", "example": "2025-01-20" }, "item_name": { "description": "품목", "type": "string", "example": "원자재 구매" }, "amount": { "description": "지출금액", "type": "number", "format": "float", "example": 5000000 }, "client_name": { "description": "거래처", "type": "string", "example": "(주)공급사" }, "account_name": { "description": "계좌", "type": "string", "example": "법인통장" } }, "type": "object" } }, "monthly_summary": { "description": "월별 합계", "properties": { "by_month": { "type": "array", "items": { "properties": { "month": { "description": "월", "type": "string", "example": "2025/01" }, "total": { "description": "합계", "type": "number", "format": "float", "example": 5000000 } }, "type": "object" } }, "total_expense": { "description": "지출 합계", "type": "number", "format": "float", "example": 15000000 }, "account_balance": { "description": "계좌 잔액", "type": "number", "format": "float", "example": 20000000 }, "final_difference": { "description": "최종 차액", "type": "number", "format": "float", "example": 5000000 } }, "type": "object" } }, "type": "object" }, "Role": { "description": "역할 상세", "required": [ "id", "name", "guard_name" ], "properties": { "id": { "type": "integer", "example": 3 }, "tenant_id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "menu-manager" }, "description": { "type": "string", "example": "메뉴 관리 역할", "nullable": true }, "guard_name": { "type": "string", "example": "api" }, "created_at": { "type": "string", "format": "date-time", "example": "2025-08-16 10:00:00" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-08-16 10:00:00" } }, "type": "object" }, "RoleBrief": { "description": "역할 요약", "required": [ "id", "name" ], "properties": { "id": { "type": "integer", "example": 3 }, "name": { "type": "string", "example": "readonly" }, "description": { "type": "string", "example": "읽기 전용", "nullable": true }, "guard_name": { "type": "string", "example": "api" } }, "type": "object" }, "RoleList": { "type": "array", "items": { "$ref": "#/components/schemas/RoleBrief" } }, "RoleCreateRequest": { "required": [ "name" ], "properties": { "name": { "description": "역할명(테넌트+가드 내 고유)", "type": "string", "example": "menu-manager" }, "description": { "type": "string", "example": "메뉴 관리 역할", "nullable": true } }, "type": "object" }, "RoleUpdateRequest": { "properties": { "name": { "type": "string", "example": "menu-admin" }, "description": { "type": "string", "example": "설명 변경", "nullable": true } }, "type": "object" }, "PermissionBrief": { "description": "퍼미션 요약", "required": [ "id", "name", "guard_name" ], "properties": { "id": { "type": "integer", "example": 15 }, "tenant_id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "menu:101.view" }, "guard_name": { "type": "string", "example": "api" }, "created_at": { "type": "string", "format": "date-time", "example": "2025-08-16 10:00:00" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-08-16 10:00:00" } }, "type": "object" }, "PermissionList": { "type": "array", "items": { "$ref": "#/components/schemas/PermissionBrief" } }, "RolePermissionGrantRequest": { "description": "역할에 퍼미션 부여. 방법 A: permission_names 배열. 방법 B: menus + actions 조합.", "type": "object", "oneOf": [ { "description": "방법 A: 퍼미션 이름 배열", "required": [ "permission_names" ], "properties": { "permission_names": { "type": "array", "items": { "type": "string" }, "example": [ "menu:101.view", "menu:101.create" ] } }, "type": "object" }, { "description": "방법 B: 메뉴+액션 조합", "required": [ "menus", "actions" ], "properties": { "menus": { "type": "array", "items": { "type": "integer" }, "example": [ 101, 102 ] }, "actions": { "type": "array", "items": { "type": "string" }, "example": [ "view", "create", "update", "delete" ] } }, "type": "object" } ] }, "RolePermissionRevokeRequest": { "description": "역할에서 퍼미션 회수. 방법 A: permission_names 배열. 방법 B: menus + actions 조합.", "type": "object", "oneOf": [ { "description": "방법 A: 퍼미션 이름 배열", "required": [ "permission_names" ], "properties": { "permission_names": { "type": "array", "items": { "type": "string" }, "example": [ "menu:101.view", "menu:101.create" ] } }, "type": "object" }, { "description": "방법 B: 메뉴+액션 조합", "required": [ "menus", "actions" ], "properties": { "menus": { "type": "array", "items": { "type": "integer" }, "example": [ 101 ] }, "actions": { "type": "array", "items": { "type": "string" }, "example": [ "create" ] } }, "type": "object" } ] }, "RolePermissionSyncRequest": { "description": "역할의 퍼미션을 전달된 목록으로 완전히 교체(동기화). 방법 A 또는 B.", "type": "object", "oneOf": [ { "description": "방법 A: 퍼미션 이름 배열", "required": [ "permission_names" ], "properties": { "permission_names": { "type": "array", "items": { "type": "string" }, "example": [ "menu:101.view", "menu:101.update" ] } }, "type": "object" }, { "description": "방법 B: 메뉴+액션 조합", "required": [ "menus", "actions" ], "properties": { "menus": { "type": "array", "items": { "type": "integer" }, "example": [ 101, 102 ] }, "actions": { "type": "array", "items": { "type": "string" }, "example": [ "view", "update" ] } }, "type": "object" } ] }, "Sale": { "description": "매출 정보", "properties": { "id": { "description": "매출 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "sale_number": { "description": "매출번호", "type": "string", "example": "SL202501150001" }, "sale_date": { "description": "매출일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1 }, "supply_amount": { "description": "공급가액", "type": "number", "format": "float", "example": 1000000 }, "tax_amount": { "description": "세액", "type": "number", "format": "float", "example": 100000 }, "total_amount": { "description": "합계", "type": "number", "format": "float", "example": 1100000 }, "description": { "description": "적요", "type": "string", "example": "1월 매출", "nullable": true }, "status": { "description": "상태", "type": "string", "enum": [ "draft", "confirmed", "invoiced" ], "example": "draft" }, "tax_invoice_id": { "description": "세금계산서 ID", "type": "integer", "example": 1, "nullable": true }, "deposit_id": { "description": "입금 연결 ID", "type": "integer", "example": 1, "nullable": true }, "client": { "description": "거래처 정보", "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "(주)테스트" } }, "type": "object", "nullable": true }, "created_by": { "description": "생성자 ID", "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "SaleCreateRequest": { "description": "매출 등록 요청", "required": [ "sale_date", "client_id", "supply_amount", "tax_amount", "total_amount" ], "properties": { "sale_date": { "description": "매출일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1 }, "supply_amount": { "description": "공급가액", "type": "number", "format": "float", "example": 1000000 }, "tax_amount": { "description": "세액", "type": "number", "format": "float", "example": 100000 }, "total_amount": { "description": "합계", "type": "number", "format": "float", "example": 1100000 }, "description": { "description": "적요", "type": "string", "maxLength": 1000, "example": "1월 매출", "nullable": true }, "deposit_id": { "description": "입금 연결 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "SaleUpdateRequest": { "description": "매출 수정 요청", "properties": { "sale_date": { "description": "매출일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1 }, "supply_amount": { "description": "공급가액", "type": "number", "format": "float", "example": 1000000 }, "tax_amount": { "description": "세액", "type": "number", "format": "float", "example": 100000 }, "total_amount": { "description": "합계", "type": "number", "format": "float", "example": 1100000 }, "description": { "description": "적요", "type": "string", "maxLength": 1000, "example": "1월 매출", "nullable": true }, "deposit_id": { "description": "입금 연결 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "SaleSummary": { "description": "매출 요약", "properties": { "total_supply_amount": { "description": "총 공급가액", "type": "number", "format": "float", "example": 10000000 }, "total_tax_amount": { "description": "총 세액", "type": "number", "format": "float", "example": 1000000 }, "total_amount": { "description": "총 합계", "type": "number", "format": "float", "example": 11000000 }, "total_count": { "description": "총 건수", "type": "integer", "example": 10 }, "by_status": { "description": "상태별 합계", "properties": { "draft": { "properties": { "total": { "type": "number", "example": 5500000 }, "count": { "type": "integer", "example": 5 } }, "type": "object" }, "confirmed": { "properties": { "total": { "type": "number", "example": 5500000 }, "count": { "type": "integer", "example": 5 } }, "type": "object" } }, "type": "object" } }, "type": "object" }, "Site": { "description": "현장 정보", "properties": { "id": { "description": "현장 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "name": { "description": "현장명", "type": "string", "example": "강남 현장" }, "address": { "description": "현장 주소", "type": "string", "example": "서울시 강남구 테헤란로 123", "nullable": true }, "latitude": { "description": "위도", "type": "number", "format": "float", "example": 37.5012, "nullable": true }, "longitude": { "description": "경도", "type": "number", "format": "float", "example": 127.0396, "nullable": true }, "is_active": { "description": "활성화 여부", "type": "boolean", "example": true }, "created_by": { "description": "생성자 ID", "type": "integer", "example": 1, "nullable": true }, "updated_by": { "description": "수정자 ID", "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "SiteCreateRequest": { "description": "현장 등록 요청", "required": [ "name" ], "properties": { "name": { "description": "현장명", "type": "string", "maxLength": 100, "example": "강남 현장" }, "address": { "description": "현장 주소", "type": "string", "maxLength": 255, "example": "서울시 강남구 테헤란로 123" }, "latitude": { "description": "위도", "type": "number", "format": "float", "maximum": 90, "minimum": -90, "example": 37.5012 }, "longitude": { "description": "경도", "type": "number", "format": "float", "maximum": 180, "minimum": -180, "example": 127.0396 }, "is_active": { "description": "활성화 여부", "type": "boolean", "example": true } }, "type": "object" }, "SiteUpdateRequest": { "description": "현장 수정 요청", "properties": { "name": { "description": "현장명", "type": "string", "maxLength": 100, "example": "강남 현장" }, "address": { "description": "현장 주소", "type": "string", "maxLength": 255, "example": "서울시 강남구 테헤란로 123" }, "latitude": { "description": "위도", "type": "number", "format": "float", "maximum": 90, "minimum": -90, "example": 37.5012 }, "longitude": { "description": "경도", "type": "number", "format": "float", "maximum": 180, "minimum": -180, "example": 127.0396 }, "is_active": { "description": "활성화 여부", "type": "boolean", "example": true } }, "type": "object" }, "SiteListItem": { "description": "현장 목록 아이템 (셀렉트박스용)", "properties": { "id": { "description": "현장 ID", "type": "integer", "example": 1 }, "name": { "description": "현장명", "type": "string", "example": "강남 현장" }, "address": { "description": "현장 주소", "type": "string", "example": "서울시 강남구", "nullable": true } }, "type": "object" }, "Tenant": { "description": "테넌트 상세 정보", "required": [ "id", "company_name" ], "properties": { "id": { "type": "integer", "example": 1 }, "company_name": { "type": "string", "example": "(주)경동기업" }, "code": { "type": "string", "example": "KDCOM" }, "email": { "type": "string", "example": "kd5130@naver.com" }, "phone": { "type": "string", "example": "01083935130" }, "address": { "type": "string", "example": "경기도 김포시 통진읍 옹정로 45-22" }, "business_num": { "type": "string", "example": "1398700333" }, "corp_reg_no": { "type": "string", "example": null, "nullable": true }, "ceo_name": { "type": "string", "example": "이대표" }, "homepage": { "type": "string", "example": null, "nullable": true }, "fax": { "type": "string", "example": null, "nullable": true }, "logo": { "type": "string", "example": null, "nullable": true }, "admin_memo": { "type": "string", "example": null, "nullable": true }, "options": { "type": "string", "example": null, "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-07-16 18:28:41" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-07-25 23:13:06" }, "deleted_at": { "type": "string", "format": "date-time", "example": null, "nullable": true } }, "type": "object" }, "TenantPagination": { "description": "라라벨 LengthAwarePaginator 기본 구조", "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/TenantBrief" } }, "first_page_url": { "type": "string", "example": "/api/v1/tenants/list?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 1 }, "last_page_url": { "type": "string", "example": "/api/v1/tenants/list?page=1" }, "links": { "type": "array", "items": { "properties": { "url": { "type": "string", "example": null, "nullable": true }, "label": { "type": "string", "example": "« Previous" }, "active": { "type": "boolean", "example": false } }, "type": "object" } }, "next_page_url": { "type": "string", "example": null, "nullable": true }, "path": { "type": "string", "example": "/api/v1/tenants/list" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 3 }, "total": { "type": "integer", "example": 3 } }, "type": "object" }, "TenantCreateRequest": { "required": [ "company_name" ], "properties": { "company_name": { "description": "회사명", "type": "string", "example": "(주)신규기업" }, "email": { "description": "대표 이메일", "type": "string", "example": "newcompany@example.com", "nullable": true }, "phone": { "description": "대표 연락처", "type": "string", "example": "01012345678", "nullable": true }, "address": { "description": "주소", "type": "string", "example": "서울시 강남구", "nullable": true }, "business_num": { "description": "사업자등록번호", "type": "string", "example": "1234567890", "nullable": true }, "ceo_name": { "description": "대표자명", "type": "string", "example": "김대표", "nullable": true } }, "type": "object" }, "TenantUpdateRequest": { "properties": { "tenant_id": { "description": "수정 대상 테넌트 ID", "type": "integer", "example": 1 }, "company_name": { "description": "회사명", "type": "string", "example": "(주)신규기업" }, "email": { "description": "대표 이메일", "type": "string", "example": "newcompany@example.com" }, "phone": { "description": "대표 연락처", "type": "string", "example": "01012345678" }, "address": { "description": "주소", "type": "string", "example": "서울시 강남구", "nullable": true }, "business_num": { "description": "사업자등록번호", "type": "string", "example": "1234567890", "nullable": true }, "ceo_name": { "description": "대표자명", "type": "string", "example": "김대표", "nullable": true } }, "type": "object" }, "TenantStatField": { "required": [ "id", "tenant_id", "target_table", "field_key", "field_name", "field_type" ], "properties": { "id": { "type": "integer", "example": 1 }, "tenant_id": { "type": "integer", "example": 1 }, "target_table": { "type": "string", "example": "products" }, "field_key": { "type": "string", "example": "margin_rate" }, "field_name": { "type": "string", "example": "마진율(%)" }, "field_type": { "type": "string", "example": "decimal" }, "aggregation_types": { "type": "array", "items": { "type": "string" }, "example": [ "avg", "min", "max" ], "nullable": true }, "is_critical": { "type": "boolean", "example": true }, "display_order": { "type": "integer", "example": 0 }, "description": { "type": "string", "example": "제품 마진율 통계", "nullable": true }, "created_by": { "type": "integer", "example": 1, "nullable": true }, "updated_by": { "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "example": "2025-11-14 10:00:00" }, "updated_at": { "type": "string", "example": "2025-11-14 10:10:00" } }, "type": "object" }, "TenantStatFieldPagination": { "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/TenantStatField" } }, "first_page_url": { "type": "string", "example": "/api/v1/tenant-stat-fields?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 2 }, "last_page_url": { "type": "string", "example": "/api/v1/tenant-stat-fields?page=2" }, "links": { "type": "array", "items": { "properties": { "url": { "type": "string", "example": null, "nullable": true }, "label": { "type": "string", "example": "« Previous" }, "active": { "type": "boolean", "example": false } }, "type": "object" } }, "next_page_url": { "type": "string", "example": "/api/v1/tenant-stat-fields?page=2", "nullable": true }, "path": { "type": "string", "example": "/api/v1/tenant-stat-fields" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 20 }, "total": { "type": "integer", "example": 9 } }, "type": "object" }, "TenantStatFieldCreateRequest": { "required": [ "target_table", "field_key", "field_name", "field_type" ], "properties": { "target_table": { "type": "string", "maxLength": 50, "example": "products" }, "field_key": { "type": "string", "maxLength": 100, "example": "processing_cost" }, "field_name": { "type": "string", "maxLength": 100, "example": "가공비(원)" }, "field_type": { "type": "string", "maxLength": 20, "example": "decimal" }, "aggregation_types": { "type": "array", "items": { "type": "string", "enum": [ "avg", "sum", "min", "max", "count" ] }, "example": [ "avg", "sum" ], "nullable": true }, "is_critical": { "type": "boolean", "example": false, "nullable": true }, "display_order": { "type": "integer", "example": 0, "nullable": true }, "description": { "type": "string", "example": "제품별 가공비 통계", "nullable": true } }, "type": "object" }, "TenantStatFieldUpdateRequest": { "properties": { "target_table": { "type": "string", "maxLength": 50, "example": "products" }, "field_key": { "type": "string", "maxLength": 100, "example": "processing_cost" }, "field_name": { "type": "string", "maxLength": 100, "example": "가공비(원)" }, "field_type": { "type": "string", "maxLength": 20, "example": "decimal" }, "aggregation_types": { "type": "array", "items": { "type": "string", "enum": [ "avg", "sum", "min", "max", "count" ] }, "nullable": true }, "is_critical": { "type": "boolean", "example": true, "nullable": true }, "display_order": { "type": "integer", "example": 5, "nullable": true }, "description": { "type": "string", "example": "제품별 가공비 통계 (일일 집계)", "nullable": true } }, "type": "object" }, "TenantStatFieldReorderRequest": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "properties": { "id": { "type": "integer", "example": 1 }, "display_order": { "type": "integer", "example": 10 } }, "type": "object" } } }, "type": "object" }, "TenantStatFieldBulkUpsertRequest": { "required": [ "items" ], "properties": { "items": { "type": "array", "items": { "properties": { "id": { "description": "수정 시 ID 필수, 신규 시 null", "type": "integer", "example": null, "nullable": true }, "target_table": { "type": "string", "maxLength": 50, "example": "products" }, "field_key": { "type": "string", "maxLength": 100, "example": "margin_rate" }, "field_name": { "type": "string", "maxLength": 100, "example": "마진율(%)" }, "field_type": { "type": "string", "maxLength": 20, "example": "decimal" }, "aggregation_types": { "type": "array", "items": { "type": "string" }, "nullable": true }, "is_critical": { "type": "boolean", "example": true, "nullable": true }, "display_order": { "type": "integer", "example": 0, "nullable": true }, "description": { "type": "string", "example": null, "nullable": true } }, "type": "object" } } }, "type": "object" }, "Member": { "description": "회원 기본 정보", "required": [ "id", "user_id", "name", "email" ], "properties": { "id": { "type": "integer", "example": 1 }, "user_id": { "type": "string", "example": "hamss" }, "phone": { "type": "string", "example": "010-4820-9104", "nullable": true }, "options": { "type": "string", "example": null, "nullable": true }, "name": { "type": "string", "example": "Kent" }, "email": { "type": "string", "example": "codebridge@gmail.com" }, "email_verified_at": { "type": "string", "format": "date-time", "example": null, "nullable": true }, "last_login_at": { "type": "string", "format": "date-time", "example": null, "nullable": true }, "current_team_id": { "type": "integer", "example": null, "nullable": true }, "profile_photo_path": { "type": "string", "example": null, "nullable": true }, "created_at": { "type": "string", "format": "date-time", "example": "2025-07-16 18:28:41" }, "updated_at": { "type": "string", "format": "date-time", "example": "2025-07-25 23:13:06" }, "deleted_at": { "type": "string", "format": "date-time", "example": null, "nullable": true } }, "type": "object" }, "MemberPagination": { "description": "라라벨 LengthAwarePaginator 기본 구조", "properties": { "current_page": { "type": "integer", "example": 1 }, "data": { "type": "array", "items": { "$ref": "#/components/schemas/Member" } }, "first_page_url": { "type": "string", "example": "/api/v1/users/index?page=1" }, "from": { "type": "integer", "example": 1 }, "last_page": { "type": "integer", "example": 1 }, "last_page_url": { "type": "string", "example": "/api/v1/users/index?page=1" }, "links": { "type": "array", "items": { "properties": { "url": { "type": "string", "example": null, "nullable": true }, "label": { "type": "string", "example": "« Previous" }, "active": { "type": "boolean", "example": false } }, "type": "object" } }, "next_page_url": { "type": "string", "example": null, "nullable": true }, "path": { "type": "string", "example": "/api/v1/users/index" }, "per_page": { "type": "integer", "example": 20 }, "prev_page_url": { "type": "string", "example": null, "nullable": true }, "to": { "type": "integer", "example": 3 }, "total": { "type": "integer", "example": 3 } }, "type": "object" }, "TenantBrief": { "description": "간단 테넌트 정보", "required": [ "id", "company_name" ], "properties": { "id": { "type": "integer", "example": 1 }, "company_name": { "type": "string", "example": "(주)경동기업" }, "code": { "type": "string", "example": "KDCOM" }, "email": { "type": "string", "example": "kd5130@naver.com" }, "phone": { "type": "string", "example": "01083935130" }, "address": { "type": "string", "example": "경기도 김포시 통진읍 옹정로 45-22" }, "business_num": { "type": "string", "example": "1398700333" }, "corp_reg_no": { "type": "string", "example": null, "nullable": true }, "ceo_name": { "type": "string", "example": "이대표" }, "homepage": { "type": "string", "example": null, "nullable": true }, "fax": { "type": "string", "example": null, "nullable": true }, "logo": { "type": "string", "example": null, "nullable": true }, "admin_memo": { "type": "string", "example": null, "nullable": true }, "options": { "type": "string", "example": null, "nullable": true } }, "type": "object" }, "MeResponseData": { "description": "내 정보 + 테넌트 정보", "properties": { "user": { "$ref": "#/components/schemas/Member" }, "tenant": { "$ref": "#/components/schemas/TenantBrief" } }, "type": "object" }, "UserUpdateRequest": { "description": "사용자 정보 수정 요청", "properties": { "name": { "type": "string", "maxLength": 100, "example": "홍길동" }, "phone": { "type": "string", "maxLength": 20, "example": "010-1234-5678", "nullable": true }, "email": { "type": "string", "maxLength": 100, "example": "user@example.com" } }, "type": "object" }, "PasswordChangeRequest": { "description": "비밀번호 변경 요청", "required": [ "current_password", "new_password", "new_password_confirmation" ], "properties": { "current_password": { "type": "string", "format": "password", "example": "current123" }, "new_password": { "type": "string", "format": "password", "minLength": 8, "example": "newpass123" }, "new_password_confirmation": { "type": "string", "format": "password", "example": "newpass123" } }, "type": "object" }, "SwitchTenantRequest": { "description": "테넌트 전환 요청", "required": [ "tenant_id" ], "properties": { "tenant_id": { "type": "integer", "example": 2 } }, "type": "object" }, "UserRoleGrantRequest": { "description": "사용자에게 역할 부여. role_names 또는 role_ids 중 하나 사용.", "type": "object", "oneOf": [ { "required": [ "role_names" ], "properties": { "role_names": { "type": "array", "items": { "type": "string" }, "example": [ "menu-manager", "readonly" ] } }, "type": "object" }, { "required": [ "role_ids" ], "properties": { "role_ids": { "type": "array", "items": { "type": "integer" }, "example": [ 1, 2 ] } }, "type": "object" } ] }, "UserRoleRevokeRequest": { "description": "사용자로부터 역할 회수. role_names 또는 role_ids 중 하나 사용.", "type": "object", "oneOf": [ { "required": [ "role_names" ], "properties": { "role_names": { "type": "array", "items": { "type": "string" }, "example": [ "readonly" ] } }, "type": "object" }, { "required": [ "role_ids" ], "properties": { "role_ids": { "type": "array", "items": { "type": "integer" }, "example": [ 2 ] } }, "type": "object" } ] }, "UserRoleSyncRequest": { "description": "사용자의 역할을 전달된 목록으로 완전히 교체. role_names 또는 role_ids 중 하나 사용.", "type": "object", "oneOf": [ { "required": [ "role_names" ], "properties": { "role_names": { "type": "array", "items": { "type": "string" }, "example": [ "menu-manager" ] } }, "type": "object" }, { "required": [ "role_ids" ], "properties": { "role_ids": { "type": "array", "items": { "type": "integer" }, "example": [ 1 ] } }, "type": "object" } ] }, "Withdrawal": { "description": "출금 정보", "properties": { "id": { "description": "출금 ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "withdrawal_date": { "description": "출금일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1, "nullable": true }, "client_name": { "description": "비회원 거래처명", "type": "string", "example": "홍길동", "nullable": true }, "bank_account_id": { "description": "출금 계좌 ID", "type": "integer", "example": 1, "nullable": true }, "amount": { "description": "금액", "type": "number", "format": "float", "example": 500000 }, "payment_method": { "description": "결제수단", "type": "string", "enum": [ "cash", "transfer", "card", "check" ], "example": "transfer" }, "account_code": { "description": "계정과목", "type": "string", "example": "501", "nullable": true }, "description": { "description": "적요", "type": "string", "example": "사무용품 구매", "nullable": true }, "reference_type": { "description": "참조 유형", "type": "string", "example": "purchase", "nullable": true }, "reference_id": { "description": "참조 ID", "type": "integer", "example": 1, "nullable": true }, "client": { "description": "거래처 정보", "properties": { "id": { "type": "integer", "example": 1 }, "name": { "type": "string", "example": "(주)테스트" } }, "type": "object", "nullable": true }, "bank_account": { "description": "계좌 정보", "properties": { "id": { "type": "integer", "example": 1 }, "bank_name": { "type": "string", "example": "국민은행" }, "account_name": { "type": "string", "example": "법인통장" } }, "type": "object", "nullable": true }, "created_by": { "description": "생성자 ID", "type": "integer", "example": 1, "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "WithdrawalCreateRequest": { "description": "출금 등록 요청", "required": [ "withdrawal_date", "amount", "payment_method" ], "properties": { "withdrawal_date": { "description": "출금일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1, "nullable": true }, "client_name": { "description": "비회원 거래처명", "type": "string", "maxLength": 100, "example": "홍길동", "nullable": true }, "bank_account_id": { "description": "출금 계좌 ID", "type": "integer", "example": 1, "nullable": true }, "amount": { "description": "금액", "type": "number", "format": "float", "example": 500000 }, "payment_method": { "description": "결제수단", "type": "string", "enum": [ "cash", "transfer", "card", "check" ], "example": "transfer" }, "account_code": { "description": "계정과목", "type": "string", "maxLength": 20, "example": "501", "nullable": true }, "description": { "description": "적요", "type": "string", "maxLength": 1000, "example": "사무용품 구매", "nullable": true }, "reference_type": { "description": "참조 유형", "type": "string", "maxLength": 50, "example": "purchase", "nullable": true }, "reference_id": { "description": "참조 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "WithdrawalUpdateRequest": { "description": "출금 수정 요청", "properties": { "withdrawal_date": { "description": "출금일", "type": "string", "format": "date", "example": "2025-01-15" }, "client_id": { "description": "거래처 ID", "type": "integer", "example": 1, "nullable": true }, "client_name": { "description": "비회원 거래처명", "type": "string", "maxLength": 100, "example": "홍길동", "nullable": true }, "bank_account_id": { "description": "출금 계좌 ID", "type": "integer", "example": 1, "nullable": true }, "amount": { "description": "금액", "type": "number", "format": "float", "example": 500000 }, "payment_method": { "description": "결제수단", "type": "string", "enum": [ "cash", "transfer", "card", "check" ], "example": "transfer" }, "account_code": { "description": "계정과목", "type": "string", "maxLength": 20, "example": "501", "nullable": true }, "description": { "description": "적요", "type": "string", "maxLength": 1000, "example": "사무용품 구매", "nullable": true }, "reference_type": { "description": "참조 유형", "type": "string", "maxLength": 50, "example": "purchase", "nullable": true }, "reference_id": { "description": "참조 ID", "type": "integer", "example": 1, "nullable": true } }, "type": "object" }, "WithdrawalSummary": { "description": "출금 요약", "properties": { "total_amount": { "description": "총 출금액", "type": "number", "format": "float", "example": 3000000 }, "total_count": { "description": "총 건수", "type": "integer", "example": 15 }, "by_payment_method": { "description": "결제수단별 합계", "properties": { "cash": { "properties": { "total": { "type": "number", "example": 500000 }, "count": { "type": "integer", "example": 5 } }, "type": "object" }, "transfer": { "properties": { "total": { "type": "number", "example": 2500000 }, "count": { "type": "integer", "example": 10 } }, "type": "object" } }, "type": "object" } }, "type": "object" }, "WorkSetting": { "description": "근무 설정 정보", "properties": { "id": { "description": "ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "work_type": { "description": "근무유형", "type": "string", "enum": [ "fixed", "flexible", "custom" ], "example": "fixed" }, "standard_hours": { "description": "주당 소정근로시간", "type": "integer", "example": 40 }, "overtime_hours": { "description": "주당 연장근로시간", "type": "integer", "example": 12 }, "overtime_limit": { "description": "연장근로한도", "type": "integer", "example": 52 }, "work_days": { "description": "근무요일", "type": "array", "items": { "type": "string" }, "example": [ "mon", "tue", "wed", "thu", "fri" ] }, "start_time": { "description": "출근시간", "type": "string", "format": "time", "example": "09:00:00" }, "end_time": { "description": "퇴근시간", "type": "string", "format": "time", "example": "18:00:00" }, "break_minutes": { "description": "휴게시간(분)", "type": "integer", "example": 60 }, "break_start": { "description": "휴게시작", "type": "string", "format": "time", "example": "12:00:00", "nullable": true }, "break_end": { "description": "휴게종료", "type": "string", "format": "time", "example": "13:00:00", "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "WorkSettingUpdateRequest": { "description": "근무 설정 수정 요청", "properties": { "work_type": { "description": "근무유형", "type": "string", "enum": [ "fixed", "flexible", "custom" ], "example": "fixed" }, "standard_hours": { "description": "주당 소정근로시간", "type": "integer", "maximum": 168, "minimum": 1, "example": 40 }, "overtime_hours": { "description": "주당 연장근로시간", "type": "integer", "maximum": 52, "minimum": 0, "example": 12 }, "overtime_limit": { "description": "연장근로한도", "type": "integer", "maximum": 100, "minimum": 0, "example": 52 }, "work_days": { "description": "근무요일", "type": "array", "items": { "type": "string", "enum": [ "mon", "tue", "wed", "thu", "fri", "sat", "sun" ] } }, "start_time": { "description": "출근시간", "type": "string", "format": "time", "example": "09:00:00" }, "end_time": { "description": "퇴근시간", "type": "string", "format": "time", "example": "18:00:00" }, "break_minutes": { "description": "휴게시간(분)", "type": "integer", "maximum": 180, "minimum": 0, "example": 60 }, "break_start": { "description": "휴게시작", "type": "string", "format": "time", "example": "12:00:00" }, "break_end": { "description": "휴게종료", "type": "string", "format": "time", "example": "13:00:00" } }, "type": "object" }, "AttendanceSetting": { "description": "출퇴근 설정 정보", "properties": { "id": { "description": "ID", "type": "integer", "example": 1 }, "tenant_id": { "description": "테넌트 ID", "type": "integer", "example": 1 }, "use_gps": { "description": "GPS 출퇴근 사용 여부", "type": "boolean", "example": true }, "allowed_radius": { "description": "허용 반경(m)", "type": "integer", "example": 100 }, "hq_address": { "description": "본사 주소", "type": "string", "example": "서울시 강남구 테헤란로 123", "nullable": true }, "hq_latitude": { "description": "본사 위도", "type": "number", "format": "float", "example": 37.5012, "nullable": true }, "hq_longitude": { "description": "본사 경도", "type": "number", "format": "float", "example": 127.0396, "nullable": true }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" } }, "type": "object" }, "AttendanceSettingUpdateRequest": { "description": "출퇴근 설정 수정 요청", "properties": { "use_gps": { "description": "GPS 출퇴근 사용 여부", "type": "boolean", "example": true }, "allowed_radius": { "description": "허용 반경(m)", "type": "integer", "maximum": 10000, "minimum": 10, "example": 100 }, "hq_address": { "description": "본사 주소", "type": "string", "example": "서울시 강남구 테헤란로 123" }, "hq_latitude": { "description": "본사 위도", "type": "number", "format": "float", "maximum": 90, "minimum": -90, "example": 37.5012 }, "hq_longitude": { "description": "본사 경도", "type": "number", "format": "float", "maximum": 180, "minimum": -180, "example": 127.0396 } }, "type": "object" } }, "parameters": { "Page": { "name": "page", "in": "query", "description": "페이지 번호(1부터)", "required": false, "schema": { "type": "integer", "minimum": 1, "example": 1 } }, "Size": { "name": "size", "in": "query", "description": "페이지 당 개수(기본 20)", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "example": 20 } } }, "securitySchemes": { "ApiKeyAuth": { "type": "apiKey", "in": "header", "name": "X-API-KEY", "description": "API Key 인증: X-API-KEY: {API_KEY}" }, "BearerAuth": { "type": "http", "bearerFormat": "JWT", "scheme": "bearer" } } }, "tags": [ { "name": "Settings - Common Codes", "description": "공통 코드 관리 API" }, { "name": "Estimate", "description": "견적 관리 API" }, { "name": "Settings - Fields", "description": "테넌트 필드 설정 관리 API" }, { "name": "Admin-Users", "description": "관리자 사용자 관리 API" }, { "name": "Approvals", "description": "전자결재 문서 관리" }, { "name": "Approval Forms", "description": "결재 양식 관리" }, { "name": "Approval Lines", "description": "결재선 템플릿 관리" }, { "name": "Attendances", "description": "근태 관리 (HR)" }, { "name": "Design Audit", "description": "Design-time audit logs" }, { "name": "BankAccounts", "description": "계좌 관리" }, { "name": "Board", "description": "게시판 관리" }, { "name": "BOM Calculation", "description": "BOM 계산 시스템" }, { "name": "Cards", "description": "카드 관리" }, { "name": "Category", "description": "카테고리 관리" }, { "name": "Classification", "description": "분류 관리 (평면 구조 / 코드 테이블)" }, { "name": "Client", "description": "거래처 관리" }, { "name": "ClientGroup", "description": "고객 그룹 관리" }, { "name": "Deposits", "description": "입금 관리" }, { "name": "Design BOM", "description": "Design-time BOM template operations" }, { "name": "Employees", "description": "사원 관리 (HR)" }, { "name": "ItemMaster-Relationships", "description": "품목기준관리 - 엔티티 관계 API" }, { "name": "Tenant.Fields", "description": "테넌트별 필드 구동(효과값 조회/설정)" }, { "name": "Tenant.Option Groups", "description": "테넌트 관리형 옵션 그룹" }, { "name": "Tenant.Option Values", "description": "옵션 그룹의 항목(값) 관리" }, { "name": "Tenant.Profiles", "description": "테넌트별 회원 프로필 조회/수정" }, { "name": "Files", "description": "파일 저장소 관리" }, { "name": "Folder", "description": "폴더 관리" }, { "name": "ItemMaster", "description": "품목기준관리 API" }, { "name": "Items", "description": "품목 관리 (Product + Material CRUD)" }, { "name": "Items BOM", "description": "품목 BOM 관리 (Code 기반)" }, { "name": "Items Files", "description": "품목 파일 관리 API - group_id 기반, field_key 동적 지원" }, { "name": "Leaves", "description": "휴가 관리 (HR)" }, { "name": "Post", "description": "게시글 관리" }, { "name": "Pricing", "description": "단가 관리" }, { "name": "Purchases", "description": "매입 관리" }, { "name": "Quote", "description": "견적 관리" }, { "name": "Reports", "description": "보고서 관리" }, { "name": "Auth", "description": "로그인/로그아웃 및 인증 관련 API\n *\n * **인증 흐름 (Authentication Flow)**\n * 1. 모든 API 요청은 반드시 X-API-KEY 헤더가 필요합니다 (API Key 인증)\n * 2. 사용자 인증이 필요한 API는 추가로 Bearer 토큰이 필요합니다 (JWT 인증)\n *\n * **API Key 사용 예시:**\n * ```\n * X-API-KEY: your-api-key-here\n * ```\n *\n * **Bearer Token 사용 예시:**\n * ```\n * Authorization: Bearer 1|abc123xyz456\n * ```\n *\n * **IP 기반 접근:**\n * - API Key가 없는 경우, IP 주소로 접근 제어가 가능합니다\n * - 단, 운영 환경에서는 반드시 API Key 사용을 권장합니다" }, { "name": "User", "description": "사용자 자기 계정 관련 API" }, { "name": "Sales", "description": "매출 관리" }, { "name": "Sites", "description": "현장 관리" }, { "name": "TenantStatField", "description": "통계 필드 메타데이터 관리" }, { "name": "Withdrawals", "description": "출금 관리" }, { "name": "WorkSettings", "description": "근무/출퇴근 설정" }, { "name": "Category-Fields", "description": "Category-Fields" }, { "name": "Category-Templates", "description": "Category-Templates" }, { "name": "Category-Logs", "description": "Category-Logs" }, { "name": "Department", "description": "Department" }, { "name": "Model", "description": "Model" }, { "name": "ModelVersion", "description": "ModelVersion" }, { "name": "BomTemplate", "description": "BomTemplate" }, { "name": "Menu", "description": "Menu" }, { "name": "Permission", "description": "Permission" }, { "name": "Role", "description": "Role" }, { "name": "RolePermission", "description": "RolePermission" }, { "name": "Tenant", "description": "Tenant" }, { "name": "UserRole", "description": "UserRole" } ] }