feat: [org-chart] 조직도 관리 API 이관 (8개 엔드포인트)

- OrgChartController + OrgChartService 신규 생성
- FormRequest 5개 (Assign/Unassign/ReorderEmployees/ReorderDepartments/ToggleHide)
- Department 모델 options cast 추가
- Swagger 문서 (OrgChartApi.php) 생성
- hr.php 라우트 그룹 추가 (/v1/org-chart)
This commit is contained in:
김보곤
2026-03-22 17:22:12 +09:00
parent d502c9b85d
commit 902f681f6e
11 changed files with 1588 additions and 24 deletions

View File

@@ -11,7 +11,7 @@
"servers": [
{
"url": "https://api.sam.kr/",
"description": "SAM API 서버"
"description": "SAM관리시스템 API 서버"
}
],
"paths": {
@@ -9577,9 +9577,15 @@
],
"properties": {
"code": {
"description": "LOT 코드",
"description": "코드 체계 (prod+spec)",
"type": "string",
"example": "RM260319"
"example": "RM"
},
"lot_no": {
"description": "LOT 번호",
"type": "string",
"example": "RM260319",
"nullable": true
},
"item_name": {
"type": "string",
@@ -36518,6 +36524,502 @@
]
}
},
"/api/v1/org-chart": {
"get": {
"tags": [
"OrgChart"
],
"summary": "조직도 전체 조회 (부서 트리 + 직원 + 통계)",
"operationId": "d92f1fc2da2664ef3543e4e1328d25e9",
"parameters": [
{
"name": "include_hidden",
"in": "query",
"description": "숨겨진 부서 포함 여부 (기본: true)",
"schema": {
"type": "boolean"
}
}
],
"responses": {
"200": {
"description": "성공",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "boolean",
"example": true
},
"message": {
"type": "string"
},
"data": {
"properties": {
"company": {
"properties": {
"name": {
"type": "string",
"example": "주일산업"
},
"ceo_name": {
"type": "string",
"example": "홍길동"
}
},
"type": "object"
},
"departments": {
"type": "array",
"items": {
"$ref": "#/components/schemas/OrgChartDepartmentNode"
}
},
"hidden_departments": {
"type": "array",
"items": {
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"code": {
"type": "string"
}
},
"type": "object"
}
},
"unassigned": {
"type": "array",
"items": {
"$ref": "#/components/schemas/OrgChartEmployee"
}
},
"stats": {
"$ref": "#/components/schemas/OrgChartStats"
}
},
"type": "object"
}
},
"type": "object"
}
}
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"BearerAuth": []
}
]
}
},
"/api/v1/org-chart/stats": {
"get": {
"tags": [
"OrgChart"
],
"summary": "조직도 통계 (전체/배치/미배치 인원)",
"operationId": "c00470fa81707bdf862c9eec4139d0ba",
"responses": {
"200": {
"description": "성공",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "boolean",
"example": true
},
"message": {
"type": "string"
},
"data": {
"$ref": "#/components/schemas/OrgChartStats"
}
},
"type": "object"
}
}
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"BearerAuth": []
}
]
}
},
"/api/v1/org-chart/unassigned": {
"get": {
"tags": [
"OrgChart"
],
"summary": "미배치 직원 목록",
"operationId": "13121a2e9ccefcfbf7cc60c727522bc4",
"parameters": [
{
"name": "q",
"in": "query",
"description": "이름 검색",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "성공",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "boolean",
"example": true
},
"message": {
"type": "string"
},
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/OrgChartEmployee"
}
}
},
"type": "object"
}
}
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"BearerAuth": []
}
]
}
},
"/api/v1/org-chart/assign": {
"post": {
"tags": [
"OrgChart"
],
"summary": "직원 부서 배치",
"operationId": "6a7281807e859f10409469dda17fdd89",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrgChartAssignRequest"
}
}
}
},
"responses": {
"200": {
"description": "성공",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "boolean",
"example": true
},
"message": {
"type": "string"
},
"data": {
"properties": {
"employee_id": {
"type": "integer"
},
"department_id": {
"type": "integer"
}
},
"type": "object"
}
},
"type": "object"
}
}
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"BearerAuth": []
}
]
}
},
"/api/v1/org-chart/unassign": {
"post": {
"tags": [
"OrgChart"
],
"summary": "직원 미배치 처리",
"operationId": "387e1c87037f9bf708b7255c35f5e86c",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrgChartUnassignRequest"
}
}
}
},
"responses": {
"200": {
"description": "성공",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "boolean",
"example": true
},
"message": {
"type": "string"
},
"data": {
"properties": {
"employee_id": {
"type": "integer"
},
"department_id": {
"type": "integer",
"nullable": true
}
},
"type": "object"
}
},
"type": "object"
}
}
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"BearerAuth": []
}
]
}
},
"/api/v1/org-chart/reorder-employees": {
"put": {
"tags": [
"OrgChart"
],
"summary": "직원 일괄 배치/이동",
"operationId": "7af302b074864287d8f4b09af4e27c9c",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrgChartReorderEmployeesRequest"
}
}
}
},
"responses": {
"200": {
"description": "성공",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "boolean",
"example": true
},
"message": {
"type": "string"
},
"data": {
"properties": {
"processed": {
"type": "integer",
"example": 3
}
},
"type": "object"
}
},
"type": "object"
}
}
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"BearerAuth": []
}
]
}
},
"/api/v1/org-chart/reorder-departments": {
"put": {
"tags": [
"OrgChart"
],
"summary": "부서 순서/계층 일괄 변경",
"operationId": "da0aa294c8ebf3ab4f7550f56ca901f3",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrgChartReorderDepartmentsRequest"
}
}
}
},
"responses": {
"200": {
"description": "성공",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "boolean",
"example": true
},
"message": {
"type": "string"
},
"data": {
"properties": {
"processed": {
"type": "integer",
"example": 5
}
},
"type": "object"
}
},
"type": "object"
}
}
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"BearerAuth": []
}
]
}
},
"/api/v1/org-chart/departments/{id}/toggle-hide": {
"patch": {
"tags": [
"OrgChart"
],
"summary": "부서 숨기기/표시 토글",
"operationId": "b3913a80123a5bc5b8f7e4d07beed9c8",
"parameters": [
{
"name": "id",
"in": "path",
"description": "부서 ID",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrgChartToggleHideRequest"
}
}
}
},
"responses": {
"200": {
"description": "성공",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "boolean",
"example": true
},
"message": {
"type": "string"
},
"data": {
"properties": {
"id": {
"type": "integer"
},
"orgchart_hidden": {
"type": "boolean"
}
},
"type": "object"
}
},
"type": "object"
}
}
}
}
},
"security": [
{
"ApiKeyAuth": []
},
{
"BearerAuth": []
}
]
}
},
"/api/v1/payments": {
"get": {
"tags": [
@@ -49474,14 +49976,9 @@
{
"name": "delivery_method",
"in": "query",
"description": "배송방식",
"description": "배송방식 (common_codes delivery_method 참조)",
"schema": {
"type": "string",
"enum": [
"pickup",
"direct",
"logistics"
]
"type": "string"
}
},
{
@@ -64904,9 +65401,15 @@
"example": 431
},
"code": {
"description": "LOT 코드: {제품Code}{종류Code}{YYMMDD}",
"description": "코드 체계 (제품Code+종류Code)",
"type": "string",
"example": "RS260319"
"example": "RS"
},
"lot_no": {
"description": "LOT 번호 (code+날짜+일련번호)",
"type": "string",
"example": "RS260319",
"nullable": true
},
"legacy_code": {
"description": "이전 코드 (items 기반)",
@@ -80193,6 +80696,204 @@
},
"type": "object"
},
"OrgChartEmployee": {
"properties": {
"id": {
"description": "프로필 ID",
"type": "integer",
"example": 5
},
"user_id": {
"type": "integer",
"example": 3
},
"department_id": {
"type": "integer",
"example": 1,
"nullable": true
},
"display_name": {
"type": "string",
"example": "홍길동"
},
"position_label": {
"type": "string",
"example": "과장",
"nullable": true
}
},
"type": "object"
},
"OrgChartDepartmentNode": {
"properties": {
"id": {
"type": "integer",
"example": 1
},
"name": {
"type": "string",
"example": "경영지원팀"
},
"code": {
"type": "string",
"example": "MGT",
"nullable": true
},
"parent_id": {
"type": "integer",
"nullable": true
},
"sort_order": {
"type": "integer",
"example": 1
},
"is_active": {
"type": "boolean",
"example": true
},
"orgchart_hidden": {
"type": "boolean",
"example": false
},
"children": {
"type": "array",
"items": {
"$ref": "#/components/schemas/OrgChartDepartmentNode"
}
},
"employees": {
"type": "array",
"items": {
"$ref": "#/components/schemas/OrgChartEmployee"
}
}
},
"type": "object"
},
"OrgChartStats": {
"properties": {
"total": {
"type": "integer",
"example": 50
},
"assigned": {
"type": "integer",
"example": 42
},
"unassigned": {
"type": "integer",
"example": 8
}
},
"type": "object"
},
"OrgChartAssignRequest": {
"required": [
"employee_id",
"department_id"
],
"properties": {
"employee_id": {
"description": "직원 프로필 ID",
"type": "integer",
"example": 5
},
"department_id": {
"description": "배치할 부서 ID",
"type": "integer",
"example": 3
}
},
"type": "object"
},
"OrgChartUnassignRequest": {
"required": [
"employee_id"
],
"properties": {
"employee_id": {
"description": "직원 프로필 ID",
"type": "integer",
"example": 5
}
},
"type": "object"
},
"OrgChartReorderEmployeesRequest": {
"required": [
"moves"
],
"properties": {
"moves": {
"type": "array",
"items": {
"required": [
"employee_id"
],
"properties": {
"employee_id": {
"type": "integer",
"example": 5
},
"department_id": {
"type": "integer",
"example": 3,
"nullable": true
}
},
"type": "object"
}
}
},
"type": "object"
},
"OrgChartReorderDepartmentsRequest": {
"required": [
"orders"
],
"properties": {
"orders": {
"type": "array",
"items": {
"required": [
"id",
"parent_id",
"sort_order"
],
"properties": {
"id": {
"type": "integer",
"example": 1
},
"parent_id": {
"type": "integer",
"example": null,
"nullable": true
},
"sort_order": {
"type": "integer",
"example": 0
}
},
"type": "object"
}
}
},
"type": "object"
},
"OrgChartToggleHideRequest": {
"required": [
"hidden"
],
"properties": {
"hidden": {
"description": "숨기기 여부",
"type": "boolean",
"example": true
}
},
"type": "object"
},
"Payment": {
"description": "결제 정보",
"properties": {
@@ -87955,13 +88656,8 @@
"example": "보통"
},
"delivery_method": {
"description": "배송방식",
"description": "배송방식 (common_codes delivery_method 참조)",
"type": "string",
"enum": [
"pickup",
"direct",
"logistics"
],
"example": "pickup"
},
"delivery_method_label": {
@@ -88371,13 +89067,8 @@
"example": "normal"
},
"delivery_method": {
"description": "배송방식",
"description": "배송방식 (common_codes delivery_method 참조)",
"type": "string",
"enum": [
"pickup",
"direct",
"logistics"
],
"example": "pickup"
},
"client_id": {
@@ -95014,6 +95705,10 @@
"name": "Order",
"description": "수주관리 API"
},
{
"name": "OrgChart",
"description": "조직도 관리"
},
{
"name": "Payments",
"description": "결제 관리"