ERP-node/docs/결재시스템_구현_현황.md

12 KiB

결재 시스템 구현 현황

1. 개요

어떤 화면/테이블에서든 결재 버튼을 추가하여 다단계(순차) 및 다중(병렬) 결재를 처리할 수 있는 범용 결재 시스템.

핵심 특징

  • 범용성: 특정 테이블에 종속되지 않고 어떤 화면에서든 사용 가능
  • 멀티테넌시: 모든 데이터가 company_code로 격리
  • 사용자 주도: 결재 요청 시 결재 모드/결재자를 직접 설정 (관리자 사전 세팅 불필요)
  • 컴포넌트 연동: 버튼 액션 타입 + 결재 단계 시각화 컴포넌트 제공

2. 아키텍처

[버튼 클릭 (approval 액션)]
    ↓
[ButtonActionExecutor] → CustomEvent('open-approval-modal') 발송
    ↓
[ApprovalGlobalListener] → 이벤트 수신
    ↓
[ApprovalRequestModal] → 결재 모드/결재자 선택 UI
    ↓
[POST /api/approval/requests] → 결재 요청 생성
    ↓
[approval_requests + approval_lines 테이블에 저장]
    ↓
[결재함 / 결재 단계 컴포넌트에서 조회 및 처리]

3. 데이터베이스

마이그레이션 파일

  • db/migrations/100_create_approval_system.sql

테이블 구조

테이블 용도 주요 컬럼
approval_definitions 결재 유형 정의 (구매결재, 문서결재 등) definition_id, definition_name, max_steps, company_code
approval_line_templates 결재선 템플릿 (미리 저장된 결재선) template_id, template_name, definition_id, company_code
approval_line_template_steps 템플릿별 결재 단계 step_id, template_id, step_order, approver_user_id, company_code
approval_requests 실제 결재 요청 건 request_id, title, target_table, target_record_id, status, requester_id, company_code
approval_lines 결재 건별 각 단계 결재자 line_id, request_id, step_order, approver_id, status, comment, company_code

결재 상태 흐름

[requested] → [in_progress] → [approved] (모든 단계 승인)
                            → [rejected] (어느 단계에서든 반려)
             → [cancelled]   (요청자가 취소)

approval_requests.status

상태 의미
requested 결재 요청됨 (1단계 결재자 처리 대기)
in_progress 결재 진행 중 (2단계 이상 진행)
approved 최종 승인 완료
rejected 반려됨
cancelled 요청자에 의해 취소

approval_lines.status

상태 의미
waiting 아직 차례가 아님
pending 현재 결재 차례 (처리 대기)
approved 승인 완료
rejected 반려
skipped 이전 단계 반려로 스킵됨

4. 백엔드 API

파일 위치

  • 컨트롤러: backend-node/src/controllers/approvalController.ts
  • 라우트: backend-node/src/routes/approvalRoutes.ts

API 엔드포인트

결재 유형 (Definitions)

메서드 경로 설명
GET /api/approval/definitions 결재 유형 목록
GET /api/approval/definitions/:id 결재 유형 상세
POST /api/approval/definitions 결재 유형 생성
PUT /api/approval/definitions/:id 결재 유형 수정
DELETE /api/approval/definitions/:id 결재 유형 삭제

결재선 템플릿 (Templates)

메서드 경로 설명
GET /api/approval/templates 템플릿 목록
GET /api/approval/templates/:id 템플릿 상세 (단계 포함)
POST /api/approval/templates 템플릿 생성
PUT /api/approval/templates/:id 템플릿 수정
DELETE /api/approval/templates/:id 템플릿 삭제

결재 요청 (Requests)

메서드 경로 설명
GET /api/approval/requests 결재 요청 목록 (필터 가능)
GET /api/approval/requests/:id 결재 요청 상세 (결재 라인 포함)
POST /api/approval/requests 결재 요청 생성
POST /api/approval/requests/:id/cancel 결재 취소

결재 라인 처리 (Lines)

메서드 경로 설명
GET /api/approval/my-pending 내 미처리 결재 목록
POST /api/approval/lines/:lineId/process 승인/반려 처리

결재 요청 생성 시 입력

