diff --git a/sam/docs/INDEX.md b/sam/docs/INDEX.md index 10e0aca..b826baf 100644 --- a/sam/docs/INDEX.md +++ b/sam/docs/INDEX.md @@ -1,30 +1,27 @@ # SAM 프로젝트 문서 인덱스 -> **Claude Code 작업 전 필수 확인** - 작업 유형에 맞는 문서를 먼저 읽고 시작하세요. +> **Claude Code 작업 전 필수 확인** — 작업 유형에 맞는 문서를 먼저 읽고 시작하세요. +> **최종 갱신**: 2026-02-28 --- -## 🎯 작업별 필수 문서 (반드시 먼저 확인) +## 🎯 작업별 필수 문서 | 작업 유형 | 필수 문서 | 용도 | |----------|----------|------| -| **TODO 확인** | `TODO.md` | 긴급/중요 이슈 및 개선사항 추적 | | **API 개발** | `standards/api-rules.md` | Service-First, FormRequest, i18n 규칙 | -| **DB 변경** | `specs/database-schema.md` | 테이블 구조, 관계, 컬럼 규칙 | -| **새 기능 구현** | `architecture/system-overview.md` | 전체 아키텍처 이해 | -| **보안 관련** | `architecture/security-policy.md` | 인증/인가, 보안 규칙 | +| **DB 변경** | `system/database/README.md` | 테이블 구조, 관계, 컬럼 규칙 | +| **새 기능 구현** | `system/overview.md` | 전체 아키텍처 이해 | +| **보안 관련** | `system/security-policy.md` | 인증/인가, 보안 규칙 | | **Git 커밋** | `standards/git-conventions.md` | 커밋 메시지, 브랜치 전략 | | **품질 검증** | `standards/quality-checklist.md` | 코드 품질 체크리스트 | | **Swagger 작성** | `guides/swagger-guide.md` | API 문서 작성 방법 | | **품목관리** | `rules/item-policy.md` | 품목 정책 (유형, 예약어, API 규칙) | -| **게시판** | `specs/board-system-spec.md` | 게시판 시스템 설계 | | **단가관리** | `rules/pricing-policy.md` | 원가/판매가 계산, 리비전 관리 | -| **운영 배포** | `plans/production-deployment-plan.md` | 운영 환경 배포 계획 (CI/CD, 서버 아키텍처) | -| **서버 동작 원리** | `guides/server-how-it-works.md` | 요청 흐름, 배포 원리 이해 | -| **과금정책 (고객용)** | `rules/customer-pricing.md` | 고객 안내용 서비스 요금표 | -| **과금정책 (파트너)** | `rules/partner-commission.md` | 영업파트너 수당 체계 및 정산 | -| **과금정책 (내부용)** | `rules/billing-policy.md` | 내부용 원가/마진/코드참조 (CONFIDENTIAL) | | **견적관리** | `features/quotes/README.md` | 견적 시스템, BOM 계산, 10단계 로직 | +| **결재관리** | `features/approvals/README.md` | 결재 시스템 (워크플로우, API, UI) | +| **운영 배포** | `plans/production-deployment-plan.md` | 운영 환경 배포 계획 | +| **서버 운영** | `deploys/ops-manual/README.md` | 서버 운영 매뉴얼 | | **MES 개발** | `projects/mes/README.md` | MES 프로젝트 개요 | --- @@ -33,27 +30,67 @@ ``` docs/ -├── plans/ # 🆕 개발 계획 - 임시 (작업 완료 후 정리 → 삭제) -├── standards/ # 개발 표준 - "어떻게 코드를 작성할 것인가" -├── architecture/ # 아키텍처 - "왜 이렇게 설계하는가" -├── rules/ # 비즈니스 규칙 - "무엇이 유효한 데이터인가" -├── specs/ # 기술 스펙 - "무엇을 구현할 것인가" -├── guides/ # 구현 가이드 - "어떻게 구현할 것인가" -├── quickstart/ # 빠른 시작 - 핵심 요약 -├── front/ # 프론트엔드 공유 문서 -├── features/ # 기능별 상세 문서 -├── projects/ # 프로젝트별 문서 (MES, Legacy) -├── history/ # 히스토리 및 로드맵 -├── contracts/ # 전자계약서 버전 관리 -├── changes/ # 변경 이력 -└── data/ # 데이터 분석 +├── system/ # 시스템 현황 — 아키텍처, DB 스키마, 인프라 (architecture/ + specs/ 통합) +├── standards/ # 개발 표준 — "어떻게 코드를 작성할 것인가" +├── rules/ # 비즈니스 규칙 — "무엇이 유효한 데이터인가" +├── features/ # 기능별 상세 — 도메인별 기능 문서 +├── guides/ # 구현 가이드 — "어떻게 구현할 것인가" +├── quickstart/ # 빠른 시작 — 핵심 요약, 명령어 +├── plans/ # 작업 추적 — 예정 → 진행 → 완료 → archive/ +├── projects/ # 프로젝트 자료 — 프로젝트성 분석, 설계, 참고 +├── deploys/ # 운영 매뉴얼 — 서버 운영, 배포 +├── changes/ # 변경 이력 +├── data/ # 데이터 분석 +├── history/ # 히스토리 기록 +├── api/ # API 통합 문서 +├── requests/ # 요청/기획 문서 +└── assets/ # BI 등 정적 자산 ``` --- ## 📚 폴더별 문서 목록 -### standards/ - 개발 표준 +### system/ — 시스템 현황 +> 아키텍처, DB 스키마, 기술 스펙, 인프라 (기존 architecture/ + specs/ 통합) + +| 문서 | 설명 | +|------|------| +| [overview.md](system/overview.md) | 전체 시스템 아키텍처 (api/react/mng 구조, 기술 스택) | +| [api-structure.md](system/api-structure.md) | API 서버 구조 (~1,027 엔드포인트, 18 도메인) | +| [react-structure.md](system/react-structure.md) | React 프론트엔드 구조 (249 페이지, 612 컴포넌트) | +| [mng-structure.md](system/mng-structure.md) | MNG 관리자 패널 구조 (171 컨트롤러, 436 뷰) | +| [docker-setup.md](system/docker-setup.md) | Docker 환경 + CI/CD (7 서비스, Jenkins) | +| [database/README.md](system/database/README.md) | DB 스키마 인덱스 (220 모델, 32 도메인, 459 마이그레이션) | + +**DB 도메인별 스키마:** + +| 문서 | 포함 도메인 | +|------|-----------| +| [database/tenants.md](system/database/tenants.md) | 테넌트, 사용자, 권한 (63 모델) | +| [database/products.md](system/database/products.md) | 제품, 품목, 설계 (21 모델) | +| [database/sales.md](system/database/sales.md) | 영업, 수주, 견적 (18 모델) | +| [database/production.md](system/database/production.md) | 생산, 시공, 자재, 품질 (20 모델) | +| [database/finance.md](system/database/finance.md) | 재무, 회계 | +| [database/hr.md](system/database/hr.md) | 인사, 면접 | +| [database/documents.md](system/database/documents.md) | 문서, 전자서명 (19 모델) | +| [database/commons.md](system/database/commons.md) | 공통, 게시판, 감사 (17 모델) | +| [database/stats.md](system/database/stats.md) | 통계 (21 모델, sam_stat DB) | + +**이관 완료 (architecture/ + specs/ → system/):** + +| 문서 | 설명 | +|------|------| +| [security-policy.md](system/security-policy.md) | 보안 정책 (다층 방어, Sanctum, RBAC) | +| [scaling-roadmap.md](system/scaling-roadmap.md) | 10K 테넌트 스케일링 로드맵 | +| [board-system-spec.md](system/board-system-spec.md) | 게시판 시스템 설계 스펙 | +| [item-master-integration.md](system/item-master-integration.md) | 품목 마스터 통합 설계 | +| [remote-work-setup.md](system/remote-work-setup.md) | 원격 개발 설정 (DEPRECATED) | +| [erp-analysis/](system/erp-analysis/) | ERP 스토리보드 분석 (9개 파일) | + +--- + +### standards/ — 개발 표준 > 코딩 컨벤션, 스타일 가이드, 품질 기준 | 문서 | 설명 | 필수 확인 시점 | @@ -61,40 +98,56 @@ docs/ | [api-rules.md](standards/api-rules.md) | API 개발 규칙 (Service-First, FormRequest, i18n) | API 개발 전 | | [git-conventions.md](standards/git-conventions.md) | Git 커밋 메시지, 브랜치 전략 | 커밋 전 | | [quality-checklist.md](standards/quality-checklist.md) | 코드 품질 체크리스트 | PR 전 | +| [pagination-policy.md](standards/pagination-policy.md) | 페이지네이션 표준 | 목록 API 구현 시 | +| [options-column-policy.md](standards/options-column-policy.md) | JSON options 컬럼 표준 정책 (마이그레이션, 모델, 쿼리) | 테이블 생성/확장 시 | -### architecture/ - 아키텍처 & 설계 원칙 -> 시스템 설계, 보안 정책, 아키텍처 결정 +--- -| 문서 | 설명 | 필수 확인 시점 | -|------|------|--------------| -| [system-overview.md](architecture/system-overview.md) | 전체 시스템 아키텍처 | 새 기능 설계 전 | -| [security-policy.md](architecture/security-policy.md) | 인증/인가, 보안 규칙 | 보안 관련 작업 전 | -| [scaling-roadmap-10k-tenants.md](architecture/scaling-roadmap-10k-tenants.md) | 10,000 테넌트 스케일링 로드맵 | 확장 전략 검토 시 | - -### rules/ - 비즈니스 규칙 -> 도메인 로직, 검증 규칙, 상태 전이 +### rules/ — 비즈니스 규칙 +> 도메인 로직, 검증 규칙, 정책 | 문서 | 설명 | 필수 확인 시점 | |------|------|--------------| | [README.md](rules/README.md) | 비즈니스 규칙 개요 | 도메인 로직 구현 전 | -| [item-policy.md](rules/item-policy.md) | 품목 정책 (유형 체계, 예약어, API 규칙) | 품목 관련 작업 전 | -| [pricing-policy.md](rules/pricing-policy.md) | 단가 정책 (원가/판매가 계산, 리비전 관리) | 단가 관련 작업 전 | +| [item-policy.md](rules/item-policy.md) | 품목 정책 (유형, 예약어, API 규칙) | 품목 관련 작업 전 | +| [pricing-policy.md](rules/pricing-policy.md) | 단가 정책 (원가/판매가, 리비전) | 단가 관련 작업 전 | | [customer-pricing.md](rules/customer-pricing.md) | 고객 안내용 서비스 요금표 | 고객 요금 안내 시 | | [partner-commission.md](rules/partner-commission.md) | 영업파트너 수당 체계 및 정산 | 수당/정산 관련 작업 전 | | [billing-policy.md](rules/billing-policy.md) | 내부용 원가/마진/코드참조 (CONFIDENTIAL) | 과금 코드 개발 전 | +| [client-policy.md](rules/client-policy.md) | 고객사 관리 정책 | 고객 관련 작업 전 | +| [attendance-api.md](rules/attendance-api.md) | 근태 API 규칙 | 근태 관련 작업 전 | +| [department-tree-api.md](rules/department-tree-api.md) | 부서 트리 API 규칙 | 부서 관련 작업 전 | +| [employee-api.md](rules/employee-api.md) | 직원 API 규칙 | 직원 관련 작업 전 | +| [numbering-rules.md](rules/numbering-rules.md) | 채번규칙 (패턴 기반 자동 번호 생성) | 채번 로직 수정 전 | -### specs/ - 기술 스펙 -> 구현 명세, DB 스키마, 시스템 설정 +--- -| 문서 | 설명 | 필수 확인 시점 | -|------|------|--------------| -| [database-schema.md](specs/database-schema.md) | DB 구조 및 관계도 | DB 변경 전 | -| [board-system-spec.md](specs/board-system-spec.md) | 게시판 시스템 설계 | 게시판 작업 전 | -| [item-master-integration.md](specs/item-master-integration.md) | 품목관리 연동 설계 | 품목 연동 구현 시 | -| [docker-setup.md](specs/docker-setup.md) | Docker 환경 구성 | 환경 설정 시 | -| [remote-work-setup.md](specs/remote-work-setup.md) | 원격 개발 설정 | 원격 작업 시 | +### features/ — 기능별 문서 +> 도메인별 기능 상세 (기능 설명 + 엔드포인트 경로 + Swagger 참조) -### guides/ - 구현 가이드 +| 문서 | 설명 | +|------|------| +| [quotes/README.md](features/quotes/README.md) | 견적 시스템 (BOM 계산, 10단계 로직) | +| [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 | +| [boards/mng-implementation.md](features/boards/mng-implementation.md) | MNG 게시판 구현 상세 | +| [hr/attendance-management-spec.md](features/hr/attendance-management-spec.md) | 근태관리 기획서 | +| [hr/hr-api-analysis.md](features/hr/hr-api-analysis.md) | HR API 분석 (근태/직원/부서) | +| [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 + 세금계산서 연동 | +| ~~business-card-request.md~~ | 명함신청 관리 (DB 마이그레이션만 존재, 문서 미작성) | +| [sales/README.md](features/sales/README.md) | 영업 관리 (면접 시나리오 포함) | +| [crm/README.md](features/crm/README.md) | CRM (거래처, 미수금, 미지급금) | +| [finance/README.md](features/finance/README.md) | 재무 관리 (14개 하위 문서) | +| [card-vehicle/README.md](features/card-vehicle/README.md) | 법인카드·차량 관리 | +| [settlement/README.md](features/settlement/README.md) | 정산 관리 | +| [esign/README.md](features/esign/README.md) | 전자서명 (계약·OTP·PDF 합성) | +| [documents/README.md](features/documents/README.md) | 문서관리 (EAV 기반 서식·결재) | +| [ai/README.md](features/ai/README.md) | AI 분석 리포트 (Gemini 연동) | +| [equipment/README.md](features/equipment/README.md) | 설비관리 (MNG 전용) | +| [approvals/README.md](features/approvals/README.md) | 결재관리 시스템 (순차결재, 보류/전결/참조/복사재기안) | + +--- + +### guides/ — 구현 가이드 > 특정 기능 구현을 위한 단계별 매뉴얼 | 문서 | 설명 | 필수 확인 시점 | @@ -103,35 +156,75 @@ docs/ | [file-storage-guide.md](guides/file-storage-guide.md) | 파일 업로드/다운로드 구현 | 파일 기능 구현 전 | | [item-management-migration.md](guides/item-management-migration.md) | Item 시스템 전환 가이드 | 마이그레이션 작업 전 | | [project-launch-roadmap.md](guides/project-launch-roadmap.md) | 런칭 준비 현황 | 런칭 관련 작업 시 | -| [production-env-sync.md](guides/production-env-sync.md) | 운영 전환 시 .env 동기화 절차 | 테스트→운영 전환 시 | -| [server-how-it-works.md](guides/server-how-it-works.md) | 서버 인프라 시리즈 ① 서버 동작 원리 | 신규 합류 시 | -| [nginx-fastcgi-guide.md](guides/nginx-fastcgi-guide.md) | 서버 인프라 시리즈 ② Nginx & FastCGI | Nginx/FastCGI 개념 이해 시 | -| [php-fpm-guide.md](guides/php-fpm-guide.md) | 서버 인프라 시리즈 ③ PHP-FPM | PHP-FPM 개념 이해 시 | -| [jenkins-setup-guide.md](guides/jenkins-setup-guide.md) | Jenkins CI/CD 셋업 가이드 | Jenkins 설치/설정 시 | +| [production-env-sync.md](guides/production-env-sync.md) | 운영 전환 시 .env 동기화 | 테스트→운영 전환 시 | +| [server-how-it-works.md](guides/server-how-it-works.md) | 서버 동작 원리 | 신규 합류 시 | +| [nginx-fastcgi-guide.md](guides/nginx-fastcgi-guide.md) | Nginx & FastCGI 가이드 | 서버 이해 시 | +| [php-fpm-guide.md](guides/php-fpm-guide.md) | PHP-FPM 가이드 | 서버 이해 시 | +| [jenkins-setup-guide.md](guides/jenkins-setup-guide.md) | Jenkins CI/CD 셋업 | Jenkins 설치/설정 시 | +| [auto-login-guide.md](guides/auto-login-guide.md) | MNG→DEV 자동 로그인 | 자동 로그인 구현 시 | +| [erp-api-list.md](guides/erp-api-list.md) | ERP API 목록 (List vs Detail 구분) | 프론트 API 연동 시 | +| [erp-api-detail.md](guides/erp-api-detail.md) | ERP API 상세 스펙 | 프론트 API 연동 시 | +| [item-master-guide.md](guides/item-master-guide.md) | 품목기준관리 페이지-섹션-필드 구조 | 품목 UI 구현 시 | +| [item-master-items-api.md](guides/item-master-items-api.md) | ItemMaster & Items API 문서 | 품목 API 연동 시 | -### quickstart/ - 빠른 시작 +--- + +### quickstart/ — 빠른 시작 > 핵심 규칙 요약, 자주 쓰는 명령어 -| 문서 | 설명 | 필수 확인 시점 | -|------|------|--------------| -| [quick-start.md](quickstart/quick-start.md) | 프로젝트 핵심 규칙 요약 | 세션 시작 시 | -| [dev-commands.md](quickstart/dev-commands.md) | 일상 개발 명령어 모음 | 명령어 확인 시 | - -### front/ - 프론트엔드 공유 문서 -> API 연동 가이드, 프론트엔드 스펙 - | 문서 | 설명 | |------|------| -| [item-master-guide.md](front/item-master-guide.md) | 품목기준관리 페이지-섹션-필드 구조 | +| [quick-start.md](quickstart/quick-start.md) | 프로젝트 핵심 규칙 요약 | +| [dev-commands.md](quickstart/dev-commands.md) | 일상 개발 명령어 모음 | -> 날짜별 API 요청 문서는 `history/2025-11/front-requests/`로 이동됨 +--- -### data/ - 데이터 분석 -> 시스템 분석, 데이터 모델링 +### plans/ — 작업 추적 +> 예정 → 진행 → 완료 → archive/ (이미 정리 완료, 현행 유지) + +| 문서 | 설명 | +|------|------| +| [index_plans.md](plans/index_plans.md) | 계획 인덱스 (ACTIVE + PLANNED) | +| [GUIDE.md](plans/GUIDE.md) | 계획 문서 작성 가이드 | + +--- + +### projects/ — 프로젝트 자료 +> 프로젝트성 분석, 설계, 참고 자료 (지속 보관) + +| 프로젝트 | 문서 | 설명 | +|---------|------|------| +| [index_projects.md](projects/index_projects.md) | 프로젝트 인덱스 | | +| **MES** | [README.md](projects/mes/README.md) | MES 프로젝트 개요 | +| **MES** | [MES_PROJECT_ROADMAP.md](projects/mes/MES_PROJECT_ROADMAP.md) | 개발 로드맵 | +| **5130 이관** | [MASTER_PLAN.md](projects/5130-migration/MASTER_PLAN.md) | 레거시 이관 마스터 플랜 | +| **API 연동** | [MASTER_PLAN.md](projects/api-integration/MASTER_PLAN.md) | React↔API 연동 | +| **Legacy** | [draw-module.md](projects/legacy-5130/draw-module.md) | 레거시 드로우 모듈 | +| **견적** | [quotation/](projects/quotation/) | 견적 프로젝트 자료 | +| **전자서명** | [e-sign/](projects/e-sign/) | 전자서명 프로젝트 자료 | + +--- + +### deploys/ — 운영 매뉴얼 +> 서버 운영, 배포 (현행 유지) + +| 문서 | 설명 | +|------|------| +| [ops-manual/README.md](deploys/ops-manual/README.md) | 서버 운영 매뉴얼 (11부 구성) | + +--- + +### changes/ — 변경 이력 +> 파일명 형식: `YYYYMMDD_description.md` + +--- + +### data/ — 데이터 분석 | 문서 | 설명 | |------|------| | [analysis/item-db-analysis.md](data/analysis/item-db-analysis.md) | Item DB/API 분석 최종본 | +| [analysis/bom-item-mapping-analysis.md](data/analysis/bom-item-mapping-analysis.md) | BOM-품목 매핑 분석 | ### contracts/ - 전자계약서 버전 관리 > DOCX 배포본 + Markdown 추적본 + 자동화 스크립트 @@ -157,13 +250,13 @@ docs/ | [production-deployment-plan.md](plans/production-deployment-plan.md) | 운영 환경 배포 계획 (CI/CD, 서버 아키텍처) | | [attendance-management-plan.md](plans/attendance-management-plan.md) | 근태현황 개발 계획 (Phase 1~2, HTMX 기반) | | [leave-management-plan.md](plans/leave-management-plan.md) | 휴가관리 모듈 개발 계획 (연차 발생/신청/승인/정책) | +| [approval-management-system-plan.md](plans/approval-management-system-plan.md) | 결재관리 시스템 기획서 (전자결재 전체 설계: 기안~회수, DB 설계, 17개 양식, 4 Phase) | ### features/ - 기능별 문서 | 문서 | 설명 | |------|------| | [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 (알림톡/친구톡) 연동 | -| [barobill-kakaotalk/esign-notification-guide.md](features/barobill-kakaotalk/esign-notification-guide.md) | 전자계약 알림톡/SMS 환경별 설정 가이드 | | [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 | | [boards/mng-implementation.md](features/boards/mng-implementation.md) | MNG 게시판 구현 상세 | | [hr/attendance-management-spec.md](features/hr/attendance-management-spec.md) | 근태관리 기획서 (화면/데이터/비즈니스규칙/API) | @@ -171,6 +264,10 @@ docs/ | [quotes/README.md](features/quotes/README.md) | 견적 시스템 분석 (BOM 계산, 10단계 로직) | | [business-card-request.md](features/business-card-request.md) | 명함신청 관리 (3단계 워크플로우: 요청→제작의뢰→처리완료) | | [academy/fire-shutter-image-prompts.md](features/academy/fire-shutter-image-prompts.md) | 방화셔터 백과사전 이미지 생성 프롬프트 (Gemini용) | +| [approvals/README.md](features/approvals/README.md) | 결재관리 시스템 개요 (아키텍처, DB, 상태관리, 권한) | +| [approvals/workflows.md](features/approvals/workflows.md) | 결재관리 워크플로우 상세 (승인/반려/회수/보류/전결/복사재기안) | +| [approvals/api-reference.md](features/approvals/api-reference.md) | 결재관리 API 명세 (20개 엔드포인트) | +| [approvals/ui-screens.md](features/approvals/ui-screens.md) | 결재관리 UI 화면 구성 (Blade + HTMX) | ### projects/ - 프로젝트별 문서 @@ -190,89 +287,112 @@ docs/ --- -## 🏗️ 서브프로젝트 문서 +### 서브프로젝트 문서 각 서브프로젝트는 독립적인 `docs/` 디렉토리를 가집니다. | 프로젝트 | 문서 경로 | 설명 | |---------|----------|------| -| **API** | [api/docs/INDEX.md](../api/docs/INDEX.md) | REST API 프로젝트 | -| **MNG** | [mng/docs/INDEX.md](../mng/docs/INDEX.md) | Plain Laravel 관리자 (운영 주력) | +| **API** | [api/docs/](../api/docs/) | REST API 프로젝트 | +| **MNG** | [mng/docs/](../mng/docs/) | Plain Laravel 관리자 | | **React** | [react/docs/](../react/docs/) | Next.js 프론트엔드 | --- -## 📝 문서 작성 가이드 - -### 새 문서 작성 시 -1. **적절한 폴더 선택**: 위 폴더 구조 참고 -2. **파일명**: 소문자 + 하이픈 (kebab-case) -3. **크기 목표**: 10KB 이하 -4. **INDEX 업데이트**: 새 문서는 반드시 이 파일에 추가 +## 📝 문서 작성 규칙 ### 폴더 선택 기준 -- **"개발 계획/작업 예정"** → `plans/` (임시, 완료 후 삭제) -- **"어떻게 코드 작성?"** → `standards/` -- **"왜 이렇게 설계?"** → `architecture/` -- **"무엇이 유효한 데이터?"** → `rules/` -- **"무엇을 구현?"** → `specs/` -- **"어떻게 구현?"** → `guides/` -### plans/ 워크플로우 -1. 개발 계획 문서를 `plans/`에 작성 -2. 작업 진행 -3. 완료 후 결과물을 해당 프로젝트 docs에 정리 -4. plan 문서 삭제 +| 질문 | 폴더 | +|------|------| +| "시스템이 현재 어떤 상태인가?" | `system/` | +| "어떻게 코드를 작성할 것인가?" | `standards/` | +| "무엇이 유효한 데이터인가?" | `rules/` | +| "이 기능은 어떻게 동작하는가?" | `features/` | +| "어떻게 구현할 것인가?" | `guides/` | +| "무슨 작업을 할 것인가?" | `plans/` | +| "프로젝트 자료를 보관하고 싶다" | `projects/` | +| "무엇이 변경되었는가?" | `changes/` | -### plans/flow-tests/ -API Flow Tester에서 생성되는 JSON 파일 저장 경로 -- 경로: `plans/flow-tests/*.json` -- 용도: MNG API Flow Tester 테스트 시나리오 -- 예시: `item-master-page-api-flow.json`, `client-api-flow.json` +### 파일명 규칙 + +| 유형 | 규칙 | 예시 | +|------|------|------| +| 기술 문서 (코드 참조) | 영문 kebab-case | `api-rules.md`, `database-schema.md` | +| 업무/비즈니스 문서 | 한글 허용 | `영업파트너가이드북.md`, `수당지급.md` | +| 변경 이력 | `YYYYMMDD_description.md` | `20260205_sus_inspection_template.md` | +| 폴더 인덱스 | `README.md` (대문자) | `features/finance/README.md` | +| **혼용 금지** | 한글+영문 섞지 않음 | ❌ `영업partner가이드.md` | + +### 크기 제한 +- **목표**: 10KB 이하 +- 초과 시 도메인별로 분할 + +### 문서 구조 템플릿 + +#### 정책/규칙 문서 (`rules/`, `standards/`) + +```markdown +# 제목 + +> **작성일**: YYYY-MM-DD +> **상태**: 설계 확정 --- -## 🔄 문서 구조 변경 이력 +## 1. 개요 +## 2. 핵심 원칙 +## 3. 상세 규칙 +## 4. API 엔드포인트 (해당 시) +## 관련 문서 -- **2026-01-28**: API 라우터 분리 및 버전 폴백 시스템 구현 - - `routes/api.php` → 13개 도메인별 파일로 분리 (1,479줄 → 61줄) - - `ApiVersionMiddleware` 추가 (헤더/쿼리 기반 버전 선택, v2→v1 폴백) - - `standards/api-rules.md` 라우팅 섹션 업데이트 - - `architecture/system-overview.md` 라우팅 구조 업데이트 +--- -- **2025-12-09**: 품목 정책 통합 문서 생성 - - `rules/item-policy.md` 생성 (4개 문서 통합) - - 삭제: `specs/ITEM-MASTER-INDEX.md`, `specs/item-master-field-key-validation.md`, `specs/item-master-field-integration.md`, `plans/items-api-unified-plan.md` - - 품목 관련 정책을 rules/ 디렉토리로 이동 +**최종 업데이트**: YYYY-MM-DD +``` -- **2025-12-09**: Item Master 문서 정리 및 인덱스 생성 - - `specs/ITEM-MASTER-INDEX.md` 생성 (개발 현황/필요 항목 정리) - - `history/2025-11/item-master-archived/` 생성 (구버전 문서 아카이브) - - 중복 문서 정리 (front-requests → history 이동) +#### 변경 이력 문서 (`changes/`) -- **2025-12-09**: 문서 정리 및 통합 - - 중복 분석 문서 삭제 (v2, DB_Modeling) - - `SAM_Item_DB_API_Analysis_v3_FINAL.md` → `item-db-analysis.md` 리네임 - - `ITEM_MASTER_FIELD_INTEGRATION_PLAN.md` → `item-master-field-integration.md` 리네임 - - `HR_API_ANALYSIS.md` → `features/hr/hr-api-analysis.md` 이동 - - 날짜 접두사 front 문서 → `history/2025-11/front-requests/` 이동 - - api/docs에서 프로젝트 문서 분리 (swagger, api-flows만 유지) +```markdown +# 변경 내용 요약 -- **2025-12-09**: api/docs 문서 통합 - - `api/docs/analysis/` → `docs/data/analysis/` 이동 - - `api/docs/front/` → `docs/front/` 병합 - - `api/docs/specs/` → `docs/specs/` 병합 - - api/docs에는 API 구성/설정 문서만 유지 (swagger, api-flows) +**날짜:** YYYY-MM-DD -- **2025-12-09**: `plans/` 폴더 추가 - - 개발 계획 문서용 임시 폴더 - - 작업 완료 후 정리 → 삭제 워크플로우 +## 변경 개요 +## 수정된 파일 +## 상세 변경 사항 +## 테스트 체크리스트 +``` -- **2025-12-05**: 폴더 구조 대폭 재정리 - - `reference/` → `standards/`, `architecture/`, `quickstart/`로 분리 - - `principles/` → `architecture/`로 통합 - - 작업별 필수 문서 가이드 추가 +### 작성 스타일 -- **2025-11-20**: 문서 구조 대규모 재정리 - - claudedocs → docs/ 체계화 - - 각 서브프로젝트별 docs/ 디렉토리 생성 \ No newline at end of file +| 항목 | 규칙 | +|------|------| +| **언어** | 한글 기본, 코드/경로/기술 식별자만 영어 | +| **어조** | 서술형 ("X 한다") | +| **경고** | `> **경고: ...**` 블록인용 | +| **금지/필수** | `❌` 금지, `✅` 필수 | +| **우선순위** | `🔴 필수`, `🟡 중요`, `🟢 권장` | +| **코드 블록** | 반드시 언어 지정 (```php, ```bash 등) | +| **인라인 코드** | 파일 경로, 메서드명, 변수명에 백틱 | +| **구분선** | `---` 주요 섹션 사이 | + +### 새 문서 작성 시 체크리스트 +- [ ] 적절한 폴더에 배치 +- [ ] 파일명 규칙 준수 +- [ ] 문서 구조 템플릿 준수 +- [ ] 이 INDEX.md에 등록 + +--- + +## 🔄 문서 정비 진행 현황 + +> 참조: [docs-comprehensive-update-plan.md](plans/docs-comprehensive-update-plan.md) + +| Phase | 작업 | 상태 | +|-------|------|------| +| **Phase 0** | 문서 정책 재정립 | ✅ 완료 | +| **Phase 1** | 시스템 현황 문서화 (DB, API, React, MNG, Docker) | ✅ 완료 (14개 문서) | +| **Phase 2** | 기존 문서 정비 (architecture/+specs/ → system/ 이관) | ⏳ 대기 | +| **Phase 3** | 신규 도메인 기능 문서 작성 | ⏳ 대기 | +| **Phase 4** | 최종 검증 및 INDEX 갱신 | ⏳ 대기 | \ No newline at end of file diff --git a/sam/docs/features/approvals/README.md b/sam/docs/features/approvals/README.md new file mode 100644 index 0000000..7485ffc --- /dev/null +++ b/sam/docs/features/approvals/README.md @@ -0,0 +1,295 @@ +# 결재관리 시스템 + +> **작성일**: 2026-02-28 +> **상태**: Phase 2 구현 완료 +> **프로젝트**: SAM MNG (관리자 웹) +> **우선순위**: 🔴 필수 + +--- + +## 1. 개요 + +### 1.1 목적 + +SAM MNG 전자결재 시스템. 기안부터 최종 승인, 반려, 회수, 보류, 전결, 참조까지 기업 결재 프로세스를 디지털화한다. + +### 1.2 문서 구조 + +| 문서 | 설명 | +|------|------| +| **README.md** (이 문서) | 시스템 전체 개요, 아키텍처, 상태 관리 | +| [workflows.md](workflows.md) | 상세 워크플로우 (승인/반려/회수/보류/전결/복사재기안) | +| [api-reference.md](api-reference.md) | API 엔드포인트 명세 | +| [ui-screens.md](ui-screens.md) | 화면별 UI 구성 및 동작 | + +### 1.3 구현 현황 + +| Phase | 범위 | 상태 | +|-------|------|------| +| **Phase 1** | 순차결재, 기안/상신/승인/반려/회수 | ✅ 완료 | +| **Phase 2** | 보류/해제, 전결, 참조 열람 추적, 복사 재기안 | ✅ 완료 | +| **Phase 3** | 병렬결재, 위임(대결), 알림 | 미착수 | +| **Phase 4** | ERP 연동, 결재 통계, 관리자 설정 | 미착수 | + +--- + +## 2. 아키텍처 + +### 2.1 기술 스택 + +| 계층 | 기술 | 설명 | +|------|------|------| +| 뷰 | Blade + HTMX + Alpine.js | 동적 UI, 부분 렌더링 | +| API | Laravel Controller + Service | JSON API (내부용) | +| 모델 | Eloquent ORM | Multi-tenant 스코프 | +| DB | MySQL 8.0 | API 프로젝트에서 마이그레이션 관리 | + +### 2.2 프로젝트 분리 + +``` +API (/home/aweso/sam/api) +├── database/migrations/ ← 모든 결재 테이블 마이그레이션 + +MNG (/home/aweso/sam/mng) +├── app/Models/Approvals/ ← 모델 (Approval, ApprovalStep, ApprovalForm, ApprovalLine, ApprovalDelegation) +├── app/Services/ ← ApprovalService (비즈니스 로직) +├── app/Http/Controllers/ ← ApprovalController (웹), ApprovalApiController (API) +├── resources/views/approvals/ ← Blade 뷰 +└── routes/ ← 웹 라우트 + API 라우트 +``` + +### 2.3 핵심 클래스 + +``` +ApprovalService +├── 목록 조회: getMyDrafts(), getPendingForMe(), getCompletedByMe(), getReferencesForMe() +├── CRUD: createApproval(), updateApproval(), deleteApproval(), getApproval() +├── 워크플로우: submit(), approve(), reject(), cancel(), hold(), releaseHold(), preDecide(), copyForRedraft() +├── 참조: markAsRead() +└── 유틸: getBadgeCounts(), getApprovalLines(), getApprovalForms(), saveApprovalSteps() +``` + +--- + +## 3. 데이터베이스 + +### 3.1 테이블 관계 + +``` +approval_forms (결재 양식) + │ 1:N + ▼ +approvals (결재 문서) + │ 1:N │ N:1 (self) + ▼ ▼ +approval_steps (결재 단계) approvals (parent_doc_id → 원본 문서) + +approval_lines (결재선 템플릿) ← approvals.line_id 참조 + +approval_delegations (위임 설정) ← Phase 3 준비 +``` + +### 3.2 approvals (결재 문서) + +| 컬럼 | 타입 | 설명 | +|------|------|------| +| `id` | BIGINT PK | | +| `tenant_id` | BIGINT | 테넌트 격리 | +| `document_number` | VARCHAR | `APR-YYMMDD-001` 형식 | +| `form_id` | BIGINT FK | 양식 | +| `line_id` | BIGINT FK NULL | 결재선 템플릿 | +| `title` | VARCHAR(200) | 제목 | +| `content` | JSON | 양식 필드 데이터 | +| `body` | TEXT NULL | 본문 | +| `status` | VARCHAR(20) | 문서 상태 (6가지) | +| `is_urgent` | BOOLEAN | 긴급 여부 | +| `drafter_id` | BIGINT FK | 기안자 | +| `department_id` | BIGINT FK NULL | 기안 부서 | +| `current_step` | INT | 현재 결재 단계 번호 | +| `drafted_at` | TIMESTAMP NULL | 상신 일시 | +| `completed_at` | TIMESTAMP NULL | 완료 일시 | +| `recall_reason` | TEXT NULL | 회수 사유 | +| `parent_doc_id` | BIGINT FK NULL | 재기안 원본 문서 | +| `attachments` | JSON NULL | 첨부파일 | + +### 3.3 approval_steps (결재 단계) + +| 컬럼 | 타입 | 설명 | +|------|------|------| +| `id` | BIGINT PK | | +| `approval_id` | BIGINT FK | 결재 문서 | +| `step_order` | INT | 순서 (1, 2, 3...) | +| `step_type` | VARCHAR | `approval`, `agreement`, `reference` | +| `parallel_group` | INT NULL | 병렬 그룹 (Phase 3) | +| `approver_id` | BIGINT FK | 결재자 | +| `acted_by` | BIGINT FK NULL | 실제 처리자 (대결 시) | +| `approver_name` | VARCHAR | 결재자명 스냅샷 | +| `approver_department` | VARCHAR | 부서 스냅샷 | +| `approver_position` | VARCHAR | 직급 스냅샷 | +| `status` | VARCHAR(20) | 단계 상태 (5가지) | +| `approval_type` | VARCHAR(20) | `normal`, `pre_decided`, `delegated` | +| `comment` | TEXT NULL | 결재 의견 | +| `acted_at` | TIMESTAMP NULL | 처리 일시 | +| `is_read` | BOOLEAN | 참조 열람 여부 | +| `read_at` | TIMESTAMP NULL | 열람 일시 | + +### 3.4 approval_delegations (위임 설정, Phase 3) + +| 컬럼 | 타입 | 설명 | +|------|------|------| +| `id` | BIGINT PK | | +| `tenant_id` | BIGINT FK | | +| `delegator_id` | BIGINT FK | 위임자 | +| `delegate_id` | BIGINT FK | 대리인 | +| `start_date` | DATE | 위임 시작일 | +| `end_date` | DATE | 위임 종료일 | +| `form_ids` | JSON NULL | 대상 양식 (NULL=전체) | +| `notify_delegator` | BOOLEAN | 대결 시 보고 여부 | +| `is_active` | BOOLEAN | 활성 여부 | +| `reason` | VARCHAR(200) | 위임 사유 | + +--- + +## 4. 상태 관리 + +### 4.1 문서 상태 (6가지) + +| 상태 | 코드 | 라벨 | 색상 | 설명 | +|------|------|------|------|------| +| 임시저장 | `draft` | 임시저장 | gray | 작성 중, 미상신 | +| 진행 | `pending` | 진행 | blue | 결재선 순환 중 | +| 완료 | `approved` | 완료 | green | 최종 승인 | +| 반려 | `rejected` | 반려 | red | 결재자가 반려 | +| 회수 | `cancelled` | 회수 | yellow | 기안자가 회수 | +| 보류 | `on_hold` | 보류 | amber | 결재자가 보류 | + +### 4.2 단계 상태 (5가지) + +| 상태 | 코드 | 라벨 | 아이콘 | 설명 | +|------|------|------|--------|------| +| 대기 | `pending` | 대기 | 숫자 | 차례 아직 아님 | +| 승인 | `approved` | 승인 | ✓ (녹색) | 승인 완료 | +| 반려 | `rejected` | 반려 | ✗ (적색) | 반려 | +| 건너뜀 | `skipped` | 건너뜀 | — (회색) | 전결/회수로 소멸 | +| 보류 | `on_hold` | 보류 | ⏸ (노란) | 보류 중 | + +### 4.3 결재 유형 (approval_type) + +| 유형 | 코드 | 아이콘 | 설명 | +|------|------|--------|------| +| 일반결재 | `normal` | ✓ | 기본 승인 | +| 전결 | `pre_decided` | ⚡ (남색) | 이후 단계 모두 건너뛰고 즉시 완료 | +| 대결 | `delegated` | — | 대리인이 처리 (Phase 3) | + +### 4.4 참여자 역할 (step_type) + +| 역할 | 코드 | 의사결정 | 설명 | +|------|------|---------|------| +| 결재 | `approval` | ✅ 있음 | 승인/반려/보류/전결 가능 | +| 합의 | `agreement` | ✅ 있음 | 타부서 동의 (승인/반려 가능) | +| 참조 | `reference` | ❌ 없음 | 열람만 가능, 열람 추적 | + +### 4.5 상태 전이 다이어그램 + +``` + ┌─────────────────────────────┐ + │ │ + ┌────────┐ submit() │ ┌─────────┐ │ + │ draft │────────────→│ │ pending │ │ + └────────┘ │ └────┬────┘ │ + ▲ │ │ │ + │ │ ┌────┼─────────┬───────┐ │ + │ (수정 후 재상신) │ │ │ │ │ │ + │ │ │ approve() reject() hold()│ + │ │ │ │ │ │ │ + │ │ │ ▼ ▼ ▼ │ + │ │ │ 다음 step rejected on_hold│ + │ │ │ 또는 │ │ │ + │ │ │ approved │ releaseHold() + │ │ │ │ │ │ │ + │ │ │ │ │ │ │ + │ │ └────┼────────┼───────┘ │ + │ │ │ │ │ + │ │ preDecide() │ │ + │ │ → approved │ │ + │ │ │ │ cancel() │ + │ │ │ │ │ │ + │ │ ▼ │ ▼ │ + │ │ ┌─────────┐ │ ┌──────────┐ + │ │ │approved │ │ │cancelled │ + │ │ └─────────┘ │ └──────────┘ + │ │ │ │ │ + │ │ │ │ │ + │ │ copyForRedraft() │ + │ │ │ │ │ + └───────────────────┼───────┴────────┘ │ + (새 draft 생성) │ │ + │ copyForRedraft() │ + │◀──────────────────────┘ + └─────────────────────────────┘ +``` + +--- + +## 5. 권한 매트릭스 + +### 5.1 누가 무엇을 할 수 있는가 + +| 액션 | 대상자 | 조건 | +|------|--------|------| +| **기안 작성** | 모든 사용자 | — | +| **수정** | 기안자 | `draft` 또는 `rejected` | +| **삭제** | 기안자 | `draft`만 | +| **상신** | 기안자 | `draft` 또는 `rejected`, 결재선 1명 이상 | +| **승인** | 현재 결재자 | `pending`, 자신이 현재 차례 | +| **반려** | 현재 결재자 | `pending`, 사유 필수 | +| **보류** | 현재 결재자 | `pending`, 사유 필수 | +| **보류 해제** | 보류한 결재자 | `on_hold`, 자신이 보류한 건 | +| **전결** | 현재 결재자 | `pending`, 이후 모든 단계 건너뜀 | +| **회수** | 기안자 | `pending` 또는 `on_hold`, 첫 결재자 미처리 | +| **복사 재기안** | 기안자 | `approved`, `rejected`, `cancelled` | +| **참조 열람** | 참조자 | `reference` step 보유 | + +### 5.2 회수 가능 조건 상세 + +``` +회수(cancel) 가능 여부 판단: + +1. 문서 상태가 pending 또는 on_hold인가? → 아니면 불가 +2. 요청자가 기안자(drafter_id)인가? → 아니면 불가 +3. 첫 번째 결재자(approval/agreement)의 상태가 pending 또는 on_hold인가? + → 이미 approved/rejected이면 불가 (첫 결재자가 이미 처리) +``` + +--- + +## 6. 메뉴 구조 + +``` +결재관리 +├── 기안함 /approval-mgmt/drafts ← 내가 기안한 문서 +├── 결재 대기함 /approval-mgmt/pending ← 내가 결재해야 할 문서 +├── 처리 완료함 /approval-mgmt/completed ← 내가 결재한 문서 +└── 참조함 /approval-mgmt/references ← 참조 문서 (열람 추적) +``` + +### 추가 페이지 + +| URL | 설명 | +|-----|------| +| `/approval-mgmt/create` | 기안 작성 | +| `/approval-mgmt/{id}` | 상세 조회 | +| `/approval-mgmt/{id}/edit` | 기안 수정 | + +--- + +## 7. 관련 문서 + +- [결재관리 워크플로우 상세](workflows.md) — 각 동작의 상세 흐름 +- [API 명세](api-reference.md) — 엔드포인트 목록 및 요청/응답 예시 +- [UI 화면 구성](ui-screens.md) — 화면별 UI 요소 및 동작 +- [기획서 원본](../../plans/approval-management-system-plan.md) — Phase 1~4 전체 기획 + +--- + +**최종 업데이트**: 2026-02-28 diff --git a/sam/docs/features/approvals/api-reference.md b/sam/docs/features/approvals/api-reference.md new file mode 100644 index 0000000..b63e31b --- /dev/null +++ b/sam/docs/features/approvals/api-reference.md @@ -0,0 +1,594 @@ +# 결재관리 API 명세 + +> **작성일**: 2026-02-28 +> **상태**: Phase 2 구현 완료 +> **Base URL**: `/api/admin/approvals` +> **미들웨어**: `web`, `auth`, `hq.member` +> **관련**: [README.md](README.md) | [워크플로우](workflows.md) | [UI 화면](ui-screens.md) + +--- + +## 1. 개요 + +모든 API는 JSON 응답을 반환한다. 인증은 세션 기반이며, CSRF 토큰이 필요하다. + +### 1.1 공통 응답 형식 + +**성공:** + +```json +{ + "success": true, + "message": "처리 메시지", + "data": { ... } +} +``` + +**실패 (400):** + +```json +{ + "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 페이지네이션 형식 + +```json +{ + "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} +``` + +**응답:** + +```json +{ + "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:** + +```json +{ + "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):** + +```json +{ + "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` 상태에서만 삭제 가능 + +**응답:** + +```json +{ + "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:** + +```json +{ + "comment": "승인합니다." // 선택 +} +``` + +**응답:** `{ "success": true, "message": "승인되었습니다.", "data": {...} }` + +--- + +### 4.3 반려 + +``` +POST /api/admin/approvals/{id}/reject +``` + +> 현재 결재자가 반려한다. 사유 필수. + +**Request Body:** + +```json +{ + "comment": "예산 초과로 반려합니다." // 필수 +} +``` + +**Validation:** `comment` — required, string, max:1000 + +**응답:** `{ "success": true, "message": "반려되었습니다.", "data": {...} }` + +--- + +### 4.4 회수 + +``` +POST /api/admin/approvals/{id}/cancel +``` + +> 기안자가 `pending`/`on_hold` 문서를 회수한다. 첫 결재자 미처리 시에만 가능. + +**Request Body:** + +```json +{ + "recall_reason": "내용 수정 필요" // 선택 +} +``` + +**응답:** `{ "success": true, "message": "결재가 회수되었습니다.", "data": {...} }` + +--- + +### 4.5 보류 + +``` +POST /api/admin/approvals/{id}/hold +``` + +> 현재 결재자가 결재를 보류한다. 사유 필수. + +**Request Body:** + +```json +{ + "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:** + +```json +{ + "comment": "전결 처리합니다." // 선택 +} +``` + +**응답:** `{ "success": true, "message": "전결 처리되었습니다.", "data": {...} }` + +--- + +### 4.8 복사 재기안 + +``` +POST /api/admin/approvals/{id}/copy +``` + +> 기안자가 `approved`/`rejected`/`cancelled` 문서를 복사하여 새 draft를 생성한다. + +**Request Body:** 없음 + +**응답:** + +```json +{ + "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 +``` + +**응답:** + +```json +{ + "success": true, + "data": [ + { "id": 1, "name": "일반 결재선", "steps": [...] } + ] +} +``` + +--- + +### 5.2 양식 목록 + +``` +GET /api/admin/approvals/forms +``` + +**응답:** + +```json +{ + "success": true, + "data": [ + { "id": 1, "name": "휴가신청서", "is_active": true } + ] +} +``` + +--- + +### 5.3 미처리 건수 (뱃지) + +``` +GET /api/admin/approvals/badge-counts +``` + +**응답:** + +```json +{ + "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` | 열람 추적 | + +--- + +## 관련 문서 + +- [README.md](README.md) — 시스템 전체 개요 +- [워크플로우 상세](workflows.md) — 각 동작의 상세 흐름 +- [UI 화면 구성](ui-screens.md) — 화면별 동작 + +--- + +**최종 업데이트**: 2026-02-28 diff --git a/sam/docs/features/approvals/ui-screens.md b/sam/docs/features/approvals/ui-screens.md new file mode 100644 index 0000000..f81b9ae --- /dev/null +++ b/sam/docs/features/approvals/ui-screens.md @@ -0,0 +1,381 @@ +# 결재관리 UI 화면 구성 + +> **작성일**: 2026-02-28 +> **상태**: Phase 2 구현 완료 +> **기술**: Blade + HTMX + Alpine.js + Tailwind CSS +> **관련**: [README.md](README.md) | [워크플로우](workflows.md) | [API 명세](api-reference.md) + +--- + +## 1. 개요 + +결재관리 화면은 MNG(관리자 웹)에서 Blade 템플릿으로 구현되며, API 호출은 `fetch()`를 사용한다. + +### 1.1 파일 구조 + +``` +resources/views/approvals/ +├── drafts.blade.php ← 기안함 (목록) +├── pending.blade.php ← 결재 대기함 (목록) +├── completed.blade.php ← 처리 완료함 (목록) +├── references.blade.php ← 참조함 (목록) +├── create.blade.php ← 기안 작성 +├── edit.blade.php ← 기안 수정 +├── show.blade.php ← 상세 조회 + 결재 처리 +└── partials/ + ├── _status-badge.blade.php ← 상태 뱃지 컴포넌트 + └── _step-progress.blade.php ← 결재 단계 진행 표시 +``` + +--- + +## 2. 목록 화면 + +### 2.1 기안함 (`/approval-mgmt/drafts`) + +내가 기안한 모든 문서를 표시한다. + +**UI 구성:** + +``` +┌──────────────────────────────────────────────────────────┐ +│ 기안함 [+ 새 기안] │ +├──────────────────────────────────────────────────────────┤ +│ [검색] [상태 필터 ▼] [긴급만 □] [날짜 범위] │ +├──────────────────────────────────────────────────────────┤ +│ 문서번호 │ 제목 │ 양식 │ 상태 │ 기안일 │ +│ APR-260228-001│ 휴가 신청 │ 휴가서 │ 🟢완료 │ 02-28 │ +│ APR-260228-002│ 출장 보고 │ 출장서 │ 🔵진행 │ 02-28 │ +│ APR-260227-001│ 경비 청구 │ 경비서 │ ⬜임시 │ 02-27 │ +├──────────────────────────────────────────────────────────┤ +│ [◀ 이전] 1 / 3 [다음 ▶] │ +└──────────────────────────────────────────────────────────┘ +``` + +**상태 필터:** 전체, 임시저장, 진행, 완료, 반려, 회수, 보류 + +--- + +### 2.2 결재 대기함 (`/approval-mgmt/pending`) + +내가 현재 결재해야 할 문서를 표시한다. + +**UI 구성:** + +``` +┌──────────────────────────────────────────────────────────┐ +│ 결재 대기함 [뱃지: 3건] │ +├──────────────────────────────────────────────────────────┤ +│ 문서번호 │ 제목 │ 기안자 │ 양식 │ 상신일 │ +│ 🔴 APR-260..│ 긴급 승인 │ 홍길동 │ 구매서 │ 02-28 │ +│ APR-260..│ 휴가 신청 │ 김영희 │ 휴가서 │ 02-27 │ +└──────────────────────────────────────────────────────────┘ +``` + +> 긴급 문서는 🔴 아이콘과 함께 상단에 표시 + +--- + +### 2.3 참조함 (`/approval-mgmt/references`) + +내가 참조자로 지정된 문서를 표시한다. + +**UI 구성:** + +``` +┌──────────────────────────────────────────────────────────┐ +│ 참조함 │ +├──────────────────────────────────────────────────────────┤ +│ [전체] [미열람 (5)] [열람완료] │ +├──────────────────────────────────────────────────────────┤ +│ 문서번호 │ 제목 │ 기안자 │ 상태 │ 열람 │ +│ APR-260228-001│ 회의록 │ 박부장 │ 🟢완료 │ ❌미열람│ +│ APR-260227-003│ 인사발령 │ 이팀장 │ 🔵진행 │ ✅열람 │ +└──────────────────────────────────────────────────────────┘ +``` + +**열람 추적:** +- 문서 클릭 시 `mark-read` API가 자동 호출된다 +- 미열람/열람완료 탭으로 필터링 가능 +- 미열람 건수가 뱃지로 표시된다 + +--- + +## 3. 상세 화면 (`/approval-mgmt/{id}`) + +### 3.1 전체 레이아웃 + +``` +┌──────────────────────────────────────────────────────────┐ +│ 결재 상세 [수정] [목록으로] │ +│ APR-260228-001 │ +├──────────────────────────────────────────────────────────┤ +│ │ +│ 상태: [🔵 진행] [🔴 긴급] │ +│ 양식: 휴가신청서 기안자: 홍길동 │ +│ 기안일: 2026-02-28 10:05 완료일: - │ +│ 원본 문서: APR-260225-003 (재기안 시 표시) │ +│ │ +│ ┌──────────────────────────────────────────────────┐ │ +│ │ 회수 사유 (cancelled 상태에서만) │ │ +│ │ 내용 수정이 필요하여 회수합니다. │ │ +│ └──────────────────────────────────────────────────┘ │ +│ │ +│ 제목: 2월 연차 사용 신청 │ +│ 본문: 2월 27일~28일 연차 사용합니다... │ +│ │ +├──────────────────────────────────────────────────────────┤ +│ │ +│ 결재 진행 │ +│ ┌────────────────────────────────────────────────┐ │ +│ │ [결재 단계 프로그레스 바] │ │ +│ │ ✓김과장(승인) → ●박부장(대기) → ③이사(대기) │ │ +│ └────────────────────────────────────────────────┘ │ +│ │ +│ 결재 의견 │ +│ ┌────────────────────────────────────────────────┐ │ +│ │ ✓ 김과장 2026-02-28 11:00 │ │ +│ │ 승인합니다. │ │ +│ └────────────────────────────────────────────────┘ │ +│ │ +├──────────────────────────────────────────────────────────┤ +│ │ +│ 결재 처리 (현재 결재자에게만 표시) │ +│ [결재 의견 textarea] │ +│ [승인] [반려] [보류] [전결] │ +│ │ +├──────────────────────────────────────────────────────────┤ +│ 보류 해제 (on_hold + 보류한 본인에게만) │ +│ [보류 해제] │ +├──────────────────────────────────────────────────────────┤ +│ 회수 (기안자 + pending/on_hold) │ +│ [회수 사유 textarea] │ +│ [결재 회수] │ +├──────────────────────────────────────────────────────────┤ +│ 복사 재기안 (기안자 + approved/rejected/cancelled) │ +│ [복사하여 재기안] │ +└──────────────────────────────────────────────────────────┘ +``` + +### 3.2 조건부 섹션 표시 + +| 섹션 | 표시 조건 | +|------|----------| +| **수정 버튼** | 기안자 + `draft`/`rejected` | +| **회수 사유** | `cancelled` + `recall_reason` 존재 | +| **원본 문서 링크** | `parent_doc_id` 존재 (재기안 문서) | +| **결재 처리** | `pending` + 현재 결재자 | +| **보류 해제** | `on_hold` + 보류한 본인 | +| **회수** | 기안자 + `pending`/`on_hold` | +| **복사 재기안** | 기안자 + `approved`/`rejected`/`cancelled` | + +--- + +## 4. 파셜 컴포넌트 + +### 4.1 상태 뱃지 (`_status-badge.blade.php`) + +문서 상태를 색상 뱃지로 표시한다. + +| 상태 | 라벨 | 스타일 | +|------|------|--------| +| `draft` | 임시저장 | `bg-gray-100 text-gray-700` | +| `pending` | 진행 | `bg-blue-100 text-blue-700` | +| `approved` | 완료 | `bg-green-100 text-green-700` | +| `rejected` | 반려 | `bg-red-100 text-red-700` | +| `cancelled` | 회수 | `bg-yellow-100 text-yellow-700` | +| `on_hold` | 보류 | `bg-amber-100 text-amber-700` | + +--- + +### 4.2 결재 단계 프로그레스 (`_step-progress.blade.php`) + +결재선의 각 단계를 가로 프로그레스 바로 표시한다. + +**단계 아이콘:** + +| 상태 | 아이콘 | 배경색 | 텍스트색 | +|------|--------|--------|---------| +| `approved` (normal) | ✓ | `bg-green-500` | white | +| `approved` (pre_decided) | ⚡ | `bg-indigo-500` | white | +| `rejected` | ✗ | `bg-red-500` | white | +| `on_hold` | ⏸ | `bg-amber-400` | white | +| `skipped` | — | `bg-gray-300` | gray | +| `pending` (현재 차례) | 번호 | `bg-blue-500` | white | +| `pending` (대기) | 번호 | `bg-gray-200` | gray | + +**레이아웃:** + +``` +┌──────────────────────────────────────────────────────┐ +│ │ +│ ✓ ──── ⚡ ──── — ──── — ──── ● ──── 3 │ +│ 김과장 박부장 이사장 팀장 최대리 참조자 │ +│ 경영팀 경영팀 대표실 개발팀 개발팀 인사팀 │ +│ (승인) (전결) (건너뜀)(건너뜀)(대기) (참조) │ +│ │ +└──────────────────────────────────────────────────────┘ +``` + +**특수 표시:** +- **전결** step: ⚡ 아이콘 + "전결" 라벨 (남색) +- **보류** step: ⏸ 아이콘 + "보류" 라벨 (노란색) +- **건너뜀** step: 이름에 취소선 (line-through) +- **참조** step: 별도 구분 없이 동일 프로그레스 바에 표시 +- **연결선**: 단계 사이 가로선 (`border-t-2`) + +--- + +## 5. 결재 처리 인터랙션 + +### 5.1 승인 + +``` +[승인 버튼 클릭] + → confirm("승인하시겠습니까?") + → POST /api/admin/approvals/{id}/approve + body: { comment: "의견 텍스트" } + → 성공 시: 토스트("승인되었습니다") + 페이지 리로드 +``` + +### 5.2 반려 + +``` +[반려 버튼 클릭] + → comment 빈 값 체크 → 경고 토스트("반려 시 사유를 입력해주세요") + → confirm("반려하시겠습니까?") + → POST /api/admin/approvals/{id}/reject + body: { comment: "사유" } + → 성공 시: 토스트("반려되었습니다") + 페이지 리로드 +``` + +### 5.3 보류 + +``` +[보류 버튼 클릭] + → comment 빈 값 체크 → 경고 토스트("보류 사유를 입력해주세요") + → confirm("이 결재를 보류하시겠습니까?") + → POST /api/admin/approvals/{id}/hold + body: { comment: "사유" } + → 성공 시: 토스트("보류되었습니다") + 페이지 리로드 +``` + +### 5.4 전결 + +``` +[전결 버튼 클릭] + → confirm("전결 처리하시겠습니까?\n이후 모든 결재를 건너뛰고 문서를 최종 승인합니다.") + → POST /api/admin/approvals/{id}/pre-decide + body: { comment: "의견(선택)" } + → 성공 시: 토스트("전결 처리되었습니다") + 페이지 리로드 +``` + +### 5.5 보류 해제 + +``` +[보류 해제 버튼 클릭] + → confirm("보류를 해제하시겠습니까?") + → POST /api/admin/approvals/{id}/release-hold + → 성공 시: 토스트("보류가 해제되었습니다") + 페이지 리로드 +``` + +### 5.6 회수 + +``` +[결재 회수 버튼 클릭] + → confirm("결재를 회수하시겠습니까? 이 작업은 되돌릴 수 없습니다.") + → POST /api/admin/approvals/{id}/cancel + body: { recall_reason: "사유(선택)" } + → 성공 시: 토스트("결재가 회수되었습니다") + 페이지 리로드 +``` + +### 5.7 복사 재기안 + +``` +[복사하여 재기안 버튼 클릭] + → confirm("이 문서를 복사하여 새 결재를 작성하시겠습니까?") + → POST /api/admin/approvals/{id}/copy + → 성공 시: 토스트("문서가 복사되었습니다") + → /approval-mgmt/{newId}/edit로 이동 +``` + +--- + +## 6. 결재 의견 표시 + +상세 페이지에서 결재 의견이 있는 step을 카드 형태로 표시한다. + +``` +┌──────────────────────────────────────┐ +│ ✓ 김과장 2026-02-28 11:00 │ +│ 승인합니다. │ +├──────────────────────────────────────┤ +│ ⚡ 박부장 (전결) 2026-02-28 14:00 │ +│ 전결 처리합니다. │ +├──────────────────────────────────────┤ +│ ⏸ 이사장 (보류) 2026-02-28 15:00 │ +│ 추가 자료 검토 필요 │ +├──────────────────────────────────────┤ +│ ✗ 팀장 2026-02-28 16:00 │ +│ 예산 초과로 반려합니다. │ +└──────────────────────────────────────┘ +``` + +**아이콘 색상:** +- ✓ 승인: 녹색 (`bg-green-100 text-green-600`) +- ⚡ 전결: 남색 (`bg-indigo-100 text-indigo-600`) +- ⏸ 보류: 노란색 (`bg-amber-100 text-amber-600`) +- ✗ 반려: 적색 (`bg-red-100 text-red-600`) + +--- + +## 7. 참조함 열람 추적 UI + +### 7.1 탭 필터 + +``` +[전체] [미열람 (5)] [열람완료] +``` + +- 탭 클릭 시 `is_read` 파라미터로 API 재호출 +- 미열람 탭에 건수 뱃지 표시 + +### 7.2 열람 상태 표시 + +| 상태 | 표시 | +|------|------| +| 미열람 | `bg-red-100 text-red-700` "미열람" | +| 열람완료 | `bg-green-100 text-green-700` "열람완료" | + +### 7.3 자동 열람 처리 + +문서 행 클릭 시: +1. `mark-read` API 호출 (비동기) +2. 상세 페이지로 이동 + +--- + +## 8. 버튼 스타일 가이드 + +| 버튼 | 색상 | Tailwind 클래스 | +|------|------|----------------| +| 승인 | 녹색 | `bg-green-600 hover:bg-green-700` | +| 반려 | 적색 | `bg-red-600 hover:bg-red-700` | +| 보류 | 노란색 | `bg-amber-500 hover:bg-amber-600` | +| 전결 | 남색 | `bg-indigo-600 hover:bg-indigo-700` | +| 보류 해제 | 노란색 | `bg-amber-500 hover:bg-amber-600` | +| 회수 | 노란색 | `bg-yellow-500 hover:bg-yellow-600` | +| 복사 재기안 | 회색 | `bg-gray-600 hover:bg-gray-700` | +| 수정 | 회색 | `bg-gray-600 hover:bg-gray-700` | + +--- + +## 관련 문서 + +- [README.md](README.md) — 시스템 전체 개요 +- [워크플로우 상세](workflows.md) — 각 동작의 상세 흐름 +- [API 명세](api-reference.md) — 엔드포인트별 요청/응답 + +--- + +**최종 업데이트**: 2026-02-28 diff --git a/sam/docs/features/approvals/workflows.md b/sam/docs/features/approvals/workflows.md new file mode 100644 index 0000000..202d525 --- /dev/null +++ b/sam/docs/features/approvals/workflows.md @@ -0,0 +1,565 @@ +# 결재관리 워크플로우 상세 + +> **작성일**: 2026-02-28 +> **상태**: Phase 2 구현 완료 +> **관련**: [README.md](README.md) | [API 명세](api-reference.md) | [UI 화면](ui-screens.md) + +--- + +## 1. 개요 + +이 문서는 결재관리 시스템의 각 동작(Action)에 대한 상세 워크플로우를 정의한다. +모든 워크플로우는 `ApprovalService`에서 트랜잭션으로 처리된다. + +### 1.1 용어 정의 + +| 용어 | 설명 | +|------|------| +| **기안자** | 결재 문서를 작성한 사람 (`drafter_id`) | +| **현재 결재자** | 결재선에서 현재 차례인 사람 (가장 작은 `step_order`의 `pending` step) | +| **결재자** | `step_type`이 `approval` 또는 `agreement`인 참여자 | +| **참조자** | `step_type`이 `reference`인 참여자 (의사결정 권한 없음) | +| **전결** | 현재 결재자가 이후 모든 결재를 건너뛰고 즉시 최종 승인 | + +--- + +## 2. 기안 작성 (createApproval) + +### 2.1 흐름 + +``` +사용자 → [양식 선택] → [제목/본문 입력] → [결재선 설정] → [임시저장] + │ + ▼ + 새 Approval 생성 + status = 'draft' + current_step = 0 +``` + +### 2.2 조건 + +- 모든 로그인 사용자가 작성 가능 +- `form_id` 필수 (양식 선택) +- 결재선(steps)은 저장 시 선택사항 (상신 시 필수) + +### 2.3 처리 로직 + +1. 문서번호 자동 채번 (`APR-YYMMDD-001` 형식) +2. `numbering_sequences` 테이블로 일일 순번 관리 +3. 결재선 설정 시 `approval_steps` 저장 + 사용자 정보 스냅샷 (이름, 부서, 직급) +4. `status = 'draft'`, `current_step = 0` + +--- + +## 3. 상신 (submit) + +### 3.1 흐름 + +``` +기안자 → [상신 버튼] → 유효성 검사 → 결재선 검사 → 상신 완료 + │ + ▼ + status = 'pending' + current_step = 1 + drafted_at = now() +``` + +### 3.2 조건 + +| 조건 | 설명 | +|------|------| +| 문서 상태 | `draft` 또는 `rejected` | +| 결재선 | 결재/합의 step 1명 이상 필수 | +| 요청자 | 기안자만 | + +### 3.3 처리 로직 + +1. `isSubmittable()` 검증 → `draft` 또는 `rejected`인지 확인 +2. 결재/합의 step 존재 확인 +3. **반려 후 재상신인 경우**: 모든 step을 `pending`으로 초기화 (comment, acted_at도 초기화) +4. `status → pending`, `drafted_at → now()`, `current_step → 1` + +### 3.4 반려 후 재상신 + +``` +rejected 문서 + │ + ├── 기안자가 내용 수정 (updateApproval) + │ + └── 상신 (submit) + ├── 모든 steps → pending (초기화) + ├── status → pending + └── current_step → 1 (처음부터 다시) +``` + +> 반려 후 재상신 시 결재선이 초기화되므로, 이전 결재 의견(comment)은 사라진다. + +--- + +## 4. 승인 (approve) + +### 4.1 흐름 + +``` +현재 결재자 → [의견 입력(선택)] → [승인 버튼] + │ + ┌──────────┴──────────┐ + │ 현재 step │ + │ status → 'approved' │ + │ comment → (입력값) │ + │ acted_at → now() │ + └──────────┬──────────┘ + │ + ┌─────────────────┴─────────────────┐ + │ │ + 다음 pending step 있음 마지막 결재자 + │ │ + current_step 갱신 status → 'approved' + (다음 순서 결재자 대기) completed_at → now() +``` + +### 4.2 조건 + +| 조건 | 설명 | +|------|------| +| 문서 상태 | `pending` | +| 요청자 | 현재 차례 결재자 (`approver_id === auth()->id()`) | + +### 4.3 처리 로직 + +1. `isActionable()` 검증 → `pending` 상태인지 확인 +2. `getCurrentApproverStep()` → 현재 차례 step 조회 +3. 현재 step → `approved` + comment + acted_at +4. 다음 pending 결재/합의 step 조회 + - **있으면**: `current_step` 갱신 + - **없으면**: 문서 `approved` + `completed_at` + +### 4.4 순차결재 순서 결정 + +``` +step_order = 1 (결재) → step_order = 2 (합의) → step_order = 3 (결재) + │ │ │ + 1번째 승인 → 2번째 승인 → 3번째 승인 → 문서 완료 +``` + +> 결재와 합의는 동일한 순차 흐름을 따른다. `step_order` 순서대로 처리된다. + +--- + +## 5. 반려 (reject) + +### 5.1 흐름 + +``` +현재 결재자 → [반려 사유 입력(필수)] → [반려 버튼] + │ + ┌──────────┴──────────┐ + │ 현재 step │ + │ status → 'rejected' │ + │ comment → (사유) │ + │ acted_at → now() │ + └──────────┬──────────┘ + │ + ▼ + 문서 status → 'rejected' + completed_at → now() +``` + +### 5.2 조건 + +| 조건 | 설명 | +|------|------| +| 문서 상태 | `pending` | +| 요청자 | 현재 차례 결재자 | +| 반려 사유 | **필수** (빈 값 불가) | + +### 5.3 처리 로직 + +1. `isActionable()` 검증 +2. 현재 결재자 확인 +3. 반려 사유 빈 값 체크 +4. 현재 step → `rejected` + comment + acted_at +5. 문서 → `rejected` + completed_at + +### 5.4 반려 후 가능한 동작 + +``` +rejected 문서 + │ + ├── 기안자가 수정 → 재상신 (submit) + │ └── 결재선 초기화, 처음부터 다시 진행 + │ + └── 기안자가 복사 재기안 (copyForRedraft) + └── 새 문서 생성 (draft), 원본은 그대로 유지 +``` + +--- + +## 6. 회수 (cancel) + +### 6.1 흐름 + +``` +기안자 → [회수 사유 입력(선택)] → [회수 버튼] + │ + ┌──────────┴──────────┐ + │ 회수 가능 여부 판단 │ + │ (첫 결재자 미처리?) │ + └──────────┬──────────┘ + │ + ┌───────────┴───────────┐ + │ │ + 첫 결재자 첫 결재자 이미 + pending/on_hold 승인/반려 + │ │ + 회수 진행 회수 불가 + │ (에러 반환) + ▼ + 모든 pending/on_hold steps → 'skipped' + 문서 status → 'cancelled' + recall_reason → (입력값) + completed_at → now() +``` + +### 6.2 조건 + +| 조건 | 설명 | +|------|------| +| 문서 상태 | `pending` 또는 `on_hold` | +| 요청자 | 기안자만 (`drafter_id === auth()->id()`) | +| 첫 결재자 상태 | `pending` 또는 `on_hold` (이미 처리했으면 불가) | + +### 6.3 회수 가능 판단 로직 + +```php +// 1단계: 문서 상태 확인 +$approval->isCancellable() // pending 또는 on_hold + +// 2단계: 기안자 확인 +$approval->drafter_id === auth()->id() + +// 3단계: 첫 결재자 상태 확인 +$firstStep = steps.approvalOnly().orderBy('step_order').first() +$firstStep->status === 'pending' || 'on_hold' // 미처리 상태여야 함 +``` + +### 6.4 처리 로직 + +1. `isCancellable()` 검증 → `pending` 또는 `on_hold` +2. 기안자 확인 +3. 첫 번째 결재/합의 step의 상태 확인 → `pending`/`on_hold`이 아니면 거부 +4. 모든 `pending`/`on_hold` steps → `skipped` +5. 문서 → `cancelled` + `recall_reason` + `completed_at` + +--- + +## 7. 보류 (hold) + +### 7.1 흐름 + +``` +현재 결재자 → [보류 사유 입력(필수)] → [보류 버튼] + │ + ┌──────────┴──────────┐ + │ 현재 step │ + │ status → 'on_hold' │ + │ comment → (사유) │ + │ acted_at → now() │ + └──────────┬──────────┘ + │ + ▼ + 문서 status → 'on_hold' +``` + +### 7.2 조건 + +| 조건 | 설명 | +|------|------| +| 문서 상태 | `pending` (`isHoldable()`) | +| 요청자 | 현재 차례 결재자 | +| 보류 사유 | **필수** (빈 값 불가) | + +### 7.3 처리 로직 + +1. `isHoldable()` 검증 → `pending` 상태인지 확인 +2. `getCurrentApproverStep()` → 현재 차례 step 조회 +3. 현재 결재자 확인 (`approver_id === auth()->id()`) +4. 보류 사유 빈 값 체크 +5. 현재 step → `on_hold` + comment + acted_at +6. 문서 → `on_hold` + +### 7.4 보류 상태의 영향 + +``` +on_hold 상태에서: +├── 다른 결재자는 아무 동작 불가 (결재 흐름 중단) +├── 기안자는 회수 가능 (첫 결재자가 미처리 상태이면) +└── 보류한 결재자만 보류 해제 가능 +``` + +--- + +## 8. 보류 해제 (releaseHold) + +### 8.1 흐름 + +``` +보류한 결재자 → [보류 해제 버튼] + │ + ┌──────────┴──────────┐ + │ on_hold step │ + │ status → 'pending' │ + │ comment → null │ + │ acted_at → null │ + └──────────┬──────────┘ + │ + ▼ + 문서 status → 'pending' + (결재 흐름 재개) +``` + +### 8.2 조건 + +| 조건 | 설명 | +|------|------| +| 문서 상태 | `on_hold` (`isHoldReleasable()`) | +| 요청자 | 보류한 본인만 (`on_hold` step의 `approver_id === auth()->id()`) | + +### 8.3 처리 로직 + +1. `isHoldReleasable()` 검증 → `on_hold` 상태인지 확인 +2. `on_hold` 상태인 step 조회 +3. 해당 step의 `approver_id`가 현재 사용자인지 확인 +4. step → `pending` + comment/acted_at 초기화 +5. 문서 → `pending` + +--- + +## 9. 전결 (preDecide) + +### 9.1 흐름 + +``` +현재 결재자 → [의견 입력(선택)] → [전결 버튼] → 확인 팝업 + │ + ┌──────────┴──────────┐ + │ 현재 step │ + │ status → 'approved' │ + │ approval_type → │ + │ 'pre_decided' │ + │ comment → (입력값) │ + │ acted_at → now() │ + └──────────┬──────────┘ + │ + ▼ + 이후 모든 pending + approval/agreement steps + → status = 'skipped' + │ + ▼ + 문서 status → 'approved' + completed_at → now() +``` + +### 9.2 조건 + +| 조건 | 설명 | +|------|------| +| 문서 상태 | `pending` (`isActionable()`) | +| 요청자 | 현재 차례 결재자 | + +### 9.3 처리 로직 + +1. `isActionable()` 검증 +2. `getCurrentApproverStep()` → 현재 차례 step 조회 +3. 현재 결재자 확인 +4. 현재 step → `approved` + `approval_type = 'pre_decided'` + comment + acted_at +5. 이후 모든 pending 결재/합의 steps → `skipped` +6. 문서 → `approved` + `completed_at` + +### 9.4 전결 예시 + +``` +step_order=1 (이사장, 결재) → approved (normal) +step_order=2 (부장, 결재) → approved (pre_decided) ← 여기서 전결 +step_order=3 (과장, 합의) → skipped (전결로 건너뜀) +step_order=4 (팀장, 결재) → skipped (전결로 건너뜀) +step_order=5 (참조자, 참조) → (참조는 영향 없음, 그대로 유지) + +문서 → approved, completed_at = now() +``` + +> 전결은 결재/합의 step만 건너뛴다. 참조 step은 영향받지 않는다. + +--- + +## 10. 복사 재기안 (copyForRedraft) + +### 10.1 흐름 + +``` +기안자 → [복사하여 재기안 버튼] + │ + ▼ + ┌─────────────────────────────┐ + │ 원본 문서에서 복사 │ + │ ├── form_id │ + │ ├── title │ + │ ├── content (양식 데이터) │ + │ ├── body │ + │ ├── is_urgent │ + │ ├── department_id │ + │ └── 결재선 (모두 pending) │ + └─────────────┬───────────────┘ + │ + ▼ + 새 문서 생성 (status = 'draft') + parent_doc_id = 원본.id + 새 문서번호 채번 + │ + ▼ + 수정 페이지로 이동 + (/approval-mgmt/{newId}/edit) +``` + +### 10.2 조건 + +| 조건 | 설명 | +|------|------| +| 원본 문서 상태 | `approved`, `rejected`, `cancelled` (`isCopyable()`) | +| 요청자 | 기안자만 (`drafter_id === auth()->id()`) | + +### 10.3 처리 로직 + +1. `isCopyable()` 검증 → `approved`/`rejected`/`cancelled` 중 하나 +2. 기안자 확인 +3. 새 문서 생성: + - 새 문서번호 채번 + - 원본의 양식, 제목, 내용, 본문, 긴급 여부, 부서 복사 + - `parent_doc_id = 원본.id` + - `status = 'draft'`, `current_step = 0` +4. 결재선 복사: 원본의 모든 steps를 새 문서에 복사 (모두 `pending` 상태) +5. 새 문서의 edit 페이지로 리다이렉트 + +### 10.4 원본과의 관계 + +``` +원본 문서 (approved/rejected/cancelled) + │ + └── parent_doc_id로 연결 + │ + ▼ + 새 문서 (draft) + ├── 상세 페이지에서 "원본 문서" 링크 표시 + └── 기안자가 내용 수정 후 상신 가능 +``` + +--- + +## 11. 참조 열람 추적 (markAsRead) + +### 11.1 흐름 + +``` +참조자 → [참조함 목록에서 문서 클릭] + │ + ├── markAsRead API 호출 + │ ├── is_read → true + │ └── read_at → now() + │ + └── 상세 페이지로 이동 +``` + +### 11.2 조건 + +| 조건 | 설명 | +|------|------| +| 요청자 | 해당 문서의 참조자 (`step_type = 'reference'`) | + +### 11.3 처리 로직 + +1. 현재 사용자의 참조 step 조회 +2. `is_read = false`인 step → `is_read = true`, `read_at = now()` +3. 이미 열람한 경우 중복 업데이트 없음 (`where('is_read', false)`) + +--- + +## 12. 전체 상태 전이 요약 + +``` +┌───────────────────────────────────────────────────────────────────┐ +│ │ +│ draft ──submit()──→ pending ──approve()──→ (다음 step 또는) │ +│ ▲ │ │ approved │ +│ │ │ │ │ +│ │ │ ├──reject()──→ rejected │ +│ │ │ │ │ │ +│ │ │ │ ├── 수정 → submit() │ +│ │ │ │ │ (재상신, draft X) │ +│ │ │ │ │ │ +│ │ │ │ └── copyForRedraft() │ +│ │ │ │ → 새 draft 생성 │ +│ │ │ │ │ +│ │ │ ├──hold()──→ on_hold │ +│ │ │ │ │ │ +│ │ │ │ ├── releaseHold() │ +│ │ │ │ │ → pending 복원 │ +│ │ │ │ │ │ +│ │ │ │ └── cancel() (기안자) │ +│ │ │ │ → cancelled │ +│ │ │ │ │ +│ │ │ ├──preDecide()──→ approved │ +│ │ │ │ (이후 steps → skipped) │ +│ │ │ │ │ +│ │ │ └──cancel()──→ cancelled │ +│ │ │ (기안자, 첫결재자 미처리 시) │ +│ │ │ │ │ +│ │ │ └── copyForRedraft() │ +│ │ │ → 새 draft 생성 │ +│ │ │ │ +│ │ └── approved ──copyForRedraft() │ +│ │ → 새 draft 생성 │ +│ │ │ +│ └── updateApproval() (draft/rejected 상태에서 수정) │ +│ │ +└───────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 13. 에러 케이스 정리 + +| 동작 | 에러 조건 | 에러 메시지 | +|------|----------|------------| +| submit | 상태가 draft/rejected 아님 | "상신할 수 없는 상태입니다." | +| submit | 결재선 없음 | "결재선을 설정해주세요." | +| approve | 상태가 pending 아님 | "승인할 수 없는 상태입니다." | +| approve | 현재 결재자 아님 | "현재 결재자가 아닙니다." | +| reject | 상태가 pending 아님 | "반려할 수 없는 상태입니다." | +| reject | 사유 미입력 | "반려 사유를 입력해주세요." | +| cancel | 상태가 pending/on_hold 아님 | "회수할 수 없는 상태입니다." | +| cancel | 기안자 아님 | "기안자만 회수할 수 있습니다." | +| cancel | 첫 결재자 이미 처리 | "첫 번째 결재자가 이미 처리하여 회수할 수 없습니다." | +| hold | 상태가 pending 아님 | "보류할 수 없는 상태입니다." | +| hold | 현재 결재자 아님 | "현재 결재자가 아닙니다." | +| hold | 사유 미입력 | "보류 사유를 입력해주세요." | +| releaseHold | 상태가 on_hold 아님 | "보류 해제할 수 없는 상태입니다." | +| releaseHold | 보류한 본인 아님 | "보류한 결재자만 해제할 수 있습니다." | +| preDecide | 상태가 pending 아님 | "전결할 수 없는 상태입니다." | +| preDecide | 현재 결재자 아님 | "현재 결재자가 아닙니다." | +| copyForRedraft | 상태가 approved/rejected/cancelled 아님 | "복사할 수 없는 상태입니다." | +| copyForRedraft | 기안자 아님 | "기안자만 복사할 수 있습니다." | +| update | 상태가 draft/rejected 아님 | "수정할 수 없는 상태입니다." | +| delete | 상태가 draft 아님 | "삭제할 수 없는 상태입니다." | + +--- + +## 관련 문서 + +- [README.md](README.md) — 시스템 전체 개요 +- [API 명세](api-reference.md) — 엔드포인트별 요청/응답 +- [UI 화면 구성](ui-screens.md) — 화면별 동작 + +--- + +**최종 업데이트**: 2026-02-28