Files
sam-docs/dev/guides/approval-module-integration-guide.md
김보곤 f00452304c docs: [approval] 결재관리 모듈 통합 가이드 추가
- 다른 기능에 결재선/참조선 붙일 때 참조하는 원스톱 가이드
- 참조 문서 맵 (8개 문서 읽기 순서), 코드 참조 맵
- 독립 결재 vs 연동 결재 2가지 통합 유형 및 구현 절차
- 부적합품관리 예시 코드 포함
- INDEX.md 작업별 필수 문서 + dev/guides 섹션 등록
2026-03-19 08:54:55 +09:00

16 KiB

결재관리 모듈 통합 가이드

작성일: 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 핵심 상수 (다른 모듈에서 참조)

// 문서 상태 (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. 양식 등록

// 마이그레이션 또는 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와 동일)

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. 결재 문서 생성 (기존 기능에서 호출)

// 부적합품 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. 결재선/참조선 생성

// 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. 상신

// ApprovalService::submit() 호출
$approvalService->submit($approval->id);
// → status: draft → pending, current_step: 1

Step 5. 결재 완료 시 원래 기능에 반영 (콜백)

// 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 컬럼으로 다형성 연결이 가능하다.

// 결재 생성 시 원본 모델 연결
$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.phpallowWithoutAuth 배열
모델 동기화 MNG에서 새 필드를 추가하면 API 모델에도 수동 동기화 필요

관련 문서

문서 경로
결재관리 종합 개요 features/approvals/README.md
워크플로우 상세 features/approvals/workflows.md
양식별 기술 명세 features/approvals/form-types.md
API 명세 (MNG) features/approvals/api-reference.md
API 명세 (서비스) frontend/api-specs/approval-api.md
MNG↔API 비교 features/approvals/mng-api-comparison.md
DB 변경/모델 동기화 features/approvals/db-changes-and-model-sync.md
UI 화면 구성 features/approvals/ui-screens.md

최종 업데이트: 2026-03-19