interface CreateApprovalRequestInput {
  title: string;                           // 결재 제목
  description?: string;                    // 결재 설명
  target_table: string;                    // 대상 테이블명 (예: sales_order_mng)
  target_record_id?: string;               // 대상 레코드 ID (선택)
  approval_mode?: "sequential" | "parallel"; // 결재 모드
  approvers: {                             // 결재자 목록
    approver_id: string;
    approver_name?: string;
    approver_position?: string;
    approver_dept?: string;
  }[];
}

결재 처리 로직

순차 결재 (sequential)

  1. 첫 번째 결재자 status = 'pending', 나머지 'waiting'
  2. 1단계 승인 → 2단계 'pending'으로 변경
  3. 모든 단계 승인 → approval_requests.status = 'approved'
  4. 어느 단계에서 반려 → 이후 단계 'skipped', 요청 'rejected'

병렬 결재 (parallel)

  1. 모든 결재자 status = 'pending' (동시 처리)
  2. 모든 결재자 승인 → 'approved'
  3. 한 명이라도 반려 → 'rejected'

5. 프론트엔드

5.1 결재 요청 모달

파일: frontend/components/approval/ApprovalRequestModal.tsx

  • 결재 모드 선택 (다단 결재 / 다중 결재)
  • 결재자 검색 (사용자 API 검색, 한글/영문/ID 검색 가능)
  • 결재자 추가/삭제, 순서 변경 (순차 결재 시)
  • 대상 테이블/레코드 ID 자동 세팅

5.2 결재 글로벌 리스너

파일: frontend/components/approval/ApprovalGlobalListener.tsx

  • open-approval-modal CustomEvent를 전역으로 수신
  • 이벤트의 detail에서 targetTable, targetRecordId, formData 추출
  • ApprovalRequestModal 열기

5.3 결재함 페이지

파일: frontend/app/(main)/admin/approvalBox/page.tsx

  • 탭 구성: 보낸 결재 / 받은 결재 / 완료된 결재
  • 결재 상태별 필터링
  • 결재 상세 조회 및 승인/반려 처리

진입점: 사용자 프로필 드롭다운 > "결재함"

5.4 결재 단계 시각화 컴포넌트 (v2-approval-step)

파일 위치: frontend/lib/registry/components/v2-approval-step/

파일 역할
types.ts ApprovalStepConfig 타입 정의
ApprovalStepComponent.tsx 결재 단계 시각화 UI (가로형 스테퍼 / 세로형 타임라인)
ApprovalStepConfigPanel.tsx 설정 패널 (대상 테이블/컬럼 Combobox, 표시 옵션)
ApprovalStepRenderer.tsx 컴포넌트 레지스트리 등록
index.ts 컴포넌트 정의 (이름, 태그, 기본값 등)

설정 항목

설정 설명
대상 테이블 결재를 걸 데이터가 있는 테이블 (Combobox 검색)
레코드 ID 필드명 테이블의 PK 컬럼 (Combobox 검색)
표시 모드 가로형 스테퍼 / 세로형 타임라인
부서/직급 표시 결재자의 부서/직급 정보 표시 여부
결재 코멘트 표시 승인/반려 시 입력한 코멘트 표시 여부
처리 시각 표시 결재 처리 시각 표시 여부
콤팩트 모드 작게 표시

5.5 API 클라이언트

파일: frontend/lib/api/approval.ts

함수 용도
getApprovalDefinitions() 결재 유형 목록 조회
getApprovalTemplates() 결재선 템플릿 목록 조회
getApprovalRequests() 결재 요청 목록 조회 (필터 지원)
getApprovalRequest(id) 결재 요청 상세 조회
createApprovalRequest(data) 결재 요청 생성
cancelApprovalRequest(id) 결재 취소
getMyPendingApprovals() 내 미처리 결재 목록
processApprovalLine(lineId, data) 승인/반려 처리

5.6 버튼 액션 연동

관련 파일

파일 수정 내용
frontend/lib/utils/buttonActions.ts ButtonActionType"approval" 추가, handleApproval 구현
frontend/lib/utils/improvedButtonActionExecutor.ts approval 액션 핸들러 추가
frontend/lib/registry/components/v2-button-primary/ButtonPrimaryComponent.tsx silentActions"approval" 추가
frontend/components/screen/config-panels/ButtonConfigPanel.tsx 결재 액션 설정 UI (대상 테이블 자동 세팅)

동작 흐름

  1. 버튼 설정에서 액션 타입 = "approval" 선택
  2. 대상 테이블 자동 설정 (현재 화면 테이블)
  3. 버튼 클릭 시 CustomEvent('open-approval-modal') 발송
  4. ApprovalGlobalListener가 수신하여 ApprovalRequestModal 오픈

6. 멀티테넌시 적용

영역 적용
DB 테이블 모든 테이블에 company_code NOT NULL 포함
인덱스 company_code 컬럼에 인덱스 생성
SELECT WHERE company_code = $N 필수
INSERT company_code 값 포함 필수
UPDATE/DELETE WHERE 절에 company_code 조건 포함
최고관리자 company_code = '*' → 모든 데이터 조회 가능
JOIN ON 절에 company_code 매칭 포함

7. 전체 파일 목록

데이터베이스

db/migrations/100_create_approval_system.sql

백엔드

backend-node/src/controllers/approvalController.ts
backend-node/src/routes/approvalRoutes.ts

프론트엔드 - 결재 모달/리스너

frontend/components/approval/ApprovalRequestModal.tsx
frontend/components/approval/ApprovalGlobalListener.tsx

프론트엔드 - 결재함 페이지

frontend/app/(main)/admin/approvalBox/page.tsx

프론트엔드 - 결재 단계 컴포넌트

frontend/lib/registry/components/v2-approval-step/types.ts
frontend/lib/registry/components/v2-approval-step/ApprovalStepComponent.tsx
frontend/lib/registry/components/v2-approval-step/ApprovalStepConfigPanel.tsx
frontend/lib/registry/components/v2-approval-step/ApprovalStepRenderer.tsx
frontend/lib/registry/components/v2-approval-step/index.ts

프론트엔드 - API 클라이언트

frontend/lib/api/approval.ts

프론트엔드 - 버튼 액션 연동 (수정된 파일)

frontend/lib/utils/buttonActions.ts
frontend/lib/utils/improvedButtonActionExecutor.ts
frontend/lib/registry/components/v2-button-primary/ButtonPrimaryComponent.tsx
frontend/components/screen/config-panels/ButtonConfigPanel.tsx

프론트엔드 - 레이아웃 (수정된 파일)

frontend/components/layout/UserDropdown.tsx     (결재함 메뉴 추가)
frontend/components/layout/AppLayout.tsx        (결재함 메뉴 추가)
frontend/lib/registry/components/index.ts       (v2-approval-step 렌더러 import)

8. 사용 방법

결재 버튼 추가

  1. 화면 디자이너에서 버튼 컴포넌트 추가
  2. 버튼 설정 > 액션 타입 = 결재 선택
  3. 대상 테이블이 자동 설정됨 (수동 변경 가능)
  4. 저장

결재 요청하기

  1. 데이터 행 선택 (선택적)
  2. 결재 버튼 클릭
  3. 결재 모달에서:
    • 결재 제목 입력
    • 결재 모드 선택 (다단 결재 / 다중 결재)
    • 결재자 검색하여 추가
  4. 결재 요청 클릭

결재 처리하기

  1. 프로필 드롭다운 > 결재함 클릭
  2. 받은 결재 탭에서 대기 중인 결재 확인
  3. 상세 보기 > 승인 또는 반려

결재 단계 표시하기

  1. 화면 디자이너에서 결재 단계 컴포넌트 추가
  2. 설정에서 대상 테이블 / 레코드 ID 필드 선택
  3. 표시 모드 (가로/세로) 및 옵션 설정
  4. 저장 → 행 선택 시 해당 레코드의 결재 단계가 표시됨

9. 향후 개선 사항

  • 결재 알림 (실시간 알림, 이메일 연동)
  • 제어관리 시스템 연동 (결재 완료 후 자동 액션)
  • 결재 위임 기능
  • 결재 이력 조회 / 통계 대시보드
  • 결재선 즐겨찾기 (자주 쓰는 결재선 저장)
  • 모바일 결재 처리 최적화