docs: [approval] 결재관리 모듈 통합 가이드 추가
- 다른 기능에 결재선/참조선 붙일 때 참조하는 원스톱 가이드 - 참조 문서 맵 (8개 문서 읽기 순서), 코드 참조 맵 - 독립 결재 vs 연동 결재 2가지 통합 유형 및 구현 절차 - 부적합품관리 예시 코드 포함 - INDEX.md 작업별 필수 문서 + dev/guides 섹션 등록
This commit is contained in:
2
INDEX.md
2
INDEX.md
@@ -32,6 +32,7 @@
|
||||
| 재고생산관리 API | `frontend/api-specs/stock-production-api.md` | 재고생산 API 명세 (기존 수주 API + STOCK 타입) |
|
||||
| 절곡품 LOT API | `frontend/api-specs/bending-lot-api.md` | 절곡품 코드맵/품목매핑/LOT 채번 API (프론트엔드 구현 가이드 포함) |
|
||||
| 결재관리 | `dev/dev_plans/approval-system-unification-plan.md` | MNG→API 결재 통합 계획 |
|
||||
| 결재 모듈 통합 | `dev/guides/approval-module-integration-guide.md` | 다른 기능에 결재선/참조선 붙이기 (참조 문서 맵, 구현 절차) |
|
||||
| API 품질 | `system/api-code-quality-audit.md` | 정석 패턴 R1~R6, 안티패턴, 보안, 체크리스트 |
|
||||
| API 학습 | `dev/guides/api-request-lifecycle.md` | Client API로 배우는 요청 생명주기 8단계 |
|
||||
| API 개선 | `dev/dev_plans/api-route-improvement-plan.md` | API 라우트 구조 개선 계획 (1,099개 분석) |
|
||||
@@ -230,6 +231,7 @@ DB 도메인별:
|
||||
| [tenant-email-integration-guide.md](dev/guides/tenant-email-integration-guide.md) | 테넌트 이메일 연동 (SMTP 프리셋, MNG 관리 화면, 연결 테스트) |
|
||||
| [performance-report-excel-export.md](dev/guides/performance-report-excel-export.md) | 실적신고 확정건 엑셀 Export (건기원 양식, PhpSpreadsheet, 셀 병합) |
|
||||
| [sam-hotkey-manager.md](dev/guides/sam-hotkey-manager.md) | SAM Hotkey Manager — Claude Code CLI 프롬프트 단축키 자동화 (AHK v2) |
|
||||
| [approval-module-integration-guide.md](dev/guides/approval-module-integration-guide.md) | 결재관리 모듈 통합 가이드 — 다른 기능에 결재선/참조선 붙이기 (문서 참조 맵, 코드 참조, 구현 절차) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
395
dev/guides/approval-module-integration-guide.md
Normal file
395
dev/guides/approval-module-integration-guide.md
Normal file
@@ -0,0 +1,395 @@
|
||||
# 결재관리 모듈 통합 가이드
|
||||
|
||||
> **작성일**: 2026-03-19
|
||||
> **상태**: 확정
|
||||
> **대상**: 결재 기능을 새 모듈(부적합품관리, 구매요청 등)에 통합하려는 개발자 또는 AI
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 목적
|
||||
|
||||
이 문서는 **"결재관리 모듈을 다른 기능에 붙이고 싶다"**는 요구에 대한 원스톱 참조 가이드다.
|
||||
어떤 문서를 읽고, 어떤 코드를 참조하며, 어떤 순서로 구현하는지를 정리한다.
|
||||
|
||||
### 1.2 사용법
|
||||
|
||||
```
|
||||
사용자: "부적합품관리에 결재 기능 붙여줘"
|
||||
Claude: 이 문서를 읽고 → 참조 문서 순서대로 파악 → 구현
|
||||
```
|
||||
|
||||
### 1.3 결재 모듈이 제공하는 것
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| **결재선 지정** | 결재자(승인/반려 권한) + 합의자(타부서 동의) 다중 선택 |
|
||||
| **참조선 지정** | 참조자(열람만 가능) 다중 선택, 열람 추적 |
|
||||
| **워크플로우** | 상신 → 승인/반려/보류/전결 → 완료 |
|
||||
| **재상신** | 반려 후 수정하여 재상신 (이력 보존) |
|
||||
| **뱃지 카운트** | 기안함/결재함/참조함/완료함 미처리 건수 |
|
||||
| **결재선 템플릿** | 자주 쓰는 결재선을 저장하여 재사용 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 참조 문서 맵
|
||||
|
||||
> **순서대로 읽으면 결재 모듈의 전체 구조를 파악할 수 있다.**
|
||||
|
||||
### 2.1 필수 읽기 (구현 전 반드시)
|
||||
|
||||
| 순서 | 문서 | 경로 | 읽는 목적 |
|
||||
|:----:|------|------|----------|
|
||||
| 1 | 결재관리 종합 개요 | `features/approvals/README.md` | 테이블 구조, 상태 머신, 권한 매트릭스 |
|
||||
| 2 | 워크플로우 상세 | `features/approvals/workflows.md` | 각 액션(상신/승인/반려/보류/전결)의 조건과 로직 |
|
||||
| 3 | API 명세 (MNG 내부) | `features/approvals/api-reference.md` | MNG 컨트롤러의 API 엔드포인트 |
|
||||
|
||||
### 2.2 서비스(API) 연동 시 추가 읽기
|
||||
|
||||
| 순서 | 문서 | 경로 | 읽는 목적 |
|
||||
|:----:|------|------|----------|
|
||||
| 4 | 서비스 API 명세 | `frontend/api-specs/approval-api.md` | React/외부에서 호출하는 REST API 28개 |
|
||||
| 5 | MNG↔API 비교 | `features/approvals/mng-api-comparison.md` | 양쪽 구현 차이, 모델 동기화 현황 |
|
||||
| 6 | DB 변경/모델 동기화 | `features/approvals/db-changes-and-model-sync.md` | 마이그레이션 이력, 모델 필드 일치 여부 |
|
||||
|
||||
### 2.3 양식 설계 시
|
||||
|
||||
| 순서 | 문서 | 경로 | 읽는 목적 |
|
||||
|:----:|------|------|----------|
|
||||
| 7 | 양식별 기술 명세 | `features/approvals/form-types.md` | 양식 JSON 구조, 필드 타입, 인터랙션 |
|
||||
| 8 | UI 화면 구성 | `features/approvals/ui-screens.md` | 화면별 UI 요소, 결재선 에디터 구조 |
|
||||
|
||||
### 2.4 배경 지식 (선택)
|
||||
|
||||
| 문서 | 경로 | 읽는 목적 |
|
||||
|------|------|----------|
|
||||
| 통합 계획 | `dev/dev_plans/approval-system-unification-plan.md` | Phase 1~6 전체 로드맵 |
|
||||
| API 개발 규칙 | `dev/standards/api-rules.md` | Service-First 패턴, FormRequest |
|
||||
|
||||
---
|
||||
|
||||
## 3. 코드 참조 맵
|
||||
|
||||
### 3.1 API 프로젝트 (`sam/api`)
|
||||
|
||||
| 구분 | 경로 | 역할 |
|
||||
|------|------|------|
|
||||
| **Service** | `app/Services/ApprovalService.php` | 전체 비즈니스 로직 (48개 메서드) |
|
||||
| **Controller** | `app/Http/Controllers/Api/V1/ApprovalController.php` | REST API 엔드포인트 |
|
||||
| **Model** | `app/Models/Tenants/Approval.php` | 결재 문서 (상태 상수, 헬퍼) |
|
||||
| | `app/Models/Tenants/ApprovalStep.php` | 결재 단계 (step_type, 스냅샷) |
|
||||
| | `app/Models/Tenants/ApprovalLine.php` | 결재선 템플릿 (STEP_TYPE 상수) |
|
||||
| | `app/Models/Tenants/ApprovalForm.php` | 결재 양식 |
|
||||
| | `app/Models/Tenants/ApprovalDelegation.php` | 위임 설정 |
|
||||
| **Routes** | `routes/api/v1/hr.php` | 45개 라우트 정의 |
|
||||
| **Migration** | `database/migrations/2025_12_17_*` ~ `2026_03_11_*` | 21개 마이그레이션 |
|
||||
|
||||
### 3.2 MNG 프로젝트 (`sam/mng`)
|
||||
|
||||
| 구분 | 경로 | 역할 |
|
||||
|------|------|------|
|
||||
| **Service** | `app/Services/ApprovalService.php` | MNG 전용 비즈니스 로직 |
|
||||
| **Controller** | `app/Http/Controllers/ApprovalController.php` | 웹 뷰 |
|
||||
| | `app/Http/Controllers/Api/ApprovalApiController.php` | HTMX/AJAX API |
|
||||
| **Model** | `app/Models/Approvals/Approval.php` 외 5개 | API 모델의 수동 동기 사본 |
|
||||
| **View** | `resources/views/approvals/` | Blade 템플릿 |
|
||||
| **결재선 에디터** | `resources/views/approvals/partials/_approval-line-editor.blade.php` | 2패널 에디터 (결재/참조 분리) |
|
||||
|
||||
### 3.3 핵심 상수 (다른 모듈에서 참조)
|
||||
|
||||
```php
|
||||
// 문서 상태 (Approval 모델)
|
||||
Approval::STATUS_DRAFT // 'draft' — 임시저장
|
||||
Approval::STATUS_PENDING // 'pending' — 진행중
|
||||
Approval::STATUS_APPROVED // 'approved' — 완료
|
||||
Approval::STATUS_REJECTED // 'rejected' — 반려
|
||||
Approval::STATUS_CANCELLED // 'cancelled' — 회수
|
||||
Approval::STATUS_ON_HOLD // 'on_hold' — 보류
|
||||
|
||||
// 단계 유형 (ApprovalLine 모델)
|
||||
ApprovalLine::STEP_TYPE_APPROVAL // 'approval' — 결재 (승인/반려 가능)
|
||||
ApprovalLine::STEP_TYPE_AGREEMENT // 'agreement' — 합의 (타부서)
|
||||
ApprovalLine::STEP_TYPE_REFERENCE // 'reference' — 참조 (열람만)
|
||||
|
||||
// 단계 상태 (ApprovalStep 모델)
|
||||
ApprovalStep::STATUS_PENDING // 'pending'
|
||||
ApprovalStep::STATUS_APPROVED // 'approved'
|
||||
ApprovalStep::STATUS_REJECTED // 'rejected'
|
||||
ApprovalStep::STATUS_SKIPPED // 'skipped' — 전결/회수 시
|
||||
ApprovalStep::STATUS_ON_HOLD // 'on_hold'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 통합 구현 절차
|
||||
|
||||
### 4.1 통합 유형 선택
|
||||
|
||||
새 기능에 결재를 붙이는 방식은 **2가지**:
|
||||
|
||||
| 유형 | 설명 | 적합한 경우 |
|
||||
|------|------|------------|
|
||||
| **A. 독립 결재** | 결재 양식을 새로 만들어 결재 모듈에서 관리 | 품의서, 신청서 등 문서 중심 |
|
||||
| **B. 연동 결재** | 기존 기능의 상태 전이에 결재를 끼워넣기 | 부적합품, 구매요청 등 업무 프로세스 중심 |
|
||||
|
||||
### 4.2 유형 A — 독립 결재 (양식 추가)
|
||||
|
||||
> 예시: "출장 품의서" 양식을 결재 시스템에 추가
|
||||
|
||||
**Step 1. 양식 등록**
|
||||
|
||||
```php
|
||||
// 마이그레이션 또는 tinker로 양식 등록
|
||||
ApprovalForm::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'name' => '출장 품의서',
|
||||
'code' => 'business_trip',
|
||||
'category' => 'request',
|
||||
'template' => [
|
||||
'destination' => ['type' => 'text', 'label' => '목적지', 'required' => true],
|
||||
'purpose' => ['type' => 'textarea', 'label' => '출장 목적'],
|
||||
'budget' => ['type' => 'currency', 'label' => '예정 비용'],
|
||||
],
|
||||
'body_template' => '<h2>출장 품의서</h2>...',
|
||||
'is_active' => true,
|
||||
]);
|
||||
```
|
||||
|
||||
- 참조: `features/approvals/form-types.md` — 양식 JSON 필드 구조
|
||||
|
||||
**Step 2. 끝**
|
||||
|
||||
양식만 등록하면 기존 결재 화면(기안함, 결재함 등)에서 바로 사용 가능하다.
|
||||
결재선/참조선 지정, 워크플로우 전체가 자동으로 작동한다.
|
||||
|
||||
### 4.3 유형 B — 연동 결재 (업무 프로세스 내장)
|
||||
|
||||
> 예시: "부적합품관리"에서 부적합 처리 결과를 결재받는 경우
|
||||
|
||||
**Step 1. 양식 등록** (유형 A와 동일)
|
||||
|
||||
```php
|
||||
ApprovalForm::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'name' => '부적합품 처리 결재',
|
||||
'code' => 'nonconforming_disposition',
|
||||
'category' => 'quality',
|
||||
'template' => [
|
||||
'nonconforming_id' => ['type' => 'hidden', 'label' => '부적합 ID'],
|
||||
'disposition_type' => ['type' => 'select', 'label' => '처리구분',
|
||||
'options' => ['반품', '특채', '수리', '폐기']],
|
||||
'disposition_detail' => ['type' => 'textarea', 'label' => '처리 상세'],
|
||||
],
|
||||
'is_active' => true,
|
||||
]);
|
||||
```
|
||||
|
||||
**Step 2. 결재 문서 생성 (기존 기능에서 호출)**
|
||||
|
||||
```php
|
||||
// 부적합품 Service에서 결재 요청 시
|
||||
use App\Models\Tenants\Approval;
|
||||
use App\Models\Tenants\ApprovalForm;
|
||||
|
||||
$form = ApprovalForm::where('code', 'nonconforming_disposition')->first();
|
||||
|
||||
$approval = Approval::create([
|
||||
'tenant_id' => $this->tenantId(),
|
||||
'form_id' => $form->id,
|
||||
'title' => "부적합품 처리 결재 - {$nonconforming->document_number}",
|
||||
'content' => [
|
||||
'nonconforming_id' => $nonconforming->id,
|
||||
'disposition_type' => $data['disposition_type'],
|
||||
'disposition_detail' => $data['disposition_detail'],
|
||||
],
|
||||
'status' => Approval::STATUS_DRAFT,
|
||||
'drafter_id' => $this->apiUserId(),
|
||||
'department_id' => $user->department_id,
|
||||
'current_step' => 0,
|
||||
]);
|
||||
```
|
||||
|
||||
**Step 3. 결재선/참조선 생성**
|
||||
|
||||
```php
|
||||
// ApprovalService::createApprovalSteps() 내부 로직 참조
|
||||
// steps 배열 예시:
|
||||
$steps = [
|
||||
['step_type' => 'approval', 'approver_id' => $teamLeaderId, 'step_order' => 1],
|
||||
['step_type' => 'approval', 'approver_id' => $qualityMgrId, 'step_order' => 2],
|
||||
['step_type' => 'reference', 'approver_id' => $productionMgrId, 'step_order' => 3],
|
||||
];
|
||||
|
||||
// ApprovalService의 createApprovalSteps() 호출 또는 동일 패턴 사용
|
||||
// → 결재자 스냅샷(이름, 부서, 직급) 자동 저장
|
||||
```
|
||||
|
||||
**Step 4. 상신**
|
||||
|
||||
```php
|
||||
// ApprovalService::submit() 호출
|
||||
$approvalService->submit($approval->id);
|
||||
// → status: draft → pending, current_step: 1
|
||||
```
|
||||
|
||||
**Step 5. 결재 완료 시 원래 기능에 반영 (콜백)**
|
||||
|
||||
```php
|
||||
// ApprovalService::approve() 내부에서
|
||||
// 최종 승인 완료 시 원래 기능의 상태를 업데이트하는 패턴:
|
||||
|
||||
// 방법 1: approve() 후 호출측에서 처리
|
||||
if ($approval->status === Approval::STATUS_APPROVED) {
|
||||
$nonconforming = Nonconforming::find($approval->content['nonconforming_id']);
|
||||
$nonconforming->update(['status' => 'disposition_approved']);
|
||||
}
|
||||
|
||||
// 방법 2: linkable (polymorphic) 관계 활용
|
||||
// → Document 브릿지 패턴 참조: ApprovalService::syncToLinkedDocument()
|
||||
```
|
||||
|
||||
### 4.4 linkable (Polymorphic) 연동 패턴
|
||||
|
||||
`approvals` 테이블의 `linkable_type`, `linkable_id` 컬럼으로 다형성 연결이 가능하다.
|
||||
|
||||
```php
|
||||
// 결재 생성 시 원본 모델 연결
|
||||
$approval = Approval::create([
|
||||
// ... 기본 필드
|
||||
'linkable_type' => Nonconforming::class,
|
||||
'linkable_id' => $nonconforming->id,
|
||||
]);
|
||||
|
||||
// 조회 시
|
||||
$approval->linkable; // → Nonconforming 모델 인스턴스
|
||||
```
|
||||
|
||||
- 참조: `ApprovalService::syncToLinkedDocument()` — Document 연동 구현 예시
|
||||
- 참조: `ApprovalService::handleApprovalCompleted()` — Leave 연동 구현 예시
|
||||
|
||||
---
|
||||
|
||||
## 5. 테이블 관계도
|
||||
|
||||
```
|
||||
┌──────────────────────┐
|
||||
│ 새 기능 테이블 │
|
||||
│ (예: nonconformings) │
|
||||
│ │
|
||||
│ approval_id FK ──────│───┐
|
||||
│ 또는 linkable 관계 │ │
|
||||
└──────────────────────┘ │
|
||||
│
|
||||
┌──────────────────────┘
|
||||
▼
|
||||
┌──────────────────┐ 1:N ┌──────────────────┐
|
||||
│ approvals │──────────→│ approval_steps │
|
||||
│ │ │ │
|
||||
│ form_id ─────────│──┐ │ step_type: │
|
||||
│ line_id ─────────│──│─┐ │ approval │
|
||||
│ status │ │ │ │ agreement │
|
||||
│ content (JSON) │ │ │ │ reference ← 참조│
|
||||
│ linkable_type │ │ │ │ │
|
||||
│ linkable_id │ │ │ │ approver_id │
|
||||
└──────────────────┘ │ │ │ approver_name │
|
||||
│ │ │ (스냅샷) │
|
||||
┌─────────────────┘ │ └──────────────────┘
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ approval_ │ │ approval_ │
|
||||
│ forms │ │ lines │
|
||||
│ │ │ │
|
||||
│ code │ │ steps (JSON) │
|
||||
│ template │ │ is_default │
|
||||
│ body_template│ └──────────────┘
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. MNG에서 구현할 때 (Blade + HTMX)
|
||||
|
||||
MNG에서 기존 화면에 결재 버튼을 추가하려면:
|
||||
|
||||
| 참조 대상 | 경로 | 복사/참조 용도 |
|
||||
|----------|------|-------------|
|
||||
| 결재선 에디터 | `mng/resources/views/approvals/partials/_approval-line-editor.blade.php` | 결재선/참조선 선택 UI |
|
||||
| 결재 상세 뷰 | `mng/resources/views/approvals/show.blade.php` | 결재 서명란, 진행 상태 |
|
||||
| 결재 생성 뷰 | `mng/resources/views/approvals/create.blade.php` | 기안 작성 폼 구조 |
|
||||
| MNG Service | `mng/app/Services/ApprovalService.php` | 비즈니스 로직 참조 |
|
||||
|
||||
---
|
||||
|
||||
## 7. React(서비스)에서 구현할 때
|
||||
|
||||
| 참조 대상 | 경로 | 용도 |
|
||||
|----------|------|------|
|
||||
| API 명세 | `docs/frontend/api-specs/approval-api.md` | 28개 엔드포인트, 요청/응답 |
|
||||
| 기존 React 페이지 | `react/src/app/[locale]/(protected)/approval/` | 페이지 구조 참조 |
|
||||
| 인증 | `authenticatedFetch` / `serverFetch` | API 호출 시 필수 |
|
||||
|
||||
### 7.1 핵심 API (연동에 필요한 최소 세트)
|
||||
|
||||
```
|
||||
POST /api/v1/approvals → 결재 문서 생성
|
||||
POST /api/v1/approvals/{id}/submit → 상신
|
||||
GET /api/v1/approvals/{id} → 상세 조회 (결재선 포함)
|
||||
GET /api/v1/approval-forms/active → 양식 목록 (드롭다운)
|
||||
GET /api/v1/approval-lines → 결재선 템플릿 목록
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 체크리스트
|
||||
|
||||
### 구현 전
|
||||
|
||||
- [ ] `features/approvals/README.md` 읽기 (테이블, 상태, 권한)
|
||||
- [ ] `features/approvals/workflows.md` 읽기 (워크플로우 상세)
|
||||
- [ ] 통합 유형 결정: **A. 독립 결재** vs **B. 연동 결재**
|
||||
- [ ] 결재 양식(ApprovalForm) 설계 — `template` JSON 필드 구조
|
||||
|
||||
### 구현 중
|
||||
|
||||
- [ ] `tenant_id` 기반 멀티테넌트 적용 확인
|
||||
- [ ] 결재선에 `step_type='reference'` 참조자 포함 가능 확인
|
||||
- [ ] 결재자 스냅샷 저장 (이름/부서/직급)
|
||||
- [ ] 결재 완료 시 원래 기능 상태 반영 로직 구현
|
||||
|
||||
### 구현 후
|
||||
|
||||
- [ ] 기안함/결재함/참조함에서 새 양식 문서가 정상 표시되는지 확인
|
||||
- [ ] 결재 승인 → 원래 기능 상태 변경 정상 동작 확인
|
||||
- [ ] 반려 → 재상신 흐름 테스트
|
||||
- [ ] 뱃지 카운트에 새 양식 문서 포함되는지 확인
|
||||
|
||||
---
|
||||
|
||||
## 9. 주의사항
|
||||
|
||||
| 항목 | 설명 |
|
||||
|------|------|
|
||||
| 마이그레이션 | 결재 테이블은 **API 프로젝트에서만** 관리. 새 기능이 MNG 전용이라도 결재 테이블 수정은 API에서 |
|
||||
| 양식 등록 | 시더가 아닌 **마이그레이션 또는 tinker**로 등록 (메뉴 관리 규칙과 동일) |
|
||||
| MNG→API 호출 | 화이트리스트 확인 필수. `ApiKeyMiddleware.php`의 `allowWithoutAuth` 배열 |
|
||||
| 모델 동기화 | MNG에서 새 필드를 추가하면 API 모델에도 수동 동기화 필요 |
|
||||
|
||||
---
|
||||
|
||||
## 관련 문서
|
||||
|
||||
| 문서 | 경로 |
|
||||
|------|------|
|
||||
| 결재관리 종합 개요 | [features/approvals/README.md](../../features/approvals/README.md) |
|
||||
| 워크플로우 상세 | [features/approvals/workflows.md](../../features/approvals/workflows.md) |
|
||||
| 양식별 기술 명세 | [features/approvals/form-types.md](../../features/approvals/form-types.md) |
|
||||
| API 명세 (MNG) | [features/approvals/api-reference.md](../../features/approvals/api-reference.md) |
|
||||
| API 명세 (서비스) | [frontend/api-specs/approval-api.md](../../frontend/api-specs/approval-api.md) |
|
||||
| MNG↔API 비교 | [features/approvals/mng-api-comparison.md](../../features/approvals/mng-api-comparison.md) |
|
||||
| DB 변경/모델 동기화 | [features/approvals/db-changes-and-model-sync.md](../../features/approvals/db-changes-and-model-sync.md) |
|
||||
| UI 화면 구성 | [features/approvals/ui-screens.md](../../features/approvals/ui-screens.md) |
|
||||
|
||||
---
|
||||
|
||||
**최종 업데이트**: 2026-03-19
|
||||
Reference in New Issue
Block a user