Files
sam-docs/sam/docs/features/approvals/api-reference.md
김보곤 490477421d docs: [approvals] 결재관리 시스템 문서 4종 작성
- README.md: 시스템 개요, 아키텍처, DB 스키마, 상태 관리, 권한 매트릭스
- workflows.md: 워크플로우 상세 (승인/반려/회수/보류/전결/복사재기안)
- api-reference.md: API 엔드포인트 20개 명세
- ui-screens.md: UI 화면 구성 및 인터랙션
- INDEX.md에 결재관리 문서 등록
2026-02-28 00:09:08 +09:00

595 lines
11 KiB
Markdown

# 결재관리 API 명세
> **작성일**: 2026-02-28
> **상태**: Phase 2 구현 완료
> **Base URL**: `/api/admin/approvals`
> **미들웨어**: `web`, `auth`, `hq.member`
> **관련**: [README.md](README.md) | [워크플로우](workflows.md) | [UI 화면](ui-screens.md)
---
## 1. 개요
모든 API는 JSON 응답을 반환한다. 인증은 세션 기반이며, CSRF 토큰이 필요하다.
### 1.1 공통 응답 형식
**성공:**
```json
{
"success": true,
"message": "처리 메시지",
"data": { ... }
}
```
**실패 (400):**
```json
{
"success": false,
"message": "에러 메시지"
}
```
### 1.2 공통 헤더
```
Content-Type: application/json
Accept: application/json
X-CSRF-TOKEN: {csrf_token}
```
---
## 2. 목록 조회 API
### 2.1 기안함
내가 기안한 문서 목록을 조회한다.
```
GET /api/admin/approvals/drafts
```
**Query Parameters:**
| 파라미터 | 타입 | 설명 |
|---------|------|------|
| `search` | string | 제목/문서번호 검색 |
| `status` | string | 상태 필터 (`draft`, `pending`, `approved`, `rejected`, `cancelled`, `on_hold`) |
| `is_urgent` | boolean | 긴급 문서만 |
| `date_from` | date | 시작일 (YYYY-MM-DD) |
| `date_to` | date | 종료일 (YYYY-MM-DD) |
| `per_page` | int | 페이지당 건수 (기본 15) |
| `page` | int | 페이지 번호 |
**응답:** Laravel 페이지네이션 형식
```json
{
"data": [
{
"id": 1,
"document_number": "APR-260228-001",
"title": "휴가 신청",
"status": "pending",
"is_urgent": false,
"form": { "id": 1, "name": "휴가신청서" },
"steps": [...],
"created_at": "2026-02-28T10:00:00",
"drafted_at": "2026-02-28T10:05:00"
}
],
"current_page": 1,
"last_page": 3,
"per_page": 15,
"total": 42
}
```
---
### 2.2 결재 대기함
내가 현재 결재해야 할 문서 목록을 조회한다.
```
GET /api/admin/approvals/pending
```
**Query Parameters:**
| 파라미터 | 타입 | 설명 |
|---------|------|------|
| `search` | string | 제목/문서번호 검색 |
| `is_urgent` | boolean | 긴급 문서만 |
| `date_from` | date | 시작일 |
| `date_to` | date | 종료일 |
| `per_page` | int | 페이지당 건수 |
> 현재 사용자가 결재 차례인 문서만 표시된다. 이미 승인/반려한 문서는 표시되지 않는다.
---
### 2.3 처리 완료함
내가 승인 또는 반려한 문서 목록을 조회한다.
```
GET /api/admin/approvals/completed
```
**Query Parameters:**
| 파라미터 | 타입 | 설명 |
|---------|------|------|
| `search` | string | 제목/문서번호 검색 |
| `status` | string | 상태 필터 |
| `date_from` | date | 시작일 |
| `date_to` | date | 종료일 |
| `per_page` | int | 페이지당 건수 |
---
### 2.4 참조함
내가 참조자로 지정된 문서 목록을 조회한다.
```
GET /api/admin/approvals/references
```
**Query Parameters:**
| 파라미터 | 타입 | 설명 |
|---------|------|------|
| `search` | string | 제목/문서번호 검색 |
| `is_read` | string | 열람 상태 필터 (`true`=열람완료, `false`=미열람) |
| `date_from` | date | 시작일 |
| `date_to` | date | 종료일 |
| `per_page` | int | 페이지당 건수 |
---
## 3. CRUD API
### 3.1 상세 조회
```
GET /api/admin/approvals/{id}
```
**응답:**
```json
{
"success": true,
"data": {
"id": 1,
"tenant_id": 1,
"document_number": "APR-260228-001",
"form_id": 1,
"line_id": null,
"title": "휴가 신청",
"content": {},
"body": "2월 27일~28일 연차 사용 신청합니다.",
"status": "pending",
"is_urgent": false,
"drafter_id": 10,
"department_id": 3,
"current_step": 2,
"drafted_at": "2026-02-28T10:05:00",
"completed_at": null,
"recall_reason": null,
"parent_doc_id": null,
"form": { "id": 1, "name": "휴가신청서" },
"drafter": { "id": 10, "name": "홍길동" },
"line": null,
"steps": [
{
"id": 1,
"step_order": 1,
"step_type": "approval",
"approver_id": 20,
"approver_name": "김과장",
"approver_department": "경영지원팀",
"approver_position": "과장",
"status": "approved",
"approval_type": "normal",
"comment": "승인합니다.",
"acted_at": "2026-02-28T11:00:00",
"is_read": false,
"read_at": null
},
{
"id": 2,
"step_order": 2,
"step_type": "approval",
"approver_id": 30,
"approver_name": "박부장",
"approver_department": "경영지원팀",
"approver_position": "부장",
"status": "pending",
"approval_type": "normal",
"comment": null,
"acted_at": null,
"is_read": false,
"read_at": null
}
]
}
}
```
---
### 3.2 생성 (임시저장)
```
POST /api/admin/approvals
```
**Request Body:**
```json
{
"form_id": 1,
"title": "휴가 신청",
"body": "2월 27일~28일 연차 사용",
"is_urgent": false,
"steps": [
{ "user_id": 20, "step_type": "approval" },
{ "user_id": 30, "step_type": "approval" },
{ "user_id": 40, "step_type": "reference" }
]
}
```
**Validation:**
| 필드 | 규칙 |
|------|------|
| `form_id` | required, exists:approval_forms,id |
| `title` | required, string, max:200 |
| `body` | nullable, string |
| `is_urgent` | boolean |
| `steps` | nullable, array |
| `steps.*.user_id` | required_with:steps, exists:users,id |
| `steps.*.step_type` | required_with:steps, in:approval,agreement,reference |
**응답 (201):**
```json
{
"success": true,
"message": "결재 문서가 저장되었습니다.",
"data": { ... }
}
```
---
### 3.3 수정
```
PUT /api/admin/approvals/{id}
```
> `draft` 또는 `rejected` 상태에서만 수정 가능
**Request Body:** (생성과 동일, 모든 필드 선택)
**Validation:**
| 필드 | 규칙 |
|------|------|
| `title` | sometimes, string, max:200 |
| `body` | nullable, string |
| `is_urgent` | boolean |
| `steps` | nullable, array |
---
### 3.4 삭제
```
DELETE /api/admin/approvals/{id}
```
> `draft` 상태에서만 삭제 가능
**응답:**
```json
{
"success": true,
"message": "결재 문서가 삭제되었습니다."
}
```
---
## 4. 워크플로우 API
### 4.1 상신
```
POST /api/admin/approvals/{id}/submit
```
> 기안자가 `draft`/`rejected` 문서를 결재 요청한다.
**Request Body:** 없음
**응답:** `{ "success": true, "message": "결재가 상신되었습니다.", "data": {...} }`
---
### 4.2 승인
```
POST /api/admin/approvals/{id}/approve
```
> 현재 결재자가 승인한다.
**Request Body:**
```json
{
"comment": "승인합니다." // 선택
}
```
**응답:** `{ "success": true, "message": "승인되었습니다.", "data": {...} }`
---
### 4.3 반려
```
POST /api/admin/approvals/{id}/reject
```
> 현재 결재자가 반려한다. 사유 필수.
**Request Body:**
```json
{
"comment": "예산 초과로 반려합니다." // 필수
}
```
**Validation:** `comment` — required, string, max:1000
**응답:** `{ "success": true, "message": "반려되었습니다.", "data": {...} }`
---
### 4.4 회수
```
POST /api/admin/approvals/{id}/cancel
```
> 기안자가 `pending`/`on_hold` 문서를 회수한다. 첫 결재자 미처리 시에만 가능.
**Request Body:**
```json
{
"recall_reason": "내용 수정 필요" // 선택
}
```
**응답:** `{ "success": true, "message": "결재가 회수되었습니다.", "data": {...} }`
---
### 4.5 보류
```
POST /api/admin/approvals/{id}/hold
```
> 현재 결재자가 결재를 보류한다. 사유 필수.
**Request Body:**
```json
{
"comment": "추가 자료 검토 필요" // 필수
}
```
**Validation:** `comment` — required, string, max:1000
**응답:** `{ "success": true, "message": "보류되었습니다.", "data": {...} }`
---
### 4.6 보류 해제
```
POST /api/admin/approvals/{id}/release-hold
```
> 보류한 결재자가 보류를 해제한다.
**Request Body:** 없음
**응답:** `{ "success": true, "message": "보류가 해제되었습니다.", "data": {...} }`
---
### 4.7 전결
```
POST /api/admin/approvals/{id}/pre-decide
```
> 현재 결재자가 이후 모든 결재를 건너뛰고 최종 승인한다.
**Request Body:**
```json
{
"comment": "전결 처리합니다." // 선택
}
```
**응답:** `{ "success": true, "message": "전결 처리되었습니다.", "data": {...} }`
---
### 4.8 복사 재기안
```
POST /api/admin/approvals/{id}/copy
```
> 기안자가 `approved`/`rejected`/`cancelled` 문서를 복사하여 새 draft를 생성한다.
**Request Body:** 없음
**응답:**
```json
{
"success": true,
"message": "문서가 복사되었습니다.",
"data": {
"id": 15,
"document_number": "APR-260228-003",
"parent_doc_id": 1,
"status": "draft",
...
}
}
```
> 응답의 `data.id`를 사용하여 `/approval-mgmt/{id}/edit`로 이동한다.
---
### 4.9 참조 열람 추적
```
POST /api/admin/approvals/{id}/mark-read
```
> 참조자가 문서를 열람했음을 기록한다.
**Request Body:** 없음
**응답:** `{ "success": true, "message": "열람 처리되었습니다." }`
---
## 5. 유틸리티 API
### 5.1 결재선 템플릿 목록
```
GET /api/admin/approvals/lines
```
**응답:**
```json
{
"success": true,
"data": [
{ "id": 1, "name": "일반 결재선", "steps": [...] }
]
}
```
---
### 5.2 양식 목록
```
GET /api/admin/approvals/forms
```
**응답:**
```json
{
"success": true,
"data": [
{ "id": 1, "name": "휴가신청서", "is_active": true }
]
}
```
---
### 5.3 미처리 건수 (뱃지)
```
GET /api/admin/approvals/badge-counts
```
**응답:**
```json
{
"success": true,
"data": {
"pending": 3,
"draft": 1,
"reference_unread": 5
}
}
```
| 필드 | 설명 |
|------|------|
| `pending` | 내가 결재해야 할 문서 수 |
| `draft` | 내 임시저장 문서 수 |
| `reference_unread` | 미열람 참조 문서 수 |
---
## 6. 라우트 전체 목록
| Method | Path | 컨트롤러 메서드 | 이름 | 설명 |
|--------|------|---------------|------|------|
| GET | `/drafts` | `drafts` | `drafts` | 기안함 |
| GET | `/pending` | `pending` | `pending` | 결재 대기함 |
| GET | `/completed` | `completed` | `completed` | 처리 완료함 |
| GET | `/references` | `references` | `references` | 참조함 |
| GET | `/lines` | `lines` | `lines` | 결재선 템플릿 |
| GET | `/forms` | `forms` | `forms` | 양식 목록 |
| GET | `/badge-counts` | `badgeCounts` | `badge-counts` | 뱃지 건수 |
| POST | `/` | `store` | `store` | 생성 |
| GET | `/{id}` | `show` | `show` | 상세 |
| PUT | `/{id}` | `update` | `update` | 수정 |
| DELETE | `/{id}` | `destroy` | `destroy` | 삭제 |
| POST | `/{id}/submit` | `submit` | `submit` | 상신 |
| POST | `/{id}/approve` | `approve` | `approve` | 승인 |
| POST | `/{id}/reject` | `reject` | `reject` | 반려 |
| POST | `/{id}/cancel` | `cancel` | `cancel` | 회수 |
| POST | `/{id}/hold` | `hold` | `hold` | 보류 |
| POST | `/{id}/release-hold` | `releaseHold` | `release-hold` | 보류 해제 |
| POST | `/{id}/pre-decide` | `preDecide` | `pre-decide` | 전결 |
| POST | `/{id}/copy` | `copyForRedraft` | `copy` | 복사 재기안 |
| POST | `/{id}/mark-read` | `markAsRead` | `mark-read` | 열람 추적 |
---
## 관련 문서
- [README.md](README.md) — 시스템 전체 개요
- [워크플로우 상세](workflows.md) — 각 동작의 상세 흐름
- [UI 화면 구성](ui-screens.md) — 화면별 동작
---
**최종 업데이트**: 2026-02-28