- README.md: 시스템 개요, 아키텍처, DB 스키마, 상태 관리, 권한 매트릭스 - workflows.md: 워크플로우 상세 (승인/반려/회수/보류/전결/복사재기안) - api-reference.md: API 엔드포인트 20개 명세 - ui-screens.md: UI 화면 구성 및 인터랙션 - INDEX.md에 결재관리 문서 등록
11 KiB
결재관리 API 명세
작성일: 2026-02-28 상태: Phase 2 구현 완료 Base URL:
/api/admin/approvals미들웨어:web,auth,hq.member관련: README.md | 워크플로우 | UI 화면
1. 개요
모든 API는 JSON 응답을 반환한다. 인증은 세션 기반이며, CSRF 토큰이 필요하다.
1.1 공통 응답 형식
성공:
{
"success": true,
"message": "처리 메시지",
"data": { ... }
}
실패 (400):
{
"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 페이지네이션 형식
{
"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}
응답:
{
"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:
{
"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):
{
"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상태에서만 삭제 가능
응답:
{
"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:
{
"comment": "승인합니다." // 선택
}
응답: { "success": true, "message": "승인되었습니다.", "data": {...} }
4.3 반려
POST /api/admin/approvals/{id}/reject
현재 결재자가 반려한다. 사유 필수.
Request Body:
{
"comment": "예산 초과로 반려합니다." // 필수
}
Validation: comment — required, string, max:1000
응답: { "success": true, "message": "반려되었습니다.", "data": {...} }
4.4 회수
POST /api/admin/approvals/{id}/cancel
기안자가
pending/on_hold문서를 회수한다. 첫 결재자 미처리 시에만 가능.
Request Body:
{
"recall_reason": "내용 수정 필요" // 선택
}
응답: { "success": true, "message": "결재가 회수되었습니다.", "data": {...} }
4.5 보류
POST /api/admin/approvals/{id}/hold
현재 결재자가 결재를 보류한다. 사유 필수.
Request Body:
{
"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:
{
"comment": "전결 처리합니다." // 선택
}
응답: { "success": true, "message": "전결 처리되었습니다.", "data": {...} }
4.8 복사 재기안
POST /api/admin/approvals/{id}/copy
기안자가
approved/rejected/cancelled문서를 복사하여 새 draft를 생성한다.
Request Body: 없음
응답:
{
"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
응답:
{
"success": true,
"data": [
{ "id": 1, "name": "일반 결재선", "steps": [...] }
]
}
5.2 양식 목록
GET /api/admin/approvals/forms
응답:
{
"success": true,
"data": [
{ "id": 1, "name": "휴가신청서", "is_active": true }
]
}
5.3 미처리 건수 (뱃지)
GET /api/admin/approvals/badge-counts
응답:
{
"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 |
열람 추적 |
관련 문서
최종 업데이트: 2026-02-28