Files
sam-docs/frontend/api-specs/approval-api.md
김보곤 5493788800 docs: [approval] 결재관리 API 프론트엔드 연동 명세서 추가
- 28개 엔드포인트 전체 명세 (요청/응답 포맷 포함)
- 상태 흐름도, 탭 구성, 버튼 조건 등 UI 가이드
- INDEX.md에 frontend/api-specs/ 섹션 등록
2026-03-11 17:40:53 +09:00

701 lines
17 KiB
Markdown

# 결재관리 API 명세
> **작성일**: 2026-03-11
> **상태**: 개발 완료 (API 배포됨)
> **Base URL**: `api.codebridge-x.com` (운영) / `api.dev.codebridge-x.com` (개발)
---
## 1. 개요
결재관리 시스템의 전체 API 명세. 기안, 결재, 참조, 위임, 완료함 등 모든 결재 워크플로우를 지원한다.
### 1.1 인증
모든 요청에 다음 헤더가 필요하다:
```
X-API-KEY: {api_key}
Authorization: Bearer {token}
```
### 1.2 공통 응답 형식
```json
{
"success": true,
"message": "조회되었습니다.",
"data": { ... }
}
```
에러 시:
```json
{
"success": false,
"message": "에러 메시지"
}
```
---
## 2. 상태 흐름도
```
┌──────────┐
│ draft │ 임시저장
└────┬─────┘
│ submit (상신)
┌──────────┐
┌────►│ pending │ 결재 진행중
│ └──┬─┬─┬──┘
│ │ │ │
release- │ hold │ │ │ approve (각 단계)
hold │ ▼ │ │ │
│ ┌──────┐│ │ │
└─┤on_hold││ │ │ 보류
└──────┘│ │ │
│ │ │
┌───────────────┘ │ └──────────────┐
│ cancel (회수) │ │ reject (반려)
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│cancelled │ │ approved │ │ rejected │
└──────────┘ └──────────┘ └──────────┘
│ submit (재상신)
┌──────────┐
│ pending │
└──────────┘
```
### 2.1 상태값
| 상태 | 값 | 설명 | UI 배지 색상 |
|------|---|------|-------------|
| 임시저장 | `draft` | 작성 중, 아직 미상신 | gray |
| 진행중 | `pending` | 결재 진행 중 | blue |
| 승인 | `approved` | 최종 승인 완료 | green |
| 반려 | `rejected` | 결재자가 반려 | red |
| 회수 | `cancelled` | 기안자가 회수 | yellow |
| 보류 | `on_hold` | 결재자가 보류 | orange |
### 2.2 결재 단계 유형
| 유형 | 값 | 설명 |
|------|---|------|
| 결재 | `approval` | 승인/반려 권한 |
| 합의 | `agreement` | 승인/반려 권한 (다른 부서) |
| 참조 | `reference` | 열람만 가능 |
### 2.3 결재 단계 상태
| 상태 | 값 | 설명 |
|------|---|------|
| 대기 | `pending` | 아직 미처리 |
| 승인 | `approved` | 승인함 |
| 반려 | `rejected` | 반려함 |
| 건너뜀 | `skipped` | 전결/회수로 건너뜀 |
| 보류 | `on_hold` | 보류 중 |
---
## 3. 목록 API (탭별)
### 3.1 기안함 (내가 기안한 문서)
```
GET /api/v1/approvals/drafts
```
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|:----:|------|
| `status` | string | - | `draft`, `pending`, `approved`, `rejected`, `cancelled`, `on_hold` |
| `search` | string | - | 제목/문서번호 검색 |
| `sort_by` | string | - | `created_at`(기본), `drafted_at`, `completed_at`, `title`, `status` |
| `sort_dir` | string | - | `asc`, `desc`(기본) |
| `per_page` | int | - | 페이지당 건수 (기본 20) |
| `page` | int | - | 페이지 번호 |
**응답 데이터** (페이지네이션):
```json
{
"data": [
{
"id": 1,
"document_number": "APR-20260311-0001",
"title": "출장 품의서",
"status": "pending",
"is_urgent": false,
"drafted_at": "2026-03-11 10:00:00",
"completed_at": null,
"created_at": "2026-03-11",
"form": {
"id": 1,
"name": "품의서",
"code": "request",
"category": "request"
},
"drafter": {
"id": 10,
"name": "홍길동",
"tenant_profile": {
"department": { "id": 3, "name": "영업부" },
"position_key": "manager"
}
},
"steps": [
{
"id": 1,
"step_order": 1,
"step_type": "approval",
"status": "approved",
"approver_name": "김팀장",
"approver_department": "영업부",
"approver_position": "팀장",
"comment": null,
"acted_at": "2026-03-11 11:00:00",
"approver": {
"id": 5,
"name": "김팀장"
}
},
{
"id": 2,
"step_order": 2,
"step_type": "approval",
"status": "pending",
"approver_name": "박부장",
"approver_department": "영업부",
"approver_position": "부장",
"approver": {
"id": 8,
"name": "박부장"
}
}
]
}
],
"current_page": 1,
"last_page": 3,
"per_page": 20,
"total": 52
}
```
---
### 3.2 기안함 현황 카드
```
GET /api/v1/approvals/drafts/summary
```
파라미터 없음.
```json
{
"total": 52,
"draft": 3,
"pending": 12,
"approved": 30,
"rejected": 7
}
```
---
### 3.3 결재함 (내가 결재할 문서)
```
GET /api/v1/approvals/inbox
```
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|:----:|------|
| `status` | string | - | `requested`(내 차례), `scheduled`(예정), `completed`(처리완료), `rejected`(내가 반려) |
| `sort_by` | string | - | `created_at`(기본), `drafted_at`, `completed_at`, `title` |
| `sort_dir` | string | - | `asc`, `desc`(기본) |
| `start_date` | string | - | `YYYY-MM-DD` 시작일 |
| `end_date` | string | - | `YYYY-MM-DD` 종료일 |
| `per_page` | int | - | 페이지당 건수 |
| `page` | int | - | 페이지 번호 |
> **`requested`**: 현재 내가 처리해야 할 문서 (내 차례)
> **`scheduled`**: 아직 내 차례가 아닌 문서 (앞 결재자가 미처리)
---
### 3.4 결재함 현황 카드
```
GET /api/v1/approvals/inbox/summary
```
```json
{
"requested": 5,
"scheduled": 3,
"completed": 20,
"rejected": 2
}
```
---
### 3.5 참조함 (내가 참조된 문서)
```
GET /api/v1/approvals/reference
```
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|:----:|------|
| `is_read` | boolean | - | `true`(읽음), `false`(안읽음) |
| `sort_by` | string | - | `created_at`(기본), `drafted_at`, `completed_at`, `title` |
| `sort_dir` | string | - | `asc`, `desc`(기본) |
| `per_page` | int | - | 페이지당 건수 |
| `page` | int | - | 페이지 번호 |
---
### 3.6 완료함 (내 기안 완료 + 내가 처리한 문서)
```
GET /api/v1/approvals/completed
```
IndexRequest와 동일한 파라미터 사용.
---
### 3.7 완료함 현황 카드
```
GET /api/v1/approvals/completed/summary
```
```json
{
"approved": 25,
"rejected": 5,
"cancelled": 2,
"unread": 3
}
```
---
### 3.8 뱃지 카운트 (사이드바/GNB용)
```
GET /api/v1/approvals/badge-counts
```
```json
{
"pending": 5,
"draft": 2,
"reference_unread": 3,
"completed_unread": 1
}
```
> **UI 활용**: 사이드바 메뉴 옆에 `pending` 뱃지, 참조 탭에 `reference_unread` 뱃지 등
---
## 4. 문서 CRUD
### 4.1 문서 상세
```
GET /api/v1/approvals/{id}
```
상세 응답에는 `form.template` (양식 필드 정의), 전체 `steps` 목록, 연결된 `linkable` 문서 데이터가 포함된다.
---
### 4.2 문서 생성 (임시저장 또는 즉시 상신)
```
POST /api/v1/approvals
```
| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `form_id` | int | O* | 결재 양식 ID (`form_code`와 택1) |
| `form_code` | string | O* | 결재 양식 코드 (`form_id`와 택1) |
| `title` | string | O | 제목 (최대 200자) |
| `content` | object | O | 양식 데이터 (JSON) |
| `body` | string | - | 본문 HTML |
| `is_urgent` | boolean | - | 긴급 여부 |
| `department_id` | int | - | 기안 부서 ID |
| `line_id` | int | - | 결재선 템플릿 ID |
| `attachments` | int[] | - | 첨부파일 ID 배열 |
| `submit` | boolean | - | `true`면 즉시 상신 |
| `steps` | array | 조건* | 결재선 (`submit=true`일 때 필수) |
**steps 배열 항목**:
| 필드 | 타입 | 설명 |
|------|------|------|
| `step_type` (또는 `type`) | string | `approval`, `agreement`, `reference` |
| `approver_id` (또는 `user_id`) | int | 결재자 ID |
| `step_order` | int | 순서 (생략 시 자동 부여) |
```json
{
"form_code": "request",
"title": "출장 품의서",
"content": {
"destination": "부산",
"purpose": "거래처 미팅",
"amount": 500000
},
"submit": true,
"steps": [
{ "step_type": "approval", "user_id": 5 },
{ "step_type": "approval", "user_id": 8 },
{ "step_type": "reference", "user_id": 12 }
]
}
```
> **참고**: `submit: false`이면 임시저장만 하고 `steps`는 선택 사항이다.
---
### 4.3 문서 수정 (임시저장 상태만)
```
PATCH /api/v1/approvals/{id}
```
모든 필드 선택적. `steps`를 전달하면 기존 결재선을 교체한다.
---
### 4.4 문서 삭제 (임시저장/반려 상태만)
```
DELETE /api/v1/approvals/{id}
```
---
## 5. 워크플로우 액션
### 5.1 상신 (임시저장 → 진행중)
```
POST /api/v1/approvals/{id}/submit
```
| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `steps` | array | - | 새 결재선 (생략 시 기존 결재선 사용) |
> **재상신**: 반려 상태에서도 호출 가능. 반려 이력이 `rejection_history`에 자동 저장되고, `resubmit_count`가 1 증가한다.
---
### 5.2 승인
```
POST /api/v1/approvals/{id}/approve
```
| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `comment` | string | - | 승인 의견 (최대 1000자) |
> 현재 내 차례인 결재 단계만 승인 가능. 마지막 결재자가 승인하면 문서 상태가 `approved`로 변경된다.
---
### 5.3 반려
```
POST /api/v1/approvals/{id}/reject
```
| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `comment` | string | **O** | 반려 사유 (필수, 최대 1000자) |
---
### 5.4 회수 (기안자만)
```
POST /api/v1/approvals/{id}/cancel
```
| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `recall_reason` | string | - | 회수 사유 (최대 1000자) |
> 첫 번째 결재자가 이미 처리한 경우 회수 불가 (에러 반환).
---
### 5.5 보류 (현재 결재자만)
```
POST /api/v1/approvals/{id}/hold
```
| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `comment` | string | **O** | 보류 사유 (필수, 최대 1000자) |
---
### 5.6 보류 해제 (보류한 결재자만)
```
POST /api/v1/approvals/{id}/release-hold
```
파라미터 없음. 보류 상태를 다시 진행중으로 되돌린다.
---
### 5.7 전결 (현재 결재자가 최종 승인)
```
POST /api/v1/approvals/{id}/pre-decide
```
| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `comment` | string | - | 전결 의견 (최대 1000자) |
> 현재 결재자 이후의 모든 단계를 `skipped`로 변경하고 문서를 `approved`로 확정한다.
---
### 5.8 복사 재기안
```
POST /api/v1/approvals/{id}/copy
```
파라미터 없음. 완료/반려/회수된 문서를 복사하여 새 임시저장 문서를 생성한다. 결재선(스냅샷 포함)도 함께 복사된다.
**응답**: 새로 생성된 Approval 객체
---
## 6. 참조 열람 관리
### 6.1 참조 열람 처리
```
POST /api/v1/approvals/{id}/read
```
### 6.2 참조 미열람 처리
```
POST /api/v1/approvals/{id}/unread
```
### 6.3 완료함 일괄 읽음 처리
```
POST /api/v1/approvals/completed/mark-read
```
> 기안자의 미읽음 완료 문서를 일괄로 읽음 처리한다.
---
## 7. 위임 관리
부재 시 다른 사용자에게 결재 권한을 위임한다.
### 7.1 위임 목록
```
GET /api/v1/approvals/delegations
```
---
### 7.2 위임 생성
```
POST /api/v1/approvals/delegations
```
| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `delegate_id` | int | **O** | 대리자 ID |
| `start_date` | string | **O** | 시작일 (`YYYY-MM-DD`, 오늘 이후) |
| `end_date` | string | **O** | 종료일 (`YYYY-MM-DD`, 시작일 이후) |
| `form_ids` | int[] | - | 특정 양식만 위임 (생략 시 전체) |
| `notify_delegator` | boolean | - | 위임자에게 알림 여부 |
| `reason` | string | - | 위임 사유 (최대 500자) |
---
### 7.3 위임 수정
```
PATCH /api/v1/approvals/delegations/{id}
```
모든 필드 선택적. `is_active: false`로 비활성화 가능.
---
### 7.4 위임 삭제
```
DELETE /api/v1/approvals/delegations/{id}
```
---
## 8. 결재 양식 API
### 8.1 양식 목록
```
GET /api/v1/approval-forms
```
### 8.2 활성 양식 목록 (기안 시 드롭다운용)
```
GET /api/v1/approval-forms/active
```
### 8.3 양식 상세
```
GET /api/v1/approval-forms/{id}
```
### 8.4 양식 생성
```
POST /api/v1/approval-forms
```
### 8.5 양식 수정
```
PATCH /api/v1/approval-forms/{id}
```
### 8.6 양식 삭제
```
DELETE /api/v1/approval-forms/{id}
```
---
## 9. 결재선 템플릿 API
### 9.1 결재선 목록
```
GET /api/v1/approval-lines
```
### 9.2 결재선 상세
```
GET /api/v1/approval-lines/{id}
```
### 9.3 결재선 생성
```
POST /api/v1/approval-lines
```
### 9.4 결재선 수정
```
PATCH /api/v1/approval-lines/{id}
```
### 9.5 결재선 삭제
```
DELETE /api/v1/approval-lines/{id}
```
---
## 10. 화면 구성 가이드
### 10.1 메인 탭 구조
```
┌─────────┬─────────┬─────────┬─────────┐
│ 기안함 │ 결재함 │ 참조함 │ 완료함 │
│ (drafts)│ (inbox) │(reference│(completed│
│ │ [5] │) [3] │) [1] │
└─────────┴─────────┴─────────┴─────────┘
```
- 각 탭의 뱃지 숫자는 `GET /badge-counts`로 가져온다
- `pending` → 결재함 뱃지
- `reference_unread` → 참조함 뱃지
- `completed_unread` → 완료함 뱃지
### 10.2 결재함 서브 필터
| 필터 | status 값 | 설명 |
|------|----------|------|
| 결재 요청 | `requested` | 현재 내 차례 (액션 버튼 표시) |
| 예정 | `scheduled` | 내 차례 대기 |
| 처리 완료 | `completed` | 내가 처리한 문서 |
| 반려 | `rejected` | 내가 반려한 문서 |
### 10.3 문서 상세 페이지 액션 버튼
| 조건 | 표시할 버튼 |
|------|-----------|
| 내가 기안자 + `draft`/`rejected` | 수정, 삭제, 상신 |
| 내가 기안자 + `pending`/`on_hold` | 회수 |
| 내가 현재 결재자 + `pending` | 승인, 반려, 보류, 전결 |
| 내가 보류한 결재자 + `on_hold` | 보류해제 |
| `approved`/`rejected`/`cancelled` | 복사 재기안 |
| 내가 참조자 | 열람/미열람 토글 |
### 10.4 결재선 표시
결재 단계를 순서대로 표시한다. 각 단계에 스냅샷 정보를 사용한다:
```
[1] 결재 | 김팀장 (영업부/팀장) → 승인 ✓ (2026-03-11 11:00)
[2] 결재 | 박부장 (영업부/부장) → 대기 중 ◯
[3] 합의 | 이과장 (재무부/과장) → 대기 중 ◯
[4] 참조 | 정대리 (인사부/대리) → 미열람
```
> **스냅샷 필드**: `approver_name`, `approver_department`, `approver_position`은 결재선 생성 시점의 정보가 저장된다. 결재자가 부서 이동해도 결재 당시 정보가 유지된다.
---
## 관련 문서
- `dev/dev_plans/approval-system-unification-plan.md` - 결재 시스템 통합 계획서
- `frontend/api-specs/document-api-integration.md` - 문서 API 연동 명세
---
**최종 업데이트**: 2026-03-11