From 0ace50b00645ab4a3e340a05985cc2ecd7129ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=ED=98=81=EC=84=B1?= Date: Fri, 27 Feb 2026 18:03:04 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20[=EC=A2=85=ED=95=A9=EC=A0=95=EB=B9=84]?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=EC=9E=AC=ED=8E=B8=20=E2=80=94=20Phase?= =?UTF-8?q?=200+2+4=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Phase 0: INDEX.md 전면 재작성, CLAUDE.md→INDEX.md 통합 삭제 - Phase 0: front/→guides/ 이관(5개 파일), changes/ D7 포맷 통일(3개) - Phase 0: guides/ai-config-설정.md→ai-config-settings.md D3 통일 - Phase 2: architecture/+specs/→system/ 이관(6개 이동, 4개 폐기) - Phase 2: 13개 파일 경로 참조 수정 (specs/→system/, architecture/→system/) - Phase 4: 7개 파일 11개 교차참조 깨진 링크 수정 Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 729 ------------ INDEX.md | 430 ++++--- architecture/README.md | 20 - architecture/scaling-roadmap-10k-tenants.md | 214 ---- architecture/security-policy.md | 784 ------------ architecture/system-overview.md | 392 ------ ...r.md => 20251111_admin_tenant_selector.md} | 2 +- ...md => 20251111_admin_users_improvement.md} | 0 ...fix.md => 20251215_items-api-files-fix.md} | 0 ...> 20251230_react_fcm_push_notification.md} | 0 features/boards/README.md | 2 +- features/boards/mng-implementation.md | 6 +- features/hr/attendance-management-spec.md | 4 +- guides/PROJECT_DEVELOPMENT_POLICY.md | 2 +- ...i-config-설정.md => ai-config-settings.md} | 0 .../auto-login-guide.md | 0 {front => guides}/erp-api-detail.md | 0 {front => guides}/erp-api-list.md | 0 {front => guides}/item-master-guide.md | 0 {front => guides}/item-master-items-api.md | 0 guides/jenkins-setup-guide.md | 2 +- guides/nginx-fastcgi-guide.md | 2 +- guides/php-fpm-guide.md | 2 +- guides/production-env-sync.md | 4 +- guides/server-how-it-works.md | 4 +- guides/swagger-guide.md | 4 +- quickstart/quick-start.md | 8 +- rules/README.md | 26 +- rules/pricing-policy.md | 2 +- specs/board-system-spec.md | 523 -------- specs/database-schema.md | 545 --------- specs/docker-setup.md | 342 ------ specs/erp-analysis/00-overview.md | 155 --- specs/erp-analysis/01-common.md | 143 --- specs/erp-analysis/02-auth.md | 205 ---- specs/erp-analysis/03-gps-attendance.md | 144 --- specs/erp-analysis/04-hr-management.md | 381 ------ specs/erp-analysis/05-approval.md | 296 ----- specs/erp-analysis/06-accounting.md | 427 ------- specs/erp-analysis/07-master-data.md | 332 ------ specs/erp-analysis/08-reports.md | 225 ---- specs/erp-analysis/99-gap-analysis.md | 1048 ----------------- specs/item-master-integration.md | 661 ----------- specs/remote-work-setup.md | 248 ---- standards/README.md | 2 +- standards/git-conventions.md | 2 +- 46 files changed, 283 insertions(+), 8035 deletions(-) delete mode 100644 CLAUDE.md delete mode 100644 architecture/README.md delete mode 100644 architecture/scaling-roadmap-10k-tenants.md delete mode 100644 architecture/security-policy.md delete mode 100644 architecture/system-overview.md rename changes/{20251111_1450_admin_tenant_selector.md => 20251111_admin_tenant_selector.md} (98%) rename changes/{20251111_1354_admin_users_improvement.md => 20251111_admin_users_improvement.md} (100%) rename changes/{2025-12-15_items-api-files-fix.md => 20251215_items-api-files-fix.md} (100%) rename changes/{20251230_1430_react_fcm_push_notification.md => 20251230_react_fcm_push_notification.md} (100%) rename guides/{ai-config-설정.md => ai-config-settings.md} (100%) rename front/AUTO_LOGIN_GUIDE.md => guides/auto-login-guide.md (100%) rename {front => guides}/erp-api-detail.md (100%) rename {front => guides}/erp-api-list.md (100%) rename {front => guides}/item-master-guide.md (100%) rename {front => guides}/item-master-items-api.md (100%) delete mode 100644 specs/board-system-spec.md delete mode 100644 specs/database-schema.md delete mode 100644 specs/docker-setup.md delete mode 100644 specs/erp-analysis/00-overview.md delete mode 100644 specs/erp-analysis/01-common.md delete mode 100644 specs/erp-analysis/02-auth.md delete mode 100644 specs/erp-analysis/03-gps-attendance.md delete mode 100644 specs/erp-analysis/04-hr-management.md delete mode 100644 specs/erp-analysis/05-approval.md delete mode 100644 specs/erp-analysis/06-accounting.md delete mode 100644 specs/erp-analysis/07-master-data.md delete mode 100644 specs/erp-analysis/08-reports.md delete mode 100644 specs/erp-analysis/99-gap-analysis.md delete mode 100644 specs/item-master-integration.md delete mode 100644 specs/remote-work-setup.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index ca30f35..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,729 +0,0 @@ -# Claude Code 전역 설정 - -> 이 파일은 모든 프로젝트에 적용되는 전역 규칙입니다. - -## 메모리 - -### sam설명 -SAM 프로젝트의 기술적 개요 문서입니다. 이 문서를 참조하면 SAM 프로젝트가 무엇인지 이해할 수 있습니다. - -**파일 경로**: `/home/aweso/sam/docs/SAM_PROJECT_OVERVIEW_FOR_AI.md` - -**핵심 요약**: -- **회사**: 주일/경동 (블라인드/스크린 제조업체) -- **프로젝트**: SAM (Smart Automation Management) - 차세대 ERP/MES 통합 시스템 -- **기술 스택**: Laravel 11 + HTMX + Tailwind CSS + MySQL 8.0 -- **아키텍처**: Multi-tenant (tenant_id 기반 데이터 격리) -- **레거시**: 5130.co.kr (PHP 기반) → SAM으로 마이그레이션 중 - -**사용자가 'sam설명'이라고 말하면**: -1. 위 경로의 `SAM_PROJECT_OVERVIEW_FOR_AI.md` 파일을 읽어서 전체 내용을 파악하세요 -2. SAM 프로젝트의 비즈니스 도메인, 기술 스택, 현재 작업 현황을 이해한 상태로 작업하세요 - ---- - -## Git 커밋 규칙 (최우선 필수 규칙) - -> **경고: 이 규칙은 절대 누락되어서는 안 됩니다!** -> **기준 문서**: `sam/docs/standards/git-conventions.md` - -### 필수 수행 절차 - -**모든 코드 작업 완료 후 반드시 다음을 수행:** - -1. 변경된 파일이 있는 Git 저장소로 이동 -2. `git status`로 변경사항 확인 -3. `git add <파일들>` 로 스테이징 -4. `git commit -m "type: [scope] 작업내용"` 로 커밋 - -### 커밋 메시지 형식 (필수) - -``` -type: [scope] 작업내용 - -- 세부항목 (생략가능) -- 세부항목 2 - -Issue: URL (생략가능) -``` - -**예시:** -```bash -feat: [calendar] 달력 기능 개선 - -- 클릭시 오류 기능 개선 -- 색상 변경 -``` - -```bash -fix: [auth] 로그인 시 세션 만료 오류 수정 -``` - -### Commit Types - -| Type | 설명 | 예시 | -|------|------|------| -| `feat` | 새로운 기능 추가 | `feat: [file] 파일 업로드 기능 추가` | -| `fix` | 버그 수정 | `fix: [auth] 세션 만료 오류 수정` | -| `chore` | 설정, 빌드 등 변경 | `chore: composer 패키지 업데이트` | -| `refactor` | 프로덕션 코드 리팩토링 | `refactor: [user] 서비스 메서드 분리` | -| `style` | 포맷/코딩 스타일 수정 | `style: Pint 포맷팅 적용` | -| `test` | 테스트 추가/수정 | `test: Product API 테스트 추가` | -| `docs` | 문서 변경 | `docs: API 문서 업데이트` | - -### Claude 서명 제외 (필수) - -``` -❌ Co-Authored-By: Claude — 포함 금지 -❌ 🤖 Generated with Claude Code — 포함 금지 -``` - -- Git hooks로 자동 제거됨 -- 간결하고 명확한 한글 커밋 메시지만 유지 - -### 푸시 정책 - -- **사용자가 수동으로 푸시 진행** -- 자동 푸시 하지 않음 -- 커밋 후 푸시 여부를 묻지 않음 - -### Claude Code 설정 파일도 커밋 대상 - -다음 파일들이 변경되면 반드시 커밋: - -| 파일/폴더 | 설명 | 커밋 예시 | -|-----------|------|----------| -| `CLAUDE.md` | 프로젝트 설정 | `docs: CLAUDE.md 규칙 업데이트` | -| `claudedocs/` | Claude 관련 문서 | `docs: 기능 분석 문서 추가` | -| `.claude/settings.json` | Claude 설정 | `chore: Claude 설정 변경` | -| `agents/`, `skills/` | 커스텀 에이전트/스킬 | `feat: [claude] 새 스킬 추가` | - -### 커밋 전 체크리스트 - -- [ ] `./vendor/bin/pint` 실행 (코드 포맷팅, 해당 시) -- [ ] `git diff`로 변경사항 검토 -- [ ] 불필요한 파일 제외 (.env, node_modules 등) -- [ ] 변경된 파일이 있는 저장소에서 git add → git commit -- [ ] CLAUDE.md, claudedocs/, agents/, skills/ 변경 확인 → git commit -- [ ] 커밋 메시지: `type: [scope] 한글 작업내용` 형식 준수 -- [ ] Co-Authored-By 서명 미포함 확인 - ---- - -## 주요 프로젝트 경로 - -| 경로 | 설명 | Git 저장소 | -|------|------|-----------| -| `/home/aweso/sam/mng` | 관리자 웹 (Laravel) | 독립 저장소 | -| `/home/aweso/sam/api` | API 서버 (Laravel) | 독립 저장소 | -| `/home/aweso/sam/react` | 프론트엔드 (Next.js) | 독립 저장소 | - -**각 폴더는 독립적인 Git 저장소입니다. 해당 폴더에서 git 명령을 실행해야 합니다.** - ---- - -## 서버 직접 접근 금지 (최우선 필수 규칙) - -> **경고: 운영/개발 서버에 SSH로 직접 접속하여 파일을 수정하거나 명령을 실행하지 마세요!** -> **2026-02-21 사고**: Claude가 서버에 SSH로 직접 접속하여 설정을 변경한 결과 502 Bad Gateway 발생. 개발팀장이 복구함. - -### 핵심 원칙 - -서버는 **개발팀장이 관리**한다. Claude는 서버에 절대 직접 접근하지 않는다. - -### 금지 사항 - -``` -❌ ssh pro@114.203.209.83 ... 로 서버 접속 금지 -❌ ssh hskwon@114.203.209.83 ... 로 서버 접속 금지 -❌ 서버에서 파일 수정, 프로세스 종료/시작, 설정 변경 금지 -❌ 서버에서 npm run build, npm start, node server.js 등 실행 금지 -❌ 서버에서 git pull, composer install, php artisan 등 실행 금지 -❌ scp, rsync로 서버에 파일 직접 전송 금지 -``` - -### 허용 사항 - -``` -✅ 로컬에서 코드 작성 및 수정 -✅ 로컬에서 git add → git commit -✅ 사용자에게 git push 안내 (사용자가 수동으로 실행) -✅ 사용자에게 서버 배포 절차 안내 (사용자가 수동으로 실행) -``` - -### 배포 흐름 - -``` -Claude 역할 사용자/팀장 역할 -┌─────────────────┐ ┌─────────────────┐ -│ 코드 작성/수정 │ │ │ -│ git add │ │ │ -│ git commit │──push──→ │ git pull │ -│ │ │ 서버 배포 │ -│ │ │ 서비스 재시작 │ -└─────────────────┘ └─────────────────┘ -``` - -### 서버 작업이 필요한 경우 - -사용자에게 명령어를 안내만 한다: - -``` -서버에서 다음 명령을 실행해주세요: -cd /home/webservice/api && git pull && composer install && php artisan migrate -``` - -### 체크리스트 (모든 작업 시) - -- [ ] SSH 명령 사용하지 않음 -- [ ] 서버 파일 직접 수정하지 않음 -- [ ] 배포가 필요하면 사용자에게 안내만 제공 -- [ ] git push까지만 Claude 역할 - ---- - -## React 빌드/배포 정책 (필수 규칙) - -> **경고: React(Next.js) 빌드는 반드시 로컬에서 실행합니다. 서버에서 빌드 절대 금지!** - -### 배경 - -서버 스펙(2코어, 3.8GB RAM, Swap 없음)으로는 Next.js 빌드 시 메모리 부족으로 20분 이상 소요되거나 실패한다. -로컬(WSL)에서 빌드 후 결과물만 서버에 배포한다. - -### 금지 사항 - -``` -❌ 서버에서 npm run build 실행 금지 -❌ 서버 SSH 접속 후 빌드 명령 실행 금지 -❌ Claude가 직접 npm run build 실행 금지 (로컬 포함) -``` - -### 빌드/배포 방법 - -``` -Claude 역할 사용자/팀장 역할 -┌─────────────────┐ ┌─────────────────┐ -│ 코드 작성/수정 │ │ │ -│ git commit │──push──→ │ git pull │ -│ │ │ npm run build │ -│ │ │ 서비스 재시작 │ -└─────────────────┘ └─────────────────┘ -``` - -### 빌드가 필요한 상황 - -사용자에게 다음과 같이 안내한다: - -``` -React 코드가 변경되었습니다. git push 후 서버에서 배포해주세요. -``` - ---- - -## 데이터베이스 아키텍처 (필수 규칙) - -> **경고: 이 규칙을 반드시 준수하세요!** - -### 핵심 원칙 - -**모든 데이터베이스 관련 파일은 API 프로젝트에서만 관리합니다.** - -| 항목 | API (`/home/aweso/sam/api`) | MNG (`/home/aweso/sam/mng`) | -|------|----------------------------|----------------------------| -| 마이그레이션 | ✅ 여기에 생성 | ❌ 생성 금지 | -| 시더 | ✅ 여기에 생성 | ⚠️ MNG 전용만 허용 | -| 팩토리 | ✅ 여기에 생성 | ❌ 생성 금지 | - -### 금지 사항 - -``` -❌ /home/aweso/sam/mng/database/migrations/ 에 파일 생성 금지 -❌ MNG에서 테이블 생성/수정 마이그레이션 작성 금지 -``` - -### 허용 사항 - -``` -✅ /home/aweso/sam/api/database/migrations/ 에 모든 마이그레이션 생성 -✅ MNG에서는 MngMenuSeeder 같은 MNG 전용 시더만 허용 -``` - -### 마이그레이션 실행 - -```bash -# 마이그레이션은 반드시 API 컨테이너에서 실행 -docker exec sam-api-1 php artisan migrate - -# MNG 컨테이너에서 마이그레이션 실행 금지 -# docker exec sam-mng-1 php artisan migrate ← 사용하지 않음 -``` - -### 이유 - -- MNG: 프론트엔드/관리자 화면 담당 (컨트롤러, 뷰, 라우트) -- API: 백엔드/데이터베이스 담당 (마이그레이션, 모델 정의, API) -- 단일 DB를 두 프로젝트가 공유하므로 마이그레이션은 한 곳에서만 관리 - ---- - -## 메뉴 관리 규칙 (필수) - -> **경고: 메뉴 시더(Seeder)를 절대 실행하지 마세요!** - -### 배경 - -메뉴 시더 실행 시 부서별 권한 설정(permission_overrides)이 초기화되는 문제가 반복 발생합니다. -메뉴 ID가 변경되면 기존 부서-메뉴 권한 매핑이 깨지기 때문입니다. - -### 금지 사항 - -``` -❌ php artisan db:seed --class=MngMenuSeeder 실행 금지 -❌ php artisan db:seed --class=*MenuSeeder 실행 금지 -❌ 메뉴 시더 파일 생성 금지 -❌ 메뉴 데이터를 일괄 삭제 후 재생성하는 방식 금지 -``` - -### 메뉴 변경 시 올바른 절차 - -메뉴 추가/수정/삭제/이동이 필요할 때는 **사용자에게 수동 실행 안내**를 제공합니다: - -1. **tinker 명령어를 안내** (사용자가 직접 실행) -2. **또는 SQL 쿼리를 안내** (사용자가 phpMyAdmin 등에서 직접 실행) -3. **절대 시더를 만들어 실행하지 않음** - -### 안내 예시 - -``` -메뉴를 추가하려면 아래 명령을 서버에서 실행해 주세요: - -ssh sam-server "cd /home/webservice/mng && php artisan tinker --execute=\" -App\\Models\\Commons\\Menu::create([ - 'tenant_id' => 1, - 'parent_id' => <부모ID>, - 'name' => '새 메뉴', - 'url' => '/new-menu', - 'icon' => 'icon-name', - 'sort_order' => 1, - 'is_active' => true, -]); -\"" -``` - -### 체크리스트 (메뉴 변경 요청 시) - -- [ ] 시더 파일 생성하지 않음 -- [ ] 시더 실행하지 않음 -- [ ] tinker 또는 SQL로 개별 레코드만 수정 -- [ ] 변경 후 부서 권한 설정이 유지되는지 확인 - ---- - -## Docker 환경 (필수 인지) - -> **중요: 로컬 개발 환경은 Docker 기반입니다!** - -### 왜 Docker를 통해 실행하나? - -PHP, Laravel, Node.js 등이 **Docker 컨테이너 안에** 설치되어 있습니다. -로컬 PC(WSL)에는 이런 도구들이 없으므로, 반드시 Docker 컨테이너를 통해 실행해야 합니다. - -``` -로컬 PC (WSL) -└── Docker - ├── sam-mng-1 ← PHP + Laravel (MNG 앱) - ├── sam-api-1 ← PHP + Laravel (API 앱) - ├── sam-mysql-1 ← MySQL DB - └── sam-nginx-1 ← Nginx 웹서버 -``` - -### Docker 명령어 패턴 - -```bash -# MNG 앱에서 artisan 명령 실행 -docker exec sam-mng-1 php artisan <명령어> - -# API 앱에서 artisan 명령 실행 -docker exec sam-api-1 php artisan <명령어> - -# 예시: 시더 실행 -docker exec sam-mng-1 php artisan db:seed --class=MngMenuSeeder - -# 예시: 마이그레이션 실행 (API에서만!) -docker exec sam-api-1 php artisan migrate - -# 예시: 캐시 클리어 -docker exec sam-mng-1 php artisan cache:clear -``` - -### 체크리스트 (명령 실행 시) - -- [ ] `php artisan` 명령 → `docker exec sam-mng-1 php artisan` 또는 `sam-api-1` 사용 -- [ ] `composer` 명령 → `docker exec sam-mng-1 composer` 또는 `sam-api-1` 사용 -- [ ] DB 시더 실행 필요 시 → Docker를 통해 실행 -- [ ] **마이그레이션은 반드시 API에서 실행** → `docker exec sam-api-1 php artisan migrate` - ---- - -## 공동 개발 워크플로우 (필수) - -> **중요: 코드를 pull 받은 후 반드시 필요한 명령을 실행하세요!** - -### 로컬 환경 (Docker) 업데이트 - -```bash -# 1. 코드 받기 (WSL에서 실행) -cd /home/aweso/sam/api -git pull - -cd /home/aweso/sam/mng -git pull - -# 2. 의존성 업데이트 (composer.json 변경 시) -docker exec sam-api-1 composer install -docker exec sam-mng-1 composer install - -# 3. DB 마이그레이션 (API에서만!) -docker exec sam-api-1 php artisan migrate - -# 4. 캐시 클리어 (설정 변경 시) -docker exec sam-api-1 php artisan config:clear -docker exec sam-mng-1 php artisan config:clear -``` - -### 서버 환경 업데이트 - -```bash -# API 프로젝트 -cd /home/webservice/api -git pull -composer install -php artisan migrate -php artisan config:clear - -# MNG 프로젝트 (마이그레이션 없음) -cd /home/webservice/mng -git pull -composer install -php artisan config:clear -``` - -### 요약 표 - -| 작업 | 로컬 (Docker) | 서버 | -|------|--------------|------| -| git pull | WSL에서 직접 | 서버에서 직접 | -| composer install | `docker exec sam-api-1 composer install` | `composer install` | -| migrate | `docker exec sam-api-1 php artisan migrate` | `php artisan migrate` | -| config:clear | `docker exec sam-api-1 php artisan config:clear` | `php artisan config:clear` | - -### 체크리스트 (pull 후) - -- [ ] API: `git pull` → `composer install` → `php artisan migrate` → `config:clear` -- [ ] MNG: `git pull` → `composer install` → `config:clear` (마이그레이션 없음) - ---- - -## 사용 가능한 Agents - -`~/.claude/agents/` 폴더에 있는 에이전트들: - -### 코드 품질 & 개발 - -| Agent | 모델 | 설명 | 출처 | -|-------|------|------|------| -| `code-reviewer` | sonnet | 코드 리뷰 (품질/보안/유지보수성), 메모리 학습 지원 | 공식 문서 패턴 | -| `debugger` | sonnet | 에러/테스트 실패 근본 원인 분석 및 수정 | 공식 문서 패턴 | -| `test-runner` | haiku | 테스트 실행 및 결과 분석/요약 | 커뮤니티 인기 | -| `security-auditor` | sonnet | OWASP Top 10 기반 보안 취약점 감사 | 커뮤니티 인기 | -| `performance-optimizer` | sonnet | N+1 쿼리, 알고리즘, 캐싱 최적화 | 커뮤니티 인기 | -| `refactoring-agent` | sonnet | 코드 구조 개선, SOLID 원칙, DRY 위반 제거 | 커뮤니티 인기 | -| `laravel-expert` | sonnet | Laravel 전문가 (SAM 프로젝트 환경 인지) | 커스텀 | - -### 워크플로우 & 문서 - -| Agent | 모델 | 설명 | 출처 | -|-------|------|------|------| -| `git-manager` | haiku | Git 브랜치/커밋/머지/PR 관리 | 커뮤니티 인기 | -| `doc-writer` | haiku | API 문서, README, 기술 가이드 작성 | 커뮤니티 인기 | -| `research-agent` | sonnet | 웹 리서치 및 자료 조사 | 기존 | -| `organizer-agent` | - | 프로젝트 구조화 및 정리 | 기존 | -| `proposal-agent` | - | 제안서 작성 | 기존 | - ---- - -## 사용 가능한 Skills - -`~/.claude/skills/` 폴더에 있는 스킬들 (슬래시 명령어로 사용): - -### 문서/프레젠테이션 - -| Skill | 설명 | -|-------|------| -| `pptx-skill` | PowerPoint 생성 | -| `ppt-auto-generator` | 마크다운/텍스트에서 PPT 생성 | -| `pdf-template-skill` | PDF 템플릿 분석/생성 | -| `text-analyzer-skill` | 텍스트 분석 및 PDF 구조 매핑 | -| `proposal-skill` | 제안서 생성 | -| `storyboard-generator` | 스토리보드 생성 | -| `design-skill` | 프레젠테이션 HTML 디자인 | - -### 코드 분석/시각화 - -| Skill | 설명 | -|-------|------| -| `code-flow-web-report` | 웹 앱 런타임 흐름 시각화 리포트 | -| `code-flow-web-doc-generator` | 소스 코드 호출/데이터 흐름 다이어그램 HTML 생성 | -| `codebase-analysis-web-report` | 코드베이스 아키텍처 인터랙티브 HTML 리포트 | -| `uml-generator` | UML 다이어그램 생성 | - -### 코드 품질 (levnikolaevich/claude-code-skills) - -| Skill | 설명 | 출처 | -|-------|------|------| -| `code-bug-finder` | 버그 자동 탐지 및 보고서 생성 | 기존 | -| `code-refactoring` | 리팩토링 권장사항/성능 분석/코드 패치 | 기존 | -| `code-commenter` | 소스 코드에 이해하기 쉬운 주석 추가 | 기존 | -| `async-await-keyword-fixer` | JS/TS 누락된 async/await 수정 | 기존 | -| `code-quality-checker` | DRY/KISS/YAGNI 위반 탐지 | levnikolaevich | -| `code-quality-auditor` | 코드 복잡도, 매직넘버 분석 | levnikolaevich | -| `code-principles-auditor` | DRY/KISS/YAGNI, TODO, DI 패턴 검사 | levnikolaevich | -| `dead-code-auditor` | 미사용 코드 탐지 | levnikolaevich | -| `build-auditor` | 컴파일러/타입 에러 검사 | levnikolaevich | -| `concurrency-auditor` | 레이스 컨디션 탐지 | levnikolaevich | -| `layer-boundary-auditor` | 레이어 위반, I/O 격리 검사 | levnikolaevich | -| `observability-auditor` | 로깅, 메트릭 적절성 검사 | levnikolaevich | -| `query-efficiency-auditor` | DB 쿼리 효율성 분석 | levnikolaevich | -| `dependencies-auditor` | 오래된 패키지, CVE 취약점 검사 | levnikolaevich | -| `regression-checker` | 기존 테스트 실행으로 사이드이펙트 탐지 | levnikolaevich | -| `story-quality-gate` | 코드리뷰 + 테스트 2단계 품질 검증 | levnikolaevich | - -### 테스트/커버리지 - -| Skill | 설명 | 출처 | -|-------|------|------| -| `app-comprehensive-test-generator` | 테스트 시나리오 생성/실행, QA 리포트 | 기존 | -| `coverage-improvement-planner` | 테스트 커버리지 분석 및 개선 계획 | 기존 | -| `test-coverage-auditor` | 테스트 커버리지 측정/분석 | levnikolaevich | -| `test-isolation-auditor` | 테스트 독립성/격리 검사 | levnikolaevich | -| `webapp-testing` | Playwright 기반 웹 앱 UI 테스트 | anthropics 공식 | - -### 보안 (Trail of Bits) - -| Skill | 설명 | 출처 | -|-------|------|------| -| `security-auditor` | 시크릿 노출, Injection, XSS 탐지 | levnikolaevich | -| `static-analysis` | CodeQL/Semgrep/SARIF 정적 분석 (3개 하위 스킬) | Trail of Bits | -| `insecure-defaults` | 위험한 기본 설정, 하드코딩 자격증명 탐지 | Trail of Bits | -| `sharp-edges` | 에러 유발 API, 위험한 디자인 패턴 탐지 | Trail of Bits | -| `differential-review` | 보안 중심 코드 변경 리뷰 | Trail of Bits | - -### 디버깅/로깅 - -| Skill | 설명 | -|-------|------| -| `system-debug-logger` | 에러/예외 자동 캡처 디버그 로깅 | -| `node-debug-logging-middleware` | Node.js Express/Koa 디버깅 로그 미들웨어 | - -### 프론트엔드/UI - -| Skill | 설명 | 출처 | -|-------|------|------| -| `frontend-design` | 프론트엔드 디자인 품질 향상 (AI slop 방지) | anthropics 공식 | -| `flutter-ux-hardening` | Flutter 앱 UI/UX 강화 | 기존 | -| `웹문서` | SAM 프로젝트 웹문서 디자인 표준 | 기존 | - -### 유틸리티 - -| Skill | 설명 | -|-------|------| -| `duplicate-file-cleaner` | 중복 이미지/미디어 파일 정리 | -| `npm-release-manager` | NPM 패키지 배포 자동화 | - -**사용 방법**: `/skill-name` 형식으로 호출 (예: `/code-quality-checker`) - ---- - -## 문서 작성 규칙 (개발팀 협약 - 필수 준수) - -> **경고: 개발자들이 `sam/docs`의 문서 작성 기법을 준용하기로 협약했습니다. 모든 문서 작성 시 반드시 따르세요!** - -### 참조 경로 - -- **인덱스**: `/home/aweso/sam/docs/INDEX.md` (전체 문서 목록 및 폴더 구조) -- **작업 전 확인**: 작업 유형에 맞는 문서를 `INDEX.md`에서 찾아 먼저 읽고 시작 - -### 폴더 선택 기준 (의미 기반 분류) - -| 폴더 | 질문 | 설명 | -|------|------|------| -| `plans/` | "무슨 작업을 할 것인가?" | 임시 개발 계획 (완료 후 삭제) | -| `standards/` | "어떻게 코드를 작성할 것인가?" | 코딩 컨벤션, 스타일 가이드 | -| `architecture/` | "왜 이렇게 설계하는가?" | 시스템 설계, 아키텍처 결정 | -| `rules/` | "무엇이 유효한 데이터인가?" | 비즈니스 규칙, 검증 규칙 | -| `specs/` | "무엇을 구현할 것인가?" | 기술 스펙, DB 스키마 | -| `guides/` | "어떻게 구현할 것인가?" | 단계별 구현 매뉴얼 | -| `features/` | 기능별 상세 | 기능 단위 심층 문서 | -| `changes/` | "무엇이 변경되었는가?" | 완료된 변경 이력 | - -### 파일명 규칙 - -- **일반 문서**: `kebab-case.md` (소문자 + 하이픈) 예: `api-rules.md`, `item-policy.md` -- **변경 이력**: `YYYYMMDD_short_description.md` 예: `20260109_handover_report_api.md` -- **폴더 인덱스**: `README.md` (대문자) -- **크기 목표**: 10KB 이하 -- **새 문서 작성 시**: 반드시 `docs/INDEX.md`에 추가 - -### 문서 구조 템플릿 - -#### 정책/규칙 문서 (`rules/`, `standards/`) - -```markdown -# 제목 - -> **작성일**: YYYY-MM-DD -> **상태**: 설계 확정 - ---- - -## 1. 개요 -### 1.1 목적 -### 1.2 핵심 원칙 - ---- - -## 2. 테이블 구조 (해당 시) -### 2.1 ERD 개요 - ---- - -## N. 비즈니스 규칙 -### N.1 검증 규칙 - ---- - -## N. API 엔드포인트 - ---- - -## 관련 문서 - ---- - -**최종 업데이트**: YYYY-MM-DD -``` - -#### 변경 이력 문서 (`changes/`) - -```markdown -# 변경 내용 요약 - -**날짜:** YYYY-MM-DD -**작업자:** Claude Code - -## 변경 개요 - -## 수정된 파일 -| 파일 | 변경 내용 | -|------|----------| - -## 상세 변경 사항 - -## 테스트 체크리스트 -- [x] 완료 항목 -- [ ] 미완료 항목 - -## 관련 문서 -``` - -### 작성 스타일 규칙 - -| 항목 | 규칙 | -|------|------| -| **언어** | 한글 기본, 코드/경로/기술 식별자만 영어 | -| **어조** | 서술형 ("X를 해야 한다" 아닌 "X 한다") | -| **경고** | `> **경고: ...**` 블록인용 형식 | -| **금지/필수** | `❌` 금지, `✅` 필수 접두사 | -| **우선순위** | `🔴 필수`, `🟡 중요`, `🟢 권장` | -| **섹션 번호** | `## 1.`, `### 1.1` 번호 매기기 | -| **규칙 번호** | R1, R2, R3... 순차 라벨 | -| **코드 블록** | 반드시 언어 지정 (```php, ```bash, ```json, ```sql) | -| **인라인 코드** | 파일 경로, 메서드명, 변수명, 컬럼명에 백틱 | -| **다이어그램** | `┌─┐│└─┘` 박스 문자, `→` 화살표 사용 | -| **구분선** | `---` 주요 섹션 사이마다 | -| **테이블** | API: `| Method | Path | 설명 |`, 필드: `| 필드 | 타입 | 설명 |` | - -### plans/ 워크플로우 - -1. 개발 계획 문서를 `plans/`에 작성 -2. 작업 진행 -3. 완료 후 결과물을 해당 폴더(`features/`, `changes/` 등)에 정리 -4. plan 문서 삭제 - -### 체크리스트 (문서 작성 시) - -- [ ] 적절한 폴더에 배치 (위 폴더 선택 기준 참고) -- [ ] `kebab-case.md` 파일명 사용 -- [ ] 문서 구조 템플릿 준수 -- [ ] 한글 기본, 기술 용어만 영어 -- [ ] 코드 블록에 언어 지정 -- [ ] `docs/INDEX.md`에 새 문서 등록 -- [ ] 10KB 이하 크기 유지 - ---- - -## PPT / 프레젠테이션 제작 규칙 (필수 준수) - -> **경고: 모든 프레젠테이션 및 문서 제작 시 반드시 따르세요!** - -### 회사 정보 - -| 항목 | 값 | -|------|------| -| **공식 회사명** | **(주)코드브릿지엑스** | -| **서비스명** | **SAM** (Smart Automation Management) | -| **푸터 표기 예시** | `SAM 서비스 요금 안내 | (주)코드브릿지엑스` | - -### 금지 사항 - -``` -❌ "주일/경동" — 문서, 슬라이드, 푸터 어디에도 사용 금지 -❌ "주일", "경동" 단독 사용 금지 -❌ 내부 제조사(주일/경동) 이름을 외부 문서에 노출 금지 -``` - -> **배경**: 주일/경동은 SAM을 기반으로 만든 내부 제조업체 이름이며, 대외 문서에 노출되어서는 안 된다. -> 모든 대외 문서의 회사명은 **(주)코드브릿지엑스**를 사용한다. - -### SAM BI (Brand Identity) 이미지 - -**프로젝트 내 경로**: `/home/aweso/sam/docs/assets/bi/` - -| 파일 | 용도 | 배경 | -|------|------|------| -| `sam_bi_black.png` | 밝은 배경 슬라이드 | 투명 배경, 검정 로고 | -| `sam_bi_white.png` | 다크 배경 슬라이드 | 투명 배경, 흰색 로고 | -| `sam_bi_blue.png` | 청색 테마 슬라이드 | 투명 배경, 파란 로고 | -| `sam_bi_green.png` | 녹색 테마 슬라이드 | 녹색 배경, 흰색 로고 | -| `sam_bi_red.png` | 적색/대외비 슬라이드 | 적색 배경, 흰색 로고 | -| `sam_bi_orange.png` | 주황 포인트 슬라이드 | 주황 배경, 흰색 로고 | -| `sam_bi_purple.png` | 보라 테마 슬라이드 | 보라 배경, 흰색 로고 | - -### PPT 슬라이드 제작 시 적용 규칙 - -1. **표지(slide-01)에 BI 로고 필수** — 배경색에 맞는 BI 이미지 사용 -2. **푸터에 회사명**: `(주)코드브릿지엑스` (주일/경동 절대 금지) -3. **BI 로고 + "SAM" 텍스트** 조합 사용 권장 -4. **배경색별 BI 선택**: - - 다크 배경 → `sam_bi_white.png` - - 밝은 배경 → `sam_bi_black.png` - - 테마 컬러 배경 → 해당 색상 BI (green, blue, red 등) - -### 체크리스트 (PPT 제작 시) - -- [ ] 회사명: (주)코드브릿지엑스 사용 -- [ ] "주일/경동" 미포함 확인 -- [ ] 표지에 SAM BI 로고 포함 -- [ ] 푸터에 (주)코드브릿지엑스 표기 -- [ ] 배경색에 맞는 BI 색상 선택 diff --git a/INDEX.md b/INDEX.md index e8f6b14..66e2c6c 100644 --- a/INDEX.md +++ b/INDEX.md @@ -1,30 +1,26 @@ # SAM 프로젝트 문서 인덱스 -> **Claude Code 작업 전 필수 확인** - 작업 유형에 맞는 문서를 먼저 읽고 시작하세요. +> **Claude Code 작업 전 필수 확인** — 작업 유형에 맞는 문서를 먼저 읽고 시작하세요. +> **최종 갱신**: 2026-02-27 --- -## 🎯 작업별 필수 문서 (반드시 먼저 확인) +## 🎯 작업별 필수 문서 | 작업 유형 | 필수 문서 | 용도 | |----------|----------|------| -| **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단계 로직 | +| **운영 배포** | `plans/production-deployment-plan.md` | 운영 환경 배포 계획 | +| **서버 운영** | `deploys/ops-manual/README.md` | 서버 운영 매뉴얼 | | **MES 개발** | `projects/mes/README.md` | MES 프로젝트 개요 | --- @@ -33,27 +29,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 +97,54 @@ 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 구현 시 | -### 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 전용) | + +--- + +### guides/ — 구현 가이드 > 특정 기능 구현을 위한 단계별 매뉴얼 | 문서 | 설명 | 필수 확인 시점 | @@ -103,180 +153,184 @@ 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 분석 최종본 | - -### contracts/ - 전자계약서 버전 관리 -> DOCX 배포본 + Markdown 추적본 + 자동화 스크립트 - -| 문서 | 설명 | -|------|------| -| [CHANGELOG.md](contracts/CHANGELOG.md) | 전체 개정이력 | -| [revisions.json](contracts/revisions.json) | 개정 데이터 | -| [docx/](contracts/docx/) | DOCX 배포본 (전자서명용 4종, 바로 사용 가능) | -| [markdown/](contracts/markdown/) | Markdown 추적본 (Git diff용 4종) | -| [scripts/extract_to_markdown.py](contracts/scripts/extract_to_markdown.py) | DOCX → Markdown 추출 | -| [scripts/sync_check.py](contracts/scripts/sync_check.py) | DOCX ↔ Markdown 동기화 검증 | - -### plans/ - 개발 계획 -> 임시 개발 계획 문서 (작업 완료 후 정리 → 삭제) - -| 문서 | 설명 | -|------|------| -| [SAM_ERP_Storyboard_D1.4_260116.md](plans/SAM_ERP_Storyboard_D1.4_260116.md) | ERP 전체 스토리보드 D1.4 (167p PDF → 마크다운 변환, 14개 섹션 146개 화면) | -| [SAM_ERP_Storyboard_D1.4.md](plans/SAM_ERP_Storyboard_D1.4.md) | ERP 스토리보드 D1.4 AI 최적화 버전 (구조화된 한글 마크다운, 15개 섹션) | -| [SAM_ERP_회계관리_Storyboard_D1.6.md](plans/SAM_ERP_회계관리_Storyboard_D1.6.md) | ERP 회계관리 스토리보드 D1.6 (65p PDF → 마크다운 변환) | -| [SAM_General_Rule_Storyboard_D1.0.md](plans/SAM_General_Rule_Storyboard_D1.0.md) | General Rule 스토리보드 D1.0 (43p PDF → 마크다운 변환, UIUX 공통 규칙) | -| [production-deployment-plan.md](plans/production-deployment-plan.md) | 운영 환경 배포 계획 (CI/CD, 서버 아키텍처) | -| **[integrated-master-plan.md](plans/integrated-master-plan.md)** | **통합 개선 계획 — 제품코드 추적성 + 검사 단위 구조 (마스터)** | -| [integrated-phase-0-1.md](plans/integrated-phase-0-1.md) | 통합 Phase 0-1: 사전 조사 + product_code 전파 수정 | -| [integrated-phase-2.md](plans/integrated-phase-2.md) | 통합 Phase 2: 절곡 검사 분석/설계 + 견적/품질 개선 | -| [integrated-phase-3.md](plans/integrated-phase-3.md) | 통합 Phase 3: 절곡 검사 동적 구현 | -| [integrated-test-scenarios.md](plans/integrated-test-scenarios.md) | 통합 계획 기능 단위 테스트 시나리오 (11개 FU) | -| [product-code-traceability-plan.md](plans/product-code-traceability-plan.md) | 제품코드 추적성 계획 (아카이브 — 통합 계획 참조) | -| [document-system-improvement-plan.md](plans/document-system-improvement-plan.md) | 검사 단위 구조 정비 계획 (아카이브 — 통합 계획 참조) | - -### features/ - 기능별 문서 - -| 문서 | 설명 | -|------|------| -| [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 (알림톡/친구톡) 연동 | -| [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) | -| [hr/hr-api-analysis.md](features/hr/hr-api-analysis.md) | HR API 분석 (근태/직원/부서) | -| [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용) | - -### projects/ - 프로젝트별 문서 - -| 프로젝트 | 문서 | 설명 | -|---------|------|------| -| **MES** | [README.md](projects/mes/README.md) | MES 프로젝트 개요 | -| **MES** | [MES_PROJECT_ROADMAP.md](projects/mes/MES_PROJECT_ROADMAP.md) | 개발 로드맵 | -| **Legacy** | [draw-module.md](projects/legacy-5130/draw-module.md) | 레거시 드로우 모듈 | - -### history/ - 히스토리 - -| 기간 | 문서 | -|------|------| -| **2025-11** | [item-master-gap-analysis.md](history/2025-11/item-master-gap-analysis.md), [item-master-spec.md](history/2025-11/item-master-spec.md), [front-requests/](history/2025-11/front-requests/), [item-master-archived/](history/2025-11/item-master-archived/) | -| **2025-09** | [checkpoint.md](history/2025-09/checkpoint.md), [database-schema.md](history/2025-09/database-schema.md) | -| **Roadmaps** | [december-2025.md](history/roadmaps/december-2025.md) | +| [analysis/bom-item-mapping-analysis.md](data/analysis/bom-item-mapping-analysis.md) | BOM-품목 매핑 분석 | --- -## 🏗️ 서브프로젝트 문서 +### 서브프로젝트 문서 각 서브프로젝트는 독립적인 `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/architecture/README.md b/architecture/README.md deleted file mode 100644 index e6eec46..0000000 --- a/architecture/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Architecture (아키텍처 & 설계 원칙) - -> 시스템 설계와 아키텍처 결정의 근간 - **"왜 이렇게 설계하는가"** - -## 목적 -- 일관된 아키텍처 결정 기준 제공 -- 기술 부채 방지 -- 확장성과 유지보수성 확보 - -## 문서 목록 - -| 문서 | 설명 | 필수 확인 시점 | -|------|------|--------------| -| [system-overview.md](system-overview.md) | 전체 시스템 아키텍처 | 새 기능 설계 전 | -| [security-policy.md](security-policy.md) | 인증/인가, 보안 규칙 | 보안 관련 작업 전 | - -## 관련 폴더 -- [standards/](../standards/) - 개발 표준 (어떻게 코드를 작성할 것인가) -- [rules/](../rules/) - 비즈니스 규칙 (무엇이 유효한 데이터인가) -- [specs/](../specs/) - 기술 스펙 (무엇을 구현할 것인가) \ No newline at end of file diff --git a/architecture/scaling-roadmap-10k-tenants.md b/architecture/scaling-roadmap-10k-tenants.md deleted file mode 100644 index 35c204a..0000000 --- a/architecture/scaling-roadmap-10k-tenants.md +++ /dev/null @@ -1,214 +0,0 @@ -# SAM 10,000 테넌트 스케일링 로드맵 - -> **작성일**: 2026-02-22 -> **성격**: 가상 시나리오 — 세계 최고 수준 엔지니어링 팀이 설계한다는 가정 - ---- - -## 1. 현재 상태 진단 - -### 1.1 현재 아키텍처 요약 - -``` -브라우저 → Nginx → PHP-FPM(20 workers) → Laravel → MySQL 8.0 (단일) -서버: 2코어/3.8GB RAM | 배포: 수동 git pull | 모니터링: 없음 | 캐시: 없음 -``` - -### 1.2 핵심 병목 지점 - -| 영역 | 현재 | 10,000 테넌트 시 문제 | 심각도 | -|------|------|---------------------|--------| -| DB | MySQL 단일 | 커넥션 폭발, 슬로우 쿼리 | 치명적 | -| 컴퓨팅 | FPM 20워커 | 동시 요청 20개 제한 | 치명적 | -| 캐시 | 없음 | 모든 요청이 DB 직행 | 치명적 | -| 큐 | DB 드라이버 | 큐 자체가 DB 압박 | 심각 | -| 검색 | SQL LIKE | 219개 테이블 풀스캔 | 심각 | -| 배포 | 수동 git pull | 다운타임, 롤백 불가 | 높음 | -| 모니터링 | 없음 | 장애 인지 불가 | 높음 | - -### 1.3 가장 먼저 죽는 곳 - -- 동시 사용자 **20명** → FPM 워커 전부 점유 → 504 Timeout -- 동시 사용자 **200명** → MySQL `max_connections`(151) 고갈 -- 테넌트 **1,000개** → 권한 UNION 3개 쿼리가 매 요청마다 실행 - ---- - -## 2. 5단계 로드맵 개요 - -``` -Phase 1 (0~3개월) 캐시 + 모니터링 + 서버 업그레이드 → 100 테넌트 -Phase 2 (3~6개월) DB 복제 + K8s + S3 + 검색 엔진 → 1,000 테넌트 -Phase 3 (6~9개월) 마이크로서비스 + 이벤트 아키텍처 → 3,000 테넌트 -Phase 4 (9~12개월) DB 샤딩 + 테넌트 티어링 + 멀티리전 → 10,000 테넌트 -Phase 5 (12~18개월) 관측성 고도화 + 카오스 엔지니어링 → 10,000+ 테넌트 -``` - ---- - -## 3. Phase 1: 기초 체력 (0~3개월) → 100 테넌트 - -### 3.1 Redis 도입 (최우선) - -| 대상 | 캐시 TTL | 효과 | -|------|---------|------| -| 세션 저장소 | 2시간 | DB 세션 테이블 부하 제거 | -| 권한 캐시 | 5분 | UNION 3개 쿼리 제거 (매 요청) | -| 메뉴 트리 | 10분 | 중첩 쿼리 제거 | -| 공통 코드 | 1시간 | `common_codes` 반복 조회 제거 | -| Laravel 큐 | - | `database` → `redis` 드라이버 전환 | - -**예상 효과**: DB 쿼리 **60~70% 감소**, 응답 시간 **3~5배 개선**. - -### 3.2 모니터링 구축 - -Grafana + Prometheus + Laravel Telescope + MySQL slow_log. - -**핵심 알림**: FPM 워커 사용률 >80%, MySQL 커넥션 >100, 응답 시간 >2초, 큐 적체 >1000건 → Slack 알림. - -### 3.3 서버 업그레이드 + CI/CD - -| 항목 | 현재 | Phase 1 | -|------|------|---------| -| CPU/RAM | 2코어/3.8GB | 8코어/32GB | -| 스토리지 | HDD | NVMe SSD | -| FPM | 20 워커 | 100 워커 | -| 배포 | 수동 git pull | Jenkins CI/CD (무중단 rolling) | - ---- - -## 4. Phase 2: 수평 확장 (3~6개월) → 1,000 테넌트 - -### 4.1 아키텍처 - -``` -브라우저 → LB(L7) → App Server ×N → Redis Cluster - → MySQL Primary + Replica ×2 - → S3 + CDN (정적/업로드 파일) -``` - -### 4.2 핵심 변경 - -| 영역 | 변경 | 효과 | -|------|------|------| -| **K8s** | HPA 기반 오토스케일링 (API 3~10 pods) | 트래픽에 따라 자동 확장 | -| **DB R/W 분리** | `config/database.php`에 read/write 설정 | 읽기 부하 80% Replica로 분산 | -| **파일 → S3** | Laravel Filesystem → S3 + CloudFront | 서버 간 파일 공유, CDN 가속 | -| **검색 엔진** | SQL LIKE → Meilisearch | 밀리초 응답, 형태소 분석, 오타 허용 | - ---- - -## 5. Phase 3: 마이크로서비스 (6~9개월) → 3,000 테넌트 - -### 5.1 서비스 분리 - -``` -모놀리스(sam-api) → Auth | Product | Order | MES | Finance | Notification -``` - -**분리 순서**: ① 알림 (독립적, 비동기) → ② MES (변경 빈도 높음) → ③ 인증 (가용성 최우선) - -### 5.2 이벤트 기반 전환 - -동기 호출 체인을 이벤트 발행으로 전환한다. 주문 생성 시 재고 차감/알림/회계를 비동기 처리. - -**메시지 브로커**: Redis Streams 또는 RabbitMQ. 응답 시간 2초 → 200ms. - -### 5.3 API Gateway - -Kong/Traefik으로 테넌트별 Rate Limiting, 인증 검증, 요청 라우팅, 응답 캐싱 통합. - ---- - -## 6. Phase 4: 대규모 멀티테넌시 (9~12개월) → 10,000 테넌트 - -### 6.1 DB 샤딩 - -``` -Shard Router (tenant_id 기반) → Shard 0 | Shard 1 | Shard 2 ... - 각 Shard = Primary + Replica -``` - -`tenant_id`가 파티션 키이므로 크로스 샤드 조인 불필요 — SAM의 강점. - -### 6.2 테넌트 티어링 - -| Tier | 자원 | SLA | Rate Limit | -|------|------|-----|-----------| -| Enterprise | 전용 DB/Redis/Pod | 99.99% | 1000/분 | -| Business | 공유 (높은 우선순위) | 99.9% | 300/분 | -| Standard | 공유 | 99.5% | 60/분 | - -### 6.3 멀티리전 - -한국(Primary) + 일본/동남아(Secondary) 리전. DB 복제 + Global Load Balancer로 지리적 라우팅. - ---- - -## 7. Phase 5: 엔터프라이즈 성숙 (12~18개월) → 10,000+ - -| 영역 | 도입 | 목적 | -|------|------|------| -| **관측성** | Jaeger(분산추적) + Loki(중앙로그) + PagerDuty | 전체 서비스 체인 추적 | -| **카오스 엔지니어링** | DB 다운, Pod Kill, 네트워크 지연 주입 | 복원력 검증 | -| **데이터 파이프라인** | CDC(Debezium) → 데이터 웨어하우스 | 운영 DB에서 분석 쿼리 분리 | -| **배포** | Blue-Green + Canary (5% → 100%) | 30초 이내 롤백 | - ---- - -## 8. 기술 스택 진화 요약 - -| 영역 | 현재 | Phase 1 | Phase 2 | Phase 4 | -|------|------|---------|---------|---------| -| 서버 | 단일 2코어 | 단일 8코어 | K8s 3+ 노드 | 멀티리전 | -| DB | MySQL 단일 | + 쿼리 최적화 | Primary + Replica ×2 | Shard ×N | -| 캐시 | 없음 | Redis 단일 | Redis Cluster | 테넌트별 격리 | -| 큐 | DB | Redis | Redis | 티어별 큐 | -| 배포 | 수동 | Jenkins CI/CD | K8s Rolling | Canary | -| 모니터링 | 없음 | Grafana | + Telescope | + 카오스 | - ---- - -## 9. 가장 중요한 3가지 - -**1. Redis (=산소)**: 캐시 없이 10,000 테넌트는 **절대 불가능**. 권한 UNION 쿼리 3개 + 메뉴 + 세션이 매 요청마다 실행된다. Redis 하나로 DB 부하 60% 감소. - -**2. DB R/W 분리 (=심장)**: ERP 읽기:쓰기 = 8:2. Replica 2대 추가로 DB 부하 1/3 분산. Laravel `config/database.php` 변경만으로 적용. - -**3. 관측성 (=눈)**: 모니터링 없이 스케일링은 눈 감고 운전하는 것. 슬로우 쿼리 + 응답 시간 + 알림부터 시작. - ---- - -## 10. SAM 특수 고려사항 - -### 10.1 tenant_id 기반 격리 - -- **강점**: `BelongsToTenant` 스코프 일관 적용, 크로스 테넌트 조인 불필요 → 샤딩에 유리 -- **개선 필요**: `tenant_id` 인덱스 첫 번째 컬럼 여부 전수 검사, `deleted_at` 누적 데이터 파티셔닝 - -### 10.2 권한 시스템 최적화 - -3중 UNION 쿼리가 매 요청 실행된다. 개선: ① Redis 권한 캐시(TTL 5분) → ② 변경 시 해당 사용자 캐시만 무효화 → ③ JWT 클레임에 권한 포함(DB 조회 0회). - -### 10.3 219개 테이블 샤딩 분류 - -| 분류 | 예시 | 처리 | -|------|------|------| -| 테넌트 데이터 | orders, products | 샤딩 대상 | -| 시스템 공통 | permissions, common_codes | 공유 DB 유지 | -| 감사 로그 | audit_logs | 별도 시계열 DB | - ---- - -## 관련 문서 - -| 문서 | 설명 | -|------|------| -| [system-overview.md](system-overview.md) | 현재 시스템 아키텍처 | -| [security-policy.md](security-policy.md) | 현재 보안 구조 | -| [docker-setup.md](../specs/docker-setup.md) | 현재 Docker 구성 | -| [server-how-it-works.md](../guides/server-how-it-works.md) | 서버 동작 원리 | - ---- - -**최종 업데이트**: 2026-02-22 diff --git a/architecture/security-policy.md b/architecture/security-policy.md deleted file mode 100644 index c6698f2..0000000 --- a/architecture/security-policy.md +++ /dev/null @@ -1,784 +0,0 @@ -# SAM API 보안 가이드 - -## 개요 - -SAM API는 다층 보안 구조를 통해 무단 접근과 악의적 공격으로부터 시스템을 보호합니다. - -**최종 업데이트:** 2025-12-26 - ---- - -## 보안 아키텍처 - -### 다층 방어 구조 (Defense in Depth) - -``` -┌─────────────────────────────────────────────────┐ -│ Layer 1: Nginx (L7 Application Layer) │ -│ - 악의적 경로 패턴 차단 │ -│ - 의심스러운 User-Agent 차단 │ -│ - Rate Limiting (Nginx 레벨) │ -└─────────────────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────────────────┐ -│ Layer 2: Laravel Rate Limiting │ -│ - IP 기반 속도 제한 (10회/분) │ -│ - API Key 없는 요청 차단 │ -└─────────────────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────────────────┐ -│ Layer 3: API Key 검증 (글로벌 미들웨어) │ -│ - 모든 요청 API Key 필수 │ -│ - 화이트리스트 라우트 제외 │ -│ - 보안 로그 자동 기록 │ -└─────────────────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────────────────┐ -│ Layer 4: Sanctum 토큰 인증 │ -│ - Bearer 토큰 검증 │ -│ - 사용자 컨텍스트 설정 │ -│ - 테넌트 격리 │ -└─────────────────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────────────────┐ -│ Layer 5: 권한 검증 (Permission Check) │ -│ - 메뉴 기반 권한 체크 │ -│ - Role 기반 접근 제어 │ -└─────────────────────────────────────────────────┘ -``` - ---- - -## Layer 1: Nginx 보안 - -### 악의적 경로 패턴 차단 - -**위치:** `docker/nginx/nginx.conf` - -```nginx -# 경로 탐색 공격 차단 -if ($request_uri ~* "(\.\.\/|\.\.\\|etc\/passwd|\.env|\.git|\.htaccess|\.sql|@fs\/)") { - return 403; -} -``` - -**차단 패턴:** -- `../`, `..\` - 디렉토리 탐색 공격 -- `etc/passwd` - 시스템 파일 접근 시도 -- `.env` - 환경 변수 파일 접근 -- `.git`, `.htaccess`, `.sql` - 민감한 파일 접근 -- `@fs/` - Vite 경로 탐색 공격 - -**응답:** 403 Forbidden - -### 의심스러운 User-Agent 차단 - -```nginx -# 보안 스캔 도구 차단 -if ($http_user_agent ~* "(sqlmap|nikto|nmap|masscan|metasploit|nessus)") { - return 403; -} -``` - -**차단 도구:** -- sqlmap - SQL 인젝션 스캐너 -- nikto - 웹 서버 스캐너 -- nmap - 포트 스캐너 -- masscan - 대량 포트 스캐너 -- metasploit - 침투 테스트 프레임워크 -- nessus - 취약점 스캐너 - -**응답:** 403 Forbidden - ---- - -## Layer 2: Rate Limiting - -### Laravel Rate Limiter - -**위치:** `app/Http/Middleware/ApiRateLimiter.php` - -```php -// IP 기반 속도 제한 -$key = 'api-key-attempts:' . $request->ip(); - -if ($this->limiter->tooManyAttempts($key, 10)) { - return response()->json([ - 'message' => 'Too many attempts. Please try again later.', - 'retry_after' => $seconds, - ], 429); -} - -$this->limiter->hit($key, 60); // 1분 동안 유지 -``` - -**설정:** -- **제한:** 10회/분 (IP별) -- **대상:** API Key 없는 요청 -- **유지 시간:** 60초 -- **응답 코드:** 429 Too Many Requests - -**로그:** -```php -Log::warning('API Rate Limit Exceeded', [ - 'ip' => $request->ip(), - 'uri' => $request->getRequestUri(), - 'retry_after' => $seconds, -]); -``` - ---- - -## Layer 3: API Key 인증 - -### 글로벌 미들웨어 - -**위치:** `bootstrap/app.php` - -```php -$middleware->append(ApiRateLimiter::class); // 1. Rate Limiting -$middleware->append(ApiKeyMiddleware::class); // 2. API Key 검증 -``` - -**실행 순서:** Rate Limiting → API Key 검증 - -### API Key 검증 로직 - -**위치:** `app/Http/Middleware/ApiKeyMiddleware.php` - -```php -// 1. 화이트리스트 체크 -$publicRoutes = [ - 'api/v1/login', - 'api/v1/signup', - 'api/v1/register', - 'api/v1/refresh', - 'api/v1/debug-apikey', - 'api-docs', // Swagger UI - 'api-docs/*', // Swagger 하위 경로 - 'docs/api-docs.json', // Swagger JSON - 'up', // Health check -]; - -// 2. API Key 검증 -$apiKey = $request->header('X-API-KEY'); -$validApiKey = DB::table('api_keys') - ->where('key', $apiKey) - ->where('is_active', true) - ->exists(); - -// 3. 보안 로그 기록 -if (!$validApiKey) { - Log::warning('Unauthorized API access attempt', [ - 'ip' => $request->ip(), - 'uri' => $request->getRequestUri(), - 'method' => $request->method(), - 'user_agent' => $request->userAgent(), - ]); -} -``` - -### 화이트리스트 (인증 제외 라우트) - -**공개 엔드포인트:** -- `api/v1/login` - 로그인 -- `api/v1/signup` - 회원가입 -- `api/v1/register` - 테넌트 등록 -- `api/v1/refresh` - 토큰 갱신 -- `api/v1/debug-apikey` - API Key 디버깅 -- `api-docs/*` - Swagger UI -- `docs/api-docs.json` - Swagger JSON -- `up` - Health check - -**특징:** -- 와일드카드 지원 (`fnmatch()` 사용) -- 공개 라우트는 로깅 제외 -- API Key 검증 스킵 - -### 보안 로그 - -**로그 레벨:** -- **Log::info** - 정상 API 요청 -- **Log::warning** - 무단 접근 시도 - -**로그 내용:** -```json -{ - "ip": "213.136.76.215", - "uri": "/@fs/etc/passwd", - "method": "GET", - "user_agent": "Mozilla/5.0 ..." -} -``` - -**민감 정보 제외:** -- `password` -- `password_confirmation` - ---- - -## Layer 4: Sanctum 토큰 인증 - -### 토큰 구조 - -**액세스 토큰:** -- 만료 시간: 2시간 (120분) -- 용도: API 호출 인증 -- 형식: `{token_id}|{plain_text_token}` - -**리프레시 토큰:** -- 만료 시간: 7일 (10080분) -- 용도: 액세스 토큰 갱신 -- 특징: 일회성 사용 (사용 후 삭제) - -### 토큰 갱신 플로우 - -``` -1. 클라이언트: POST /api/v1/refresh - Headers: X-API-KEY, Authorization: Bearer {refresh_token} - -2. 서버: 리프레시 토큰 검증 - - 유효성 체크 - - 만료 시간 체크 - - 사용자 확인 - -3. 서버: 기존 리프레시 토큰 삭제 - - 일회성 사용 보장 - -4. 서버: 새 토큰 발급 - - 새 액세스 토큰 생성 - - 새 리프레시 토큰 생성 - -5. 응답: - { - "access_token": "...", - "refresh_token": "...", - "expires_in": 7200, - "expires_at": "2025-11-13 21:30:00" - } -``` - -### 토큰 만료 에러 처리 - -**위치:** `app/Exceptions/Handler.php` - -```php -if ($exception instanceof AuthenticationException) { - $bearerToken = $request->bearerToken(); - if ($bearerToken) { - $token = PersonalAccessToken::findToken($bearerToken); - if ($token && $token->expires_at && $token->expires_at->isPast()) { - return response()->json([ - 'success' => false, - 'message' => __('error.token_expired'), - 'error_code' => 'TOKEN_EXPIRED', - ], 401); - } - } -} -``` - -**프론트엔드 처리:** -```javascript -if (response.error_code === 'TOKEN_EXPIRED') { - // 자동 리프레시 토큰으로 재발급 - const newTokens = await refreshToken(refreshToken); - // 원래 요청 재시도 - return retryRequest(originalRequest, newTokens.access_token); -} -``` - ---- - -## Layer 5: 권한 검증 (Permission System) - -### 권한 시스템 개요 - -SAM은 **Spatie Permission** 패키지를 기반으로 한 다층 권한 시스템을 사용합니다. - -**3단계 권한 구조:** -``` -┌────────────────────────────────────────┐ -│ 1. 사용자 역할 권한 │ -│ User → Role → Permissions │ -│ (model_has_roles → role_has_perms) │ -└────────────────────────────────────────┘ - + -┌────────────────────────────────────────┐ -│ 2. 사용자 직접 권한 │ -│ User → Permissions │ -│ (model_has_permissions) │ -└────────────────────────────────────────┘ - + -┌────────────────────────────────────────┐ -│ 3. 부서 역할 권한 │ -│ User → Department → Role → Perms │ -│ (department_user → model_has_roles) │ -└────────────────────────────────────────┘ - ↓ -┌────────────────────────────────────────┐ -│ UNION (중복 제거) │ -│ → 최종 사용자 권한 목록 │ -└────────────────────────────────────────┘ -``` - -**특징:** -- 멀티테넌트 지원 (tenant_id로 격리) -- 메뉴 기반 세분화된 권한 -- 다형성(Polymorphic) 구조로 유연한 확장 -- Permission Override로 임시/긴급 권한 제어 - ---- - -### 권한 패턴 및 타입 - -**권한 명명 규칙:** -``` -menu:{menu_id}.{permission_type} -``` - -**권한 타입 (7가지):** - -| 타입 | 약자 | 설명 | 예시 | -|------|------|------|------| -| view | V | 조회 | 목록/상세 보기 | -| create | C | 생성 | 신규 데이터 등록 | -| update | U | 수정 | 기존 데이터 편집 | -| delete | D | 삭제 | 데이터 삭제 | -| approve | A | 승인 | 워크플로우 승인 | -| export | E | 내보내기 | Excel/PDF 다운로드 | -| manage | M | 관리 | 전체 관리 권한 | - -**권한 예시:** -``` -menu:1.view → 대시보드 보기 -menu:2.create → 제품 생성 -menu:2.update → 제품 수정 -menu:2.delete → 제품 삭제 -menu:3.approve → 주문 승인 -menu:4.export → 재고 내보내기 -menu:5.manage → 사용자 관리 -``` - ---- - -### 권한 조회 로직 - -**구현 위치:** -- **API:** `app/Services/MemberService.php` - `getUserInfoForLogin()` -- **Admin:** `app/Filament/Resources/Users/Tables/UsersTable.php` - `getAccessibleMenusCount()` - -**권한 조회 쿼리 구조:** - -```php -// 1. 사용자 역할 권한 -$userRolePermissions = DB::table('model_has_roles') - ->join('role_has_permissions', 'model_has_roles.role_id', '=', 'role_has_permissions.role_id') - ->join('permissions', 'role_has_permissions.permission_id', '=', 'permissions.id') - ->where('model_has_roles.model_type', User::class) - ->where('model_has_roles.model_id', $userId) - ->where('model_has_roles.tenant_id', $tenantId) - ->where('permissions.name', 'like', 'menu:%.view') - ->select('permissions.name'); - -// 2. 사용자 직접 권한 -$userDirectPermissions = DB::table('model_has_permissions') - ->join('permissions', 'model_has_permissions.permission_id', '=', 'permissions.id') - ->where('model_has_permissions.model_type', User::class) - ->where('model_has_permissions.model_id', $userId) - ->where('model_has_permissions.tenant_id', $tenantId) - ->where('permissions.name', 'like', 'menu:%.view') - ->select('permissions.name'); - -// 3. 부서 역할 권한 -$departmentRolePermissions = DB::table('department_user') - ->join('model_has_roles', function ($join) { - $join->on('department_user.department_id', '=', 'model_has_roles.model_id') - ->where('model_has_roles.model_type', '=', Department::class); - }) - ->join('role_has_permissions', 'model_has_roles.role_id', '=', 'role_has_permissions.role_id') - ->join('permissions', 'role_has_permissions.permission_id', '=', 'permissions.id') - ->where('department_user.user_id', $userId) - ->where('department_user.tenant_id', $tenantId) - ->where('permissions.name', 'like', 'menu:%.view') - ->select('permissions.name'); - -// 4. 모든 권한 통합 (UNION + 중복 제거) -$allPermissions = $userRolePermissions - ->union($userDirectPermissions) - ->union($departmentRolePermissions) - ->pluck('name') - ->toArray(); -``` - -**권한 파싱:** -```php -// menu:123.view → 메뉴 ID 123 추출 -foreach ($allPermissions as $permName) { - if (preg_match('/^menu:(\d+)\.view$/', $permName, $matches)) { - $allowedMenuIds[] = (int) $matches[1]; - } -} -``` - ---- - -### Permission Override (우선순위 제어) - -**시간 기반 권한 제어:** - -```php -// permission_overrides 테이블 -[ - 'tenant_id' => 1, - 'model_type' => 'App\Models\Members\User', - 'model_id' => 123, - 'permission_id' => 456, - 'effect' => 1, // 1=ALLOW, -1=DENY - 'effective_from' => '2025-11-13 00:00:00', - 'effective_to' => '2025-11-20 23:59:59', -] -``` - -**우선순위:** -1. **Override DENY** (-1) - 최우선 차단 -2. **Override ALLOW** (1) - 명시적 허용 -3. **Base Permission** - 역할/부서/직접 권한 - -**최종 권한 계산:** -```php -foreach ($allMenuPermissions as $permName) { - if (preg_match('/^menu:(\d+)\.view$/', $permName, $matches)) { - $menuId = (int) $matches[1]; - - // Override DENY 체크 (강제 차단) - if (isset($overrides[$permName]) && $overrides[$permName]->effect === -1) { - continue; // 이 메뉴는 차단됨 - } - - // Override ALLOW 또는 기본 권한 - if ( - (isset($overrides[$permName]) && $overrides[$permName]->effect === 1) || - in_array($permName, $basePermissions, true) - ) { - $allowedMenuIds[] = $menuId; - } - } -} -``` - -**사용 사례:** -- **임시 권한 부여:** 프로젝트 기간 동안만 특정 메뉴 접근 허용 -- **긴급 권한 차단:** 보안 사고 발생 시 즉시 권한 제거 -- **휴가 기간 제한:** 특정 기간 동안 권한 자동 차단 -- **시간대별 접근 제어:** 업무 시간에만 권한 부여 - ---- - -### 메뉴별 권한 매트릭스 뷰 - -**Admin 패널:** `http://admin.sam.kr/admin/permissions` - -**테이블 구조:** - -| 메뉴 ID | 메뉴명 | V (조회) | C (생성) | U (수정) | D (삭제) | A (승인) | E (내보내기) | M (관리) | -|---------|--------|----------|----------|----------|----------|----------|-------------|----------| -| 1 | 대시보드 | 홍길동, 김철수 | - | - | - | - | - | - | -| 2 | 제품 관리 | 홍길동, 김철수 | 홍길동 | 홍길동 | 관리자 | - | 김철수 | 관리자 | -| 3 | 주문 관리 | 전체팀 | 영업팀 | 영업팀 | 관리자 | 관리자 | 회계팀 | 관리자 | - -**특징:** -- 각 Row = 하나의 메뉴 -- 각 권한 타입별 Column에 해당 권한을 가진 사용자 목록 표시 -- 사용자 배지에 마우스 오버 시 `user_id` 툴팁 표시 -- 권한 없는 경우 `-` 표시 -- 3가지 권한 소스 (역할/부서/직접) 모두 통합하여 표시 - -**구현 코드:** -```php -// app/Filament/Resources/Permissions/Tables/PermissionsTable.php -protected static function getUsersWithPermission(int $menuId, string $permissionType): string -{ - $permissionName = "menu:{$menuId}.{$permissionType}"; - - // 3가지 권한 소스 UNION - $userIds = $userRoleQuery - ->union($userDirectQuery) - ->union($departmentRoleQuery) - ->pluck('user_id') - ->unique() - ->toArray(); - - // 사용자 배지 HTML 생성 - $users = User::whereIn('id', $userIds)->orderBy('name')->get(); - foreach ($users as $user) { - $badges[] = sprintf( - '%s', - htmlspecialchars($user->user_id), - htmlspecialchars($user->name) - ); - } - - return implode(', ', $badges); -} -``` - ---- - -### 권한 할당 방법 - -**1. 역할에 권한 할당:** -```php -$role = Role::findByName('영업팀', 'web'); -$role->givePermissionTo([ - 'menu:2.view', - 'menu:2.create', - 'menu:3.view', -]); -``` - -**2. 사용자에게 직접 권한 할당:** -```php -$user = User::find(123); -$user->givePermissionTo('menu:5.manage'); -``` - -**3. 부서에 역할 할당:** -```php -$department = Department::find(1); -$department->assignRole('영업팀'); -``` - -**4. Permission Override 설정:** -```php -DB::table('permission_overrides')->insert([ - 'tenant_id' => 1, - 'model_type' => User::class, - 'model_id' => 123, - 'permission_id' => 456, - 'effect' => -1, // DENY - 'effective_from' => now(), - 'effective_to' => now()->addDays(7), -]); -``` - ---- - -### 권한 체크 (Controller/Service) - -**CheckPermission Middleware:** -```php -// routes/api.php -Route::get('/products', [ProductController::class, 'index']) - ->middleware(['auth:sanctum', 'permission:menu:2.view']); -``` - -**서비스 레이어:** -```php -if (!auth()->user()->can('menu:2.create')) { - throw new \Exception(__('error.permission_denied'), 403); -} -``` - -**권한 확인 헬퍼:** -```php -// 단일 권한 체크 -auth()->user()->can('menu:2.view'); - -// 여러 권한 중 하나라도 있으면 -auth()->user()->hasAnyPermission(['menu:2.view', 'menu:2.manage']); - -// 모든 권한 필요 -auth()->user()->hasAllPermissions(['menu:2.view', 'menu:2.create']); -``` - ---- - -## 보안 모니터링 - -### 로그 파일 - -**1. 보안 로그** -```bash -# 무단 접근 시도 -tail -f storage/logs/laravel.log | grep "Unauthorized API access attempt" - -# Rate Limit 초과 -tail -f storage/logs/laravel.log | grep "API Rate Limit Exceeded" -``` - -**2. Nginx 로그** -```bash -# 접근 로그 -tail -f /var/log/nginx/api.sam.kr_access.log - -# 에러 로그 (403 차단) -tail -f /var/log/nginx/api.sam.kr_error.log -``` - -### 공격 패턴 분석 - -**자주 발생하는 공격:** - -1. **경로 탐색 (Path Traversal)** - ``` - GET /@fs/etc/passwd - GET /../../../etc/passwd - GET /api/../.env - ``` - **대응:** Nginx에서 403 차단 - -2. **보안 스캔** - ``` - User-Agent: sqlmap/1.0 - User-Agent: nikto/2.1.5 - ``` - **대응:** Nginx User-Agent 필터링 - -3. **무차별 대입 (Brute Force)** - ``` - POST /api/v1/login (반복) - ``` - **대응:** Rate Limiting (10회/분) - -4. **API Key 누락** - ``` - GET /api/v1/users (X-API-KEY 없음) - ``` - **대응:** 401 Unauthorized + 보안 로그 - ---- - -## 보안 체크리스트 - -### 개발 시 - -- [ ] 모든 API 엔드포인트에 `auth.apikey` 미들웨어 적용 -- [ ] 민감한 정보 로깅 제외 (`password`, `password_confirmation`) -- [ ] FormRequest로 입력 검증 -- [ ] SQL 인젝션 방지 (Eloquent ORM 사용) -- [ ] XSS 방지 (출력 시 이스케이핑) -- [ ] CSRF 보호 (Sanctum 자동 적용) - -### 배포 전 - -- [ ] `.env` 파일 보안 설정 확인 -- [ ] API Key 로테이션 -- [ ] Nginx 보안 규칙 테스트 -- [ ] Rate Limiting 임계값 검토 -- [ ] HTTPS 인증서 유효성 확인 -- [ ] 방화벽 규칙 설정 - -### 운영 중 - -- [ ] 매일 보안 로그 검토 -- [ ] 주간 공격 패턴 분석 -- [ ] 월간 토큰 만료 정책 검토 -- [ ] 분기별 API Key 갱신 -- [ ] 반기별 침투 테스트 - ---- - -## 보안 사고 대응 - -### 1단계: 즉시 조치 - -```bash -# 1. 의심스러운 IP 차단 (Nginx) -# /etc/nginx/conf.d/blocked_ips.conf -deny 213.136.76.215; - -# 2. Nginx 재시작 -sudo systemctl reload nginx - -# 3. 활성 세션 강제 종료 -php artisan sanctum:prune-expired --hours=0 - -# 4. API Key 비활성화 -UPDATE api_keys SET is_active = 0 WHERE key = 'suspicious_key'; -``` - -### 2단계: 로그 분석 - -```bash -# 공격 패턴 분석 -grep "213.136.76.215" /var/log/nginx/api.sam.kr_access.log - -# 영향받은 엔드포인트 확인 -grep "Unauthorized API access attempt" storage/logs/laravel.log | grep "213.136.76.215" - -# 시간대별 요청 횟수 -awk '{print $4}' /var/log/nginx/api.sam.kr_access.log | cut -d: -f1-2 | uniq -c -``` - -### 3단계: 복구 및 강화 - -```bash -# 1. 모든 사용자 비밀번호 초기화 (필요 시) -# 2. 새 API Key 발급 -# 3. 토큰 만료 시간 단축 (임시) -# 4. Rate Limiting 임계값 강화 -# 5. 추가 보안 규칙 적용 -``` - ---- - -## FAQ - -### Q1. API Key는 어디서 발급받나요? - -**A:** 관리자 패널(admin.sam.kr)에서 발급합니다. -```sql --- api_keys 테이블 구조 -id, tenant_id, name, key, is_active, created_at, updated_at -``` - -### Q2. Rate Limiting이 너무 엄격해요. - -**A:** `ApiRateLimiter.php`에서 임계값 조정: -```php -if ($this->limiter->tooManyAttempts($key, 10)) { // 10 → 20으로 변경 -``` - -### Q3. 화이트리스트에 라우트를 추가하려면? - -**A:** `ApiKeyMiddleware.php` 수정: -```php -$publicRoutes = [ - // 기존 라우트... - 'api/v1/public-data', // 추가 -]; -``` - -### Q4. 특정 IP만 허용하려면? - -**A:** Nginx 설정 추가: -```nginx -# 화이트리스트 IP만 허용 -allow 203.0.113.0/24; -allow 198.51.100.50; -deny all; -``` - -### Q5. 토큰 만료 시간을 변경하려면? - -**A:** `.env` 파일 수정: -```env -SANCTUM_ACCESS_TOKEN_EXPIRATION=120 # 2시간 → 4시간 (240) -SANCTUM_REFRESH_TOKEN_EXPIRATION=10080 # 7일 → 14일 (20160) -``` - ---- - -## 참고 문서 - -- [OWASP Top 10](https://owasp.org/www-project-top-ten/) -- [Laravel Security Best Practices](https://laravel.com/docs/12.x/security) -- [Sanctum Documentation](https://laravel.com/docs/12.x/sanctum) -- [Nginx Security Tips](https://nginx.org/en/docs/http/ngx_http_access_module.html) - ---- - -**작성일:** 2025-12-26 -**버전:** 1.0 -**담당자:** SAM Development Team \ No newline at end of file diff --git a/architecture/system-overview.md b/architecture/system-overview.md deleted file mode 100644 index 35f2d58..0000000 --- a/architecture/system-overview.md +++ /dev/null @@ -1,392 +0,0 @@ -# SAM 시스템 아키텍처 - -**업데이트**: 2026-01-28 - ---- - -## 전체 아키텍처 - -SAM은 다중 애플리케이션 Laravel 기반 시스템으로 구성됩니다: - -``` -SAM/ -├── api/ # Laravel 12 REST API (백엔드) -├── mng/ # Laravel 12 + Plain Blade/Tailwind (관리자 패널) -├── react/ # Next.js 15.5.7 프론트엔드 -├── docs/ # 기술 문서 -├── design/ # 디자인 시스템 (Storybook) -├── planning/ # 기획 문서 -├── sales/ # 영업자 사이트 (추후 개발) -├── 5130/ # 레거시 PHP 애플리케이션 -└── docker/ # Docker 설정 -``` - -## 애플리케이션별 상세 - -### mng/ - 관리자 패널 - -**기술 스택:** -- Laravel 12 -- PHP 8.4 -- Pure Blade + Tailwind CSS 3.x -- Sanctum (인증) - -**주요 기능:** -- 테넌트 관리 -- 사용자 관리 -- 권한 관리 (RBAC) -- 메뉴 관리 -- 역할 및 부서 관리 - -**주요 특징:** -- AI 없이 수정 가능한 단순 구조 -- 좌측 사이드바 + 상단 헤더 레이아웃 - -**개발 명령어:** -```bash -php artisan serve # Laravel 서버 -npm run dev # Vite HMR (Tailwind) -``` - -### api/ - REST API - -**기술 스택:** -- Laravel 12 -- PHP 8.4 -- Sanctum (인증) -- l5-swagger 9.0 (API 문서화) - -**주요 기능:** -- RESTful API 엔드포인트 -- Swagger 문서화 -- Multi-tenant 지원 -- 권한 기반 접근 제어 - -**API 구조:** -- **인증**: `/v1/login`, `/v1/logout`, `/v1/signup` -- **사용자**: `/v1/users/*` -- **테넌트**: `/v1/tenants/*` -- **제품**: `/v1/products/*` -- **자재**: `/v1/materials/*` -- **카테고리**: `/v1/categories/*` -- **파일**: `/v1/file/*` -- **디자인**: `/v1/design/*` - -**API 문서:** -- Swagger UI: `http://api.sam.kr/api-docs/index.html` -- JSON Spec: `http://api.sam.kr/docs/api-docs.json` - -### react/ - Next.js 프론트엔드 - -**기술 스택:** -- Next.js 15.5.7 -- React 19.2.1 -- TypeScript 5.x -- Tailwind CSS v4 -- Zustand (상태 관리) -- React Hook Form -- shadcn/ui -- next-intl (i18n) - -**주요 기능:** -- 모던 UI/UX -- Server Components 및 App Router -- 실시간 데이터 동기화 -- 역할 전환 기능 -- 대시보드 -- 다국어 지원 (i18n) - -## Multi-tenant 아키텍처 - -### 데이터 격리 - -- **방식**: `tenant_id` 컬럼 기반 격리 -- **스코프**: BelongsToTenant global scope 자동 적용 -- **모델**: `shared/Models/` 디렉토리의 공통 모델 사용 - -### 테넌트 구조 - -``` -Tenant (회사/조직) - ├── Users (사용자) - ├── Departments (부서) - ├── Roles (역할) - ├── Permissions (권한) - └── Data (비즈니스 데이터) -``` - -### 테넌트 전환 - -- 사용자는 여러 테넌트에 속할 수 있음 (`user_tenants` 테이블) -- 기본 테넌트 설정 가능 -- API: `POST /v1/users/me/tenants/switch` - -## 인증 및 권한 - -### 인증 흐름 - -1. **API Key 인증** (모든 요청) - - 헤더: `X-API-KEY` - - 미들웨어: `auth.apikey` - -2. **사용자 인증** (보호된 라우트) - - 엔드포인트: `POST /v1/login` - - 토큰: Sanctum Bearer Token - - 미들웨어: `auth:sanctum` - -### 권한 시스템 - -**3단계 권한 구조:** -1. **사용자 역할 권한**: User → Role → Permissions -2. **사용자 직접 권한**: User → Permissions -3. **부서 역할 권한**: User → Department → Role → Permissions - -**권한 명명 규칙:** -``` -menu:{menu_id}.{permission_type} -``` - -**권한 타입:** -- `view` - 조회 -- `create` - 생성 -- `update` - 수정 -- `delete` - 삭제 -- `approve` - 승인 -- `export` - 내보내기 -- `manage` - 관리 - -## 데이터베이스 구조 - -### 핵심 테이블 - -**인증 및 권한:** -- `api_keys` - API 키 관리 -- `users` - 사용자 계정 -- `user_tenants` - 사용자-테넌트 관계 -- `permissions` - 권한 정의 -- `roles` - 역할 정의 -- `model_has_permissions/roles` - 권한 할당 - -**멀티테넌트:** -- `tenants` - 테넌트 마스터 -- `tenant_user_profiles` - 테넌트별 사용자 프로필 -- `departments` - 부서 구조 -- `department_user` - 사용자-부서 관계 - -**제품 관리:** -- `categories` - 카테고리 계층 -- `category_fields` - 동적 필드 정의 -- `products` - 제품 카탈로그 -- `product_components` - BOM 관계 -- `materials` - 자재 마스터 - -**디자인 및 제조:** -- `models` - 디자인 모델 -- `model_versions` - 모델 버전 -- `bom_templates` - BOM 템플릿 -- `bom_template_items` - BOM 항목 - -**주문 및 운영:** -- `orders` - 주문/견적 마스터 -- `order_items` - 주문 항목 -- `order_item_components` - 주문 항목 구성 -- `clients` - 고객/벤더 마스터 - -**시스템:** -- `audit_logs` - 감사 로그 (13개월 보관) -- `files` - 다형성 파일 첨부 -- `common_codes` - 공통 코드 - -### 공통 컬럼 패턴 - -모든 테이블에 공통으로 포함: -- `id` - 기본 키 -- `tenant_id` - 테넌트 ID (필수) -- `created_by` - 생성자 ID -- `updated_by` - 수정자 ID -- `deleted_by` - 삭제자 ID -- `created_at`, `updated_at` - 타임스탬프 -- `deleted_at` - Soft Delete - -## 미들웨어 스택 - -**실행 순서:** -1. `ApiRateLimiter` - Rate Limiting -2. `ApiVersionMiddleware` - API 버전 선택 및 폴백 처리 -3. `ApiKeyMiddleware` - API Key 검증 -4. `CheckSwaggerAuth` - Swagger 인증 체크 -5. `CorsMiddleware` - CORS 처리 -6. `CheckPermission` - 권한 검증 -7. `PermMapper` - 권한 매핑 - -## 라우팅 구조 - -### 도메인별 라우트 분리 - -API 라우트는 도메인별로 분리되어 관리됩니다: - -``` -routes/api/ -├── v1/ # v1 API 라우트 (13개 도메인) -│ ├── auth.php # 인증 (login, logout, signup) -│ ├── admin.php # 관리자 기능 -│ ├── users.php # 사용자 관리 -│ ├── tenants.php # 테넌트 관리 -│ ├── hr.php # HR/인사 관리 -│ ├── finance.php # 재무/회계 -│ ├── sales.php # 영업/판매 -│ ├── inventory.php # 재고/품목 -│ ├── production.php # 생산 관리 -│ ├── design.php # 설계/모델 -│ ├── files.php # 파일 관리 -│ ├── boards.php # 게시판 -│ └── common.php # 공통 기능 -├── v2/ # v2 API (필요시 생성) -└── api.php # 라우트 로더 -``` - -### API 버전 관리 - -**ApiVersionMiddleware**가 버전 선택 및 폴백을 처리합니다: - -**버전 지정 방법:** -- `Accept-Version` 헤더 (권장) -- `X-API-Version` 헤더 -- `api_version` 쿼리 파라미터 -- 미지정 시 기본값: `v1` - -**폴백 동작:** -- v2 요청 시 해당 라우트가 v2에 없으면 v1으로 자동 폴백 -- 응답 헤더 `X-API-Version`에 실제 사용 버전 표시 - -### 기본 경로 그룹 - -```php -// routes/api.php - 라우트 로더 -Route::prefix('v1')->middleware(['auth.apikey'])->group(function () { - require __DIR__.'/api/v1/auth.php'; - require __DIR__.'/api/v1/admin.php'; - require __DIR__.'/api/v1/users.php'; - // ... 13개 도메인 파일 로드 -}); - -// v2 라우트 (존재하는 경우) -if (is_dir(__DIR__.'/api/v2')) { - Route::prefix('v2')->middleware(['auth.apikey'])->group(function () { - // v2 전용 라우트 - }); -} -``` - -## 공유 모델 구조 - -`shared/Models/` 디렉토리 구조: -- **Members/** - 사용자 및 테넌트 관리 -- **Products/** - 제품 카탈로그 및 BOM -- **Materials/** - 자재 사양 및 재고 -- **Orders/** - 주문 처리 워크플로우 -- **Tenants/** - 멀티테넌트 설정 -- **Commons/** - 공유 유틸리티 및 공통 데이터 - -## Docker 설정 - -**위치**: `docker/` 디렉토리 - -### 서비스 구성 - -**docker-compose.yml**에 정의된 주요 서비스: - -1. **nginx** - 리버스 프록시 서버 - - 포트: 80 - - 도메인: `api.sam.kr`, `mng.sam.kr`, `admin.sam.kr`, `dev.sam.kr` - - 보안 규칙 적용 (경로 탐색 공격 차단, User-Agent 필터링) - -2. **api** - Laravel 12 API 서버 - - 이미지: `php:8.4-fpm` - - PHP 확장: zip, mysqli, pdo, pdo_mysql, intl - - Supervisor로 nginx + php-fpm 동시 실행 - -3. **mng** - Laravel 12 관리자 패널 - - 이미지: `php:8.4-fpm` - - Pure Blade + Tailwind CSS - - Supervisor로 nginx + php-fpm 동시 실행 - -4. **react** - Next.js 15.5.7 프론트엔드 - - 이미지: `node:20-alpine` - - 포트: 3000 (내부) - - HMR 지원 (WebSocket) - -5. **mysql** - MySQL 8.0 데이터베이스 - - 포트: 3306 - - 데이터베이스: `samdb` - - 사용자: `samuser` / `sampass` - -6. **design** - 디자인 시스템 (Storybook) - - 포트: 6006 - -### 네트워크 구조 - -``` -samnet (bridge network) -├── nginx (리버스 프록시) -├── api (Laravel API) -├── mng (Laravel 관리자) -├── react (Next.js) -├── design (Storybook) -└── mysql (데이터베이스) -``` - -### 도메인 매핑 - -| 도메인 | 대상 서비스 | 포트 | 용도 | -|--------|-----------|------|------| -| `api.sam.kr` | api (Laravel) | 80 | REST API | -| `mng.sam.kr` | mng (Laravel) | 80 | 관리자 패널 | -| `admin.sam.kr` | mng (Laravel) | 80 | 관리자 패널 (별칭) | -| `dev.sam.kr` | react (Next.js) | 3000 | 프론트엔드 | - -### 주요 설정 파일 - -**nginx/nginx.conf** -- 리버스 프록시 설정 -- 보안 규칙 (경로 탐색, User-Agent 필터링) -- WebSocket 지원 (Next.js HMR) - -**api/Dockerfile, mng/Dockerfile** -- PHP 8.4-fpm 기반 -- Composer 2 포함 -- Supervisor 설정 - -**react/Dockerfile** -- Node.js 20 Alpine -- Next.js 15 개발 서버 - -**mysql/init.sql** -- 초기 데이터베이스 설정 - -## 저장소 구조 - -이 프로젝트는 **독립적인 Git 저장소들**로 구성됩니다: - -1. **api/** - REST API 저장소 -2. **mng/** - 관리자 패널 저장소 -3. **react/** - Next.js 프론트엔드 저장소 -4. **docs/** - 기술 문서 저장소 -5. **design/** - 디자인 시스템 저장소 -6. **planning/** - 기획 문서 저장소 - -각 저장소는 독립적으로 운영되며: -- 개별 Git 히스토리 및 브랜치 -- 독립적인 환경 설정 (`.env` 파일) -- 독립적인 의존성 및 빌드 프로세스 - -## 관련 문서 - -- [API 개발 규칙](./api_rules.md) -- [데이터베이스 스키마](./database_schema.md) -- [보안 가이드](./security.md) -- [Git 컨벤션](./git_conventions.md) - ---- - -**최종 업데이트**: 2025-12-26 (admin→mng 전환, Next.js 15.5.7, React 19.2.1 반영) \ No newline at end of file diff --git a/changes/20251111_1450_admin_tenant_selector.md b/changes/20251111_admin_tenant_selector.md similarity index 98% rename from changes/20251111_1450_admin_tenant_selector.md rename to changes/20251111_admin_tenant_selector.md index 35d4e6a..9ddacc9 100644 --- a/changes/20251111_1450_admin_tenant_selector.md +++ b/changes/20251111_admin_tenant_selector.md @@ -211,7 +211,7 @@ class ProductResource extends Resource ## 🔗 관련 문서 -- 이전 작업: `/Users/hskwon/Works/@KD_SAM/SAM/docs/changes/20251111_1354_admin_users_improvement.md` +- 이전 작업: `docs/changes/20251111_admin_users_improvement.md` - CLAUDE.md: `/Users/hskwon/Works/@KD_SAM/SAM/CLAUDE.md` --- diff --git a/changes/20251111_1354_admin_users_improvement.md b/changes/20251111_admin_users_improvement.md similarity index 100% rename from changes/20251111_1354_admin_users_improvement.md rename to changes/20251111_admin_users_improvement.md diff --git a/changes/2025-12-15_items-api-files-fix.md b/changes/20251215_items-api-files-fix.md similarity index 100% rename from changes/2025-12-15_items-api-files-fix.md rename to changes/20251215_items-api-files-fix.md diff --git a/changes/20251230_1430_react_fcm_push_notification.md b/changes/20251230_react_fcm_push_notification.md similarity index 100% rename from changes/20251230_1430_react_fcm_push_notification.md rename to changes/20251230_react_fcm_push_notification.md diff --git a/features/boards/README.md b/features/boards/README.md index 13156a2..59390f1 100644 --- a/features/boards/README.md +++ b/features/boards/README.md @@ -6,7 +6,7 @@ | 문서 | 설명 | 대상 | |------|------|------| -| [시스템 스펙](../../specs/board-system-spec.md) | 게시판 전체 설계 스펙 | 설계 참고 | +| [시스템 스펙](../../system/board-system-spec.md) | 게시판 전체 설계 스펙 | 설계 참고 | | [MNG 구현](./mng-implementation.md) | MNG 관리자 패널 구현 상세 | MNG 개발 | ## 개요 diff --git a/features/boards/mng-implementation.md b/features/boards/mng-implementation.md index 4f8d065..5dce063 100644 --- a/features/boards/mng-implementation.md +++ b/features/boards/mng-implementation.md @@ -243,6 +243,6 @@ public function update($id) ## 관련 문서 -- [SAM API Rules](/SAM/API_RULES.md) -- [MNG Critical Rules](/SAM/mng/docs/MNG_CRITICAL_RULES.md) -- [Board System Spec](/SAM/docs/specs/board-system-spec.md) +- [SAM API Rules](../../standards/api-rules.md) +- [MNG Critical Rules](../../../mng/docs/MNG_CRITICAL_RULES.md) +- [Board System Spec](../../system/board-system-spec.md) diff --git a/features/hr/attendance-management-spec.md b/features/hr/attendance-management-spec.md index eb8e9b3..040def0 100644 --- a/features/hr/attendance-management-spec.md +++ b/features/hr/attendance-management-spec.md @@ -332,8 +332,8 @@ | 파일 | 설명 | |------|------| | `docs/rules/attendance-api.md` | API 비즈니스 규칙 | -| `docs/specs/erp-analysis/03-gps-attendance.md` | GPS 출퇴근 스펙 | -| `docs/specs/erp-analysis/04-hr-management.md` | HR 시스템 분석 | +| `docs/system/erp-analysis/03-gps-attendance.md` | GPS 출퇴근 스펙 | +| `docs/system/erp-analysis/04-hr-management.md` | HR 시스템 분석 | --- diff --git a/guides/PROJECT_DEVELOPMENT_POLICY.md b/guides/PROJECT_DEVELOPMENT_POLICY.md index 50977ec..2f72b76 100644 --- a/guides/PROJECT_DEVELOPMENT_POLICY.md +++ b/guides/PROJECT_DEVELOPMENT_POLICY.md @@ -380,7 +380,7 @@ class ExampleModel extends Model ### SAM 전체 문서 ``` -docs/specs/ # 시스템 스펙 +docs/system/ # 시스템 현황 docs/reference/ # 레퍼런스 docs/guides/ # 가이드 (이 문서 포함) ``` diff --git a/guides/ai-config-설정.md b/guides/ai-config-settings.md similarity index 100% rename from guides/ai-config-설정.md rename to guides/ai-config-settings.md diff --git a/front/AUTO_LOGIN_GUIDE.md b/guides/auto-login-guide.md similarity index 100% rename from front/AUTO_LOGIN_GUIDE.md rename to guides/auto-login-guide.md diff --git a/front/erp-api-detail.md b/guides/erp-api-detail.md similarity index 100% rename from front/erp-api-detail.md rename to guides/erp-api-detail.md diff --git a/front/erp-api-list.md b/guides/erp-api-list.md similarity index 100% rename from front/erp-api-list.md rename to guides/erp-api-list.md diff --git a/front/item-master-guide.md b/guides/item-master-guide.md similarity index 100% rename from front/item-master-guide.md rename to guides/item-master-guide.md diff --git a/front/item-master-items-api.md b/guides/item-master-items-api.md similarity index 100% rename from front/item-master-items-api.md rename to guides/item-master-items-api.md diff --git a/guides/jenkins-setup-guide.md b/guides/jenkins-setup-guide.md index d40ac35..14f5ea5 100644 --- a/guides/jenkins-setup-guide.md +++ b/guides/jenkins-setup-guide.md @@ -267,7 +267,7 @@ sh 'export NODE_OPTIONS="--max-old-space-size=2048" && npm run build' - [운영 환경 배포 계획서](../plans/production-deployment-plan.md) - Jenkinsfile 상세, 브랜치 전략 - [.env 동기화 절차](production-env-sync.md) - 환경 변수 분리 -- [Docker 환경 스펙](../specs/docker-setup.md) - 현재 개발 환경 +- [Docker 환경 스펙](../system/docker-setup.md) - 현재 개발 환경 --- diff --git a/guides/nginx-fastcgi-guide.md b/guides/nginx-fastcgi-guide.md index acccca0..be78173 100644 --- a/guides/nginx-fastcgi-guide.md +++ b/guides/nginx-fastcgi-guide.md @@ -263,7 +263,7 @@ fastcgi_param SCRIPT_FILENAME /var/www/mng/public$fastcgi_script_name; | 문서 | 설명 | |------|------| -| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 | +| [docker-setup.md](../system/docker-setup.md) | Docker 환경 설정값 상세 | --- diff --git a/guides/php-fpm-guide.md b/guides/php-fpm-guide.md index 827406a..46d2b78 100644 --- a/guides/php-fpm-guide.md +++ b/guides/php-fpm-guide.md @@ -265,7 +265,7 @@ docker exec sam-mng-1 supervisorctl status | 문서 | 설명 | |------|------| -| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 | +| [docker-setup.md](../system/docker-setup.md) | Docker 환경 설정값 상세 | --- diff --git a/guides/production-env-sync.md b/guides/production-env-sync.md index c94d161..b9ba6fc 100644 --- a/guides/production-env-sync.md +++ b/guides/production-env-sync.md @@ -306,8 +306,8 @@ docker exec sam-mng-1 php artisan config:clear ## 관련 문서 -- [Docker 환경 구성](../specs/docker-setup.md) -- [시스템 아키텍처](../architecture/system-overview.md) +- [Docker 환경 구성](../system/docker-setup.md) +- [시스템 아키텍처](../system/overview.md) - [바로빌 카카오톡 연동](../features/barobill-kakaotalk/README.md) --- diff --git a/guides/server-how-it-works.md b/guides/server-how-it-works.md index 9e1ee73..680629a 100644 --- a/guides/server-how-it-works.md +++ b/guides/server-how-it-works.md @@ -249,8 +249,8 @@ API 호출 시 → Next.js API Route 프록시 → api.sam.kr | 문서 | 설명 | |------|------| -| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 | -| [system-overview.md](../architecture/system-overview.md) | 시스템 아키텍처 레퍼런스 | +| [docker-setup.md](../system/docker-setup.md) | Docker 환경 설정값 상세 | +| [overview.md](../system/overview.md) | 시스템 아키텍처 레퍼런스 | | [production-deployment-plan.md](../plans/production-deployment-plan.md) | 운영 배포 계획 | | [dev-commands.md](../quickstart/dev-commands.md) | 개발 명령어 모음 | diff --git a/guides/swagger-guide.md b/guides/swagger-guide.md index e197a14..de37bd4 100644 --- a/guides/swagger-guide.md +++ b/guides/swagger-guide.md @@ -237,8 +237,8 @@ php artisan l5-swagger:generate ## 관련 문서 -- [API 개발 규칙](./api_rules.md) -- [개발 명령어](./dev_commands.md) +- [API 개발 규칙](../standards/api-rules.md) +- [개발 명령어](../quickstart/dev-commands.md) --- diff --git a/quickstart/quick-start.md b/quickstart/quick-start.md index 931bdc7..cf31c3f 100644 --- a/quickstart/quick-start.md +++ b/quickstart/quick-start.md @@ -206,7 +206,7 @@ SAM/ ├── CURRENT_WORKS.md # 현재 작업 현황 │ └── docs/ # 상세 문서 - ├── architecture/ # 시스템 아키텍처 + ├── system/ # 시스템 현황 (아키텍처, DB, 인프라) ├── standards/ # 개발 표준 ├── quickstart/ # 빠른 시작 가이드 └── mes/ # MES/ERP 프로젝트 문서 @@ -229,13 +229,13 @@ SAM/ | 주제 | 문서 | |------|------| | **프로젝트 개요** | [`CLAUDE.md`](../../CLAUDE.md) | -| **현재 작업** | [`CURRENT_WORKS.md`](../../CURRENT_WORKS.md) | +| **현재 작업** | [`CURRENT_WORKS.md`](../CURRENT_WORKS.md) | | **API 규칙** | [`docs/standards/api-rules.md`](../standards/api-rules.md) | | **개발 명령어** | [`docs/quickstart/dev-commands.md`](./dev-commands.md) | | **품질 체크리스트** | [`docs/standards/quality-checklist.md`](../standards/quality-checklist.md) | | **Git 규칙** | [`docs/standards/git-conventions.md`](../standards/git-conventions.md) | -| **DB 스키마** | [`docs/architecture/database-schema.md`](../architecture/database-schema.md) | -| **MES 프로젝트** | [`docs/mes/README.md`](../mes/README.md) | +| **DB 스키마** | [`docs/system/database/README.md`](../system/database/README.md) | +| **MES 프로젝트** | [`docs/projects/mes/README.md`](../projects/mes/README.md) | --- diff --git a/rules/README.md b/rules/README.md index 7252b66..f847c0b 100644 --- a/rules/README.md +++ b/rules/README.md @@ -7,21 +7,29 @@ - 개발 시 규칙 기반 구현 가이드 - 검증 로직의 근거 제공 -## 포함 내용 -- 품목코드 생성 규칙 -- 필드 검증 규칙 -- 상태 전이 규칙 -- 권한/접근 제어 규칙 -- 데이터 무결성 규칙 - ## 문서 목록 | 문서 | 설명 | |------|------| | [item-policy.md](item-policy.md) | 품목 정책 (유형 체계, 예약어, API 규칙) | | [pricing-policy.md](pricing-policy.md) | 단가 정책 (원가/판매가 계산, 리비전 관리) | +| [customer-pricing.md](customer-pricing.md) | 고객 안내용 서비스 요금표 | +| [partner-commission.md](partner-commission.md) | 영업파트너 수당 체계 및 정산 | +| [billing-policy.md](billing-policy.md) | 내부용 원가/마진/코드참조 (CONFIDENTIAL) | +| [client-policy.md](client-policy.md) | 고객사 관리 정책 | +| [attendance-api.md](attendance-api.md) | 근태 API 규칙 | +| [department-tree-api.md](department-tree-api.md) | 부서 트리 API 규칙 | +| [employee-api.md](employee-api.md) | 직원 API 규칙 | +| [numbering-rules.md](numbering-rules.md) | 채번규칙 (패턴 기반 자동 번호 생성) | + +## 첨부 파일 + +| 파일 | 설명 | +|------|------| +| billing-policy.pptx | 과금 정책 프레젠테이션 | +| customer-pricing.pptx | 고객 요금 프레젠테이션 | +| partner-commission.pptx | 파트너 수당 프레젠테이션 | ## 관련 폴더 - [standards/](../standards/) - 개발 표준 (어떻게 코드를 작성할 것인가) -- [architecture/](../architecture/) - 설계 원칙 (왜 이렇게 설계하는가) -- [specs/](../specs/) - 기술 스펙 (무엇을 구현할 것인가) \ No newline at end of file +- [system/](../system/) - 시스템 현황 (아키텍처, DB, 인프라) \ No newline at end of file diff --git a/rules/pricing-policy.md b/rules/pricing-policy.md index 699b413..4905354 100644 --- a/rules/pricing-policy.md +++ b/rules/pricing-policy.md @@ -394,7 +394,7 @@ WHERE deleted_at IS NULL; ## 10. 관련 문서 - [API 개발 규칙](../standards/api-rules.md) -- [데이터베이스 스키마](../specs/database-schema.md) +- [데이터베이스 스키마](../system/database/README.md) - [프론트엔드 요청서](../front/[API-2025-12-08]%20pricing-api-enhancement-request.md) --- diff --git a/specs/board-system-spec.md b/specs/board-system-spec.md deleted file mode 100644 index 59cde86..0000000 --- a/specs/board-system-spec.md +++ /dev/null @@ -1,523 +0,0 @@ -# 게시판 시스템 스펙 - -**작성일**: 2025-11-27 -**상태**: 설계 완료, 구현 대기 -**관련 프로젝트**: mng, api - ---- - -## 1. 개요 - -### 1.1 목적 -- mng에서 **시스템 게시판**을 생성하여 모든 테넌트에게 제공 -- sam(api)에서 테넌트별 **자체 게시판** 생성 가능 -- 공지사항, 1:1 문의, FAQ 등 다양한 게시판 유형 지원 - -### 1.2 핵심 개념 - -| 구분 | 설명 | -|------|------| -| **시스템 게시판** | mng에서 생성, `is_system=true`, 모든 테넌트에서 접근 가능 | -| **테넌트 게시판** | sam에서 생성, `is_system=false`, 해당 테넌트만 접근 | -| **board_type** | 자유 입력 (notice, qna, faq, free 등 제한 없음) | - -### 1.3 역할 분리 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ mng (상위 관리자) │ -├─────────────────────────────────────────────────────────────┤ -│ • 시스템 게시판 CRUD (is_system = true) │ -│ • 게시판 필드 정의 (board_settings) │ -│ • 게시판 유형 자유 설정 (board_type) │ -│ • tenant_id = NULL │ -└─────────────────────────────────────────────────────────────┘ - ↓ 전체 테넌트 공개 -┌─────────────────────────────────────────────────────────────┐ -│ sam (api - 테넌트용) │ -├─────────────────────────────────────────────────────────────┤ -│ • 테넌트 게시판 CRUD (is_system = false) │ -│ • 시스템 게시판 사용 (읽기 전용 구조) │ -│ • 게시글 CRUD (posts) │ -│ • tenant_id = 현재 테넌트 │ -└─────────────────────────────────────────────────────────────┘ -``` - ---- - -## 2. 데이터베이스 스키마 - -### 2.1 기존 테이블 현황 - -현재 구현된 테이블 (6개): -- `boards` - 게시판 정의 -- `board_settings` - EAV 커스텀 필드 정의 -- `posts` - 게시글 -- `post_custom_field_values` - EAV 커스텀 필드 값 -- `board_comments` - 댓글 -- `board_files` - 파일 첨부 - -### 2.2 boards 테이블 확장 - -**추가 컬럼:** - -| 컬럼 | 타입 | 설명 | -|------|------|------| -| `is_system` | TINYINT(1) DEFAULT 0 | 시스템 게시판 여부 (1=전체 공개) | -| `board_type` | VARCHAR(50) NULL | 게시판 유형 (자유 입력) | - -**변경 컬럼:** - -| 컬럼 | 변경 내용 | -|------|----------| -| `tenant_id` | NOT NULL → **NULL 허용** (시스템 게시판용) | - -**최종 boards 테이블 구조:** - -```sql -CREATE TABLE boards ( - id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - tenant_id BIGINT UNSIGNED NULL COMMENT '테넌트 ID (NULL=시스템 게시판)', - is_system TINYINT(1) DEFAULT 0 COMMENT '시스템 게시판 여부 (1=전체 테넌트 공개)', - board_type VARCHAR(50) NULL COMMENT '게시판 유형 (notice, qna, faq, free 등)', - board_code VARCHAR(50) NOT NULL COMMENT '게시판 코드 (URL용)', - name VARCHAR(100) NOT NULL COMMENT '게시판명', - description TEXT NULL COMMENT '게시판 설명', - editor_type VARCHAR(20) DEFAULT 'wysiwyg' COMMENT '에디터 타입', - allow_files TINYINT(1) DEFAULT 1 COMMENT '파일 첨부 허용', - max_file_count INT DEFAULT 5 COMMENT '최대 파일 수', - max_file_size INT DEFAULT 20480 COMMENT '최대 파일 크기 (KB)', - extra_settings JSON NULL COMMENT '추가 설정 (권한, 옵션 등)', - is_active TINYINT(1) DEFAULT 1 COMMENT '활성 여부', - created_at TIMESTAMP NULL, - updated_at TIMESTAMP NULL, - created_by BIGINT UNSIGNED NULL, - updated_by BIGINT UNSIGNED NULL, - deleted_at TIMESTAMP NULL, - deleted_by BIGINT UNSIGNED NULL, - - INDEX idx_boards_tenant (tenant_id), - INDEX idx_boards_is_system (is_system), - INDEX idx_boards_board_type (board_type), - UNIQUE INDEX uk_boards_code (tenant_id, board_code) -); -``` - -### 2.3 board_settings 테이블 (EAV 필드 정의) - -현재 구조 유지: - -```sql -CREATE TABLE board_settings ( - id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - board_id BIGINT UNSIGNED NOT NULL COMMENT '게시판 ID', - name VARCHAR(100) NOT NULL COMMENT '필드명', - field_key VARCHAR(50) NOT NULL COMMENT '필드 키', - field_type VARCHAR(30) NOT NULL COMMENT '필드 타입 (text, number, select, date 등)', - field_meta JSON NULL COMMENT '필드 메타 (옵션, 유효성 등)', - is_required TINYINT(1) DEFAULT 0 COMMENT '필수 여부', - sort_order INT DEFAULT 0 COMMENT '정렬 순서', - created_at TIMESTAMP NULL, - updated_at TIMESTAMP NULL, - created_by BIGINT UNSIGNED NULL, - updated_by BIGINT UNSIGNED NULL, - - INDEX idx_board_settings_board (board_id), - FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE -); -``` - -### 2.4 posts 테이블 - -현재 구조 유지 (SoftDeletes 적용): - -```sql -CREATE TABLE posts ( - id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID', - board_id BIGINT UNSIGNED NOT NULL COMMENT '게시판 ID', - user_id BIGINT UNSIGNED NOT NULL COMMENT '작성자 ID', - title VARCHAR(255) NOT NULL COMMENT '제목', - content LONGTEXT NULL COMMENT '내용', - editor_type VARCHAR(20) DEFAULT 'wysiwyg' COMMENT '에디터 타입', - ip_address VARCHAR(45) NULL COMMENT 'IP 주소', - is_notice TINYINT(1) DEFAULT 0 COMMENT '공지 여부', - is_secret TINYINT(1) DEFAULT 0 COMMENT '비밀글 여부', - views INT DEFAULT 0 COMMENT '조회수', - status VARCHAR(20) DEFAULT 'active' COMMENT '상태', - created_at TIMESTAMP NULL, - updated_at TIMESTAMP NULL, - created_by BIGINT UNSIGNED NULL, - updated_by BIGINT UNSIGNED NULL, - deleted_at TIMESTAMP NULL, - deleted_by BIGINT UNSIGNED NULL, - - INDEX idx_posts_tenant_board (tenant_id, board_id), - INDEX idx_posts_status (status), - FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE -); -``` - -### 2.5 post_custom_field_values 테이블 (EAV 값) - -현재 구조 유지: - -```sql -CREATE TABLE post_custom_field_values ( - id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - post_id BIGINT UNSIGNED NOT NULL COMMENT '게시글 ID', - field_id BIGINT UNSIGNED NOT NULL COMMENT '필드 ID (board_settings.id)', - value TEXT NULL COMMENT '필드 값', - created_at TIMESTAMP NULL, - updated_at TIMESTAMP NULL, - created_by BIGINT UNSIGNED NULL, - updated_by BIGINT UNSIGNED NULL, - - INDEX idx_pcfv_post (post_id), - INDEX idx_pcfv_field (field_id), - FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE, - FOREIGN KEY (field_id) REFERENCES board_settings(id) ON DELETE CASCADE -); -``` - ---- - -## 3. 게시판 유형 (board_type) - -### 3.1 권장 유형 - -| board_type | 설명 | 특징 | -|------------|------|------| -| `notice` | 공지사항 | 관리자만 작성, 전체 공개 | -| `qna` | 1:1 문의 | 작성자+관리자만 열람, 비밀글 기본 | -| `faq` | FAQ | 관리자 작성, 카테고리 분류 | -| `free` | 자유게시판 | 댓글 허용, 전체 공개 | -| `gallery` | 갤러리 | 이미지 중심 | -| `download` | 자료실 | 파일 첨부 중심 | - -### 3.2 유형별 extra_settings 예시 - -```json -// notice (공지사항) -{ - "write_roles": ["admin", "manager"], - "allow_comment": false, - "allow_secret": false -} - -// qna (1:1 문의) -{ - "write_roles": ["*"], - "allow_comment": true, - "default_secret": true, - "only_author_view": true -} - -// faq -{ - "write_roles": ["admin"], - "use_category": true, - "allow_comment": false -} - -// free (자유게시판) -{ - "write_roles": ["*"], - "allow_comment": true, - "allow_secret": true -} -``` - ---- - -## 4. API 설계 - -### 4.1 mng API (시스템 게시판 관리) - -``` -# 시스템 게시판 CRUD -GET /mng/boards # 시스템 게시판 목록 -POST /mng/boards # 시스템 게시판 생성 -GET /mng/boards/{id} # 시스템 게시판 상세 -PUT /mng/boards/{id} # 시스템 게시판 수정 -DELETE /mng/boards/{id} # 시스템 게시판 삭제 - -# 게시판 필드 관리 -GET /mng/boards/{id}/fields # 필드 목록 -POST /mng/boards/{id}/fields # 필드 추가 -PUT /mng/boards/{id}/fields/{fid} # 필드 수정 -DELETE /mng/boards/{id}/fields/{fid} # 필드 삭제 -POST /mng/boards/{id}/fields/reorder # 필드 순서 변경 -``` - -### 4.2 sam API (테넌트용) - -``` -# 게시판 조회 (시스템 + 테넌트) -GET /v1/boards # 접근 가능한 게시판 목록 -GET /v1/boards/{code} # 게시판 상세 - -# 테넌트 게시판 관리 -POST /v1/boards # 테넌트 게시판 생성 -PUT /v1/boards/{code} # 테넌트 게시판 수정 -DELETE /v1/boards/{code} # 테넌트 게시판 삭제 - -# 게시글 CRUD -GET /v1/boards/{code}/posts # 게시글 목록 -POST /v1/boards/{code}/posts # 게시글 작성 -GET /v1/boards/{code}/posts/{id} # 게시글 상세 -PUT /v1/boards/{code}/posts/{id} # 게시글 수정 -DELETE /v1/boards/{code}/posts/{id} # 게시글 삭제 - -# 댓글 -GET /v1/posts/{id}/comments # 댓글 목록 -POST /v1/posts/{id}/comments # 댓글 작성 -PUT /v1/comments/{id} # 댓글 수정 -DELETE /v1/comments/{id} # 댓글 삭제 -``` - ---- - -## 5. 모델 설계 - -### 5.1 Board 모델 - -```php -// api/app/Models/Boards/Board.php - -namespace App\Models\Boards; - -use App\Traits\BelongsToTenant; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\SoftDeletes; - -class Board extends Model -{ - use SoftDeletes; - - protected $fillable = [ - 'tenant_id', 'is_system', 'board_type', 'board_code', 'name', - 'description', 'editor_type', 'allow_files', 'max_file_count', - 'max_file_size', 'extra_settings', 'is_active', - 'created_by', 'updated_by', 'deleted_by', - ]; - - protected $casts = [ - 'is_system' => 'boolean', - 'is_active' => 'boolean', - 'allow_files' => 'boolean', - 'extra_settings' => 'array', - ]; - - /** - * 현재 테넌트에서 접근 가능한 게시판 - * - 시스템 게시판 (is_system = true) - * - 해당 테넌트 게시판 (tenant_id = 현재 테넌트) - */ - public function scopeAccessible($query, int $tenantId) - { - return $query->where(function ($q) use ($tenantId) { - $q->where('is_system', true) - ->orWhere('tenant_id', $tenantId); - })->where('is_active', true); - } - - /** - * 시스템 게시판만 (mng용) - */ - public function scopeSystemOnly($query) - { - return $query->where('is_system', true); - } - - /** - * 테넌트 게시판만 - */ - public function scopeTenantOnly($query, int $tenantId) - { - return $query->where('is_system', false) - ->where('tenant_id', $tenantId); - } - - // 관계 - public function fields() - { - return $this->hasMany(BoardSetting::class, 'board_id') - ->orderBy('sort_order'); - } - - public function posts() - { - return $this->hasMany(Post::class, 'board_id'); - } - - // Helper - public function getSetting(string $key, $default = null) - { - return data_get($this->extra_settings, $key, $default); - } -} -``` - -### 5.2 BoardService - -```php -// api/app/Services/Boards/BoardService.php - -namespace App\Services\Boards; - -use App\Models\Boards\Board; -use App\Services\Service; - -class BoardService extends Service -{ - /** - * 접근 가능한 게시판 목록 (시스템 + 테넌트) - */ - public function getAccessibleBoards(array $filters = []) - { - return Board::accessible($this->tenantId()) - ->when(isset($filters['board_type']), fn($q) => - $q->where('board_type', $filters['board_type'])) - ->orderBy('is_system', 'desc') - ->orderBy('name') - ->get(); - } - - /** - * 시스템 게시판 목록 (mng용) - */ - public function getSystemBoards() - { - return Board::systemOnly() - ->orderBy('name') - ->get(); - } - - /** - * 시스템 게시판 생성 (mng용) - */ - public function createSystemBoard(array $data): Board - { - $data['is_system'] = true; - $data['tenant_id'] = null; - $data['created_by'] = $this->apiUserId(); - - return Board::create($data); - } - - /** - * 테넌트 게시판 생성 (sam용) - */ - public function createTenantBoard(array $data): Board - { - $data['is_system'] = false; - $data['tenant_id'] = $this->tenantId(); - $data['created_by'] = $this->apiUserId(); - - return Board::create($data); - } - - /** - * 게시판 코드로 조회 - */ - public function getBoardByCode(string $code): ?Board - { - return Board::accessible($this->tenantId()) - ->where('board_code', $code) - ->first(); - } -} -``` - ---- - -## 6. 권한 모델 - -### 6.1 extra_settings 기반 권한 - -게시판별 권한은 `extra_settings` JSON 필드로 관리: - -```json -{ - "permissions": { - "read": ["*"], // 모든 역할 읽기 가능 - "write": ["admin", "user"], // admin, user 역할만 작성 - "manage": ["admin"] // admin만 관리 - } -} -``` - -### 6.2 권한 검증 - -```php -// Board 모델에 추가 -public function canRead(User $user): bool -{ - $roles = $this->getSetting('permissions.read', ['*']); - return in_array('*', $roles) || - $user->hasAnyRole($roles); -} - -public function canWrite(User $user): bool -{ - $roles = $this->getSetting('permissions.write', ['*']); - return in_array('*', $roles) || - $user->hasAnyRole($roles); -} - -public function canManage(User $user): bool -{ - $roles = $this->getSetting('permissions.manage', ['admin']); - return $user->hasAnyRole($roles); -} -``` - ---- - -## 7. 구현 계획 - -### 7.1 Phase 1: DB 마이그레이션 (api/) - -1. `boards` 테이블 확장 - - `tenant_id` nullable 변경 - - `is_system` 컬럼 추가 - - `board_type` 컬럼 추가 - - `deleted_at`, `deleted_by` 추가 (없으면) - - 인덱스 추가 - -### 7.2 Phase 2: 모델/서비스 수정 (api/) - -1. `Board` 모델 업데이트 - - 스코프 추가 (accessible, systemOnly, tenantOnly) - - SoftDeletes 적용 - - 권한 헬퍼 메서드 - -2. `BoardService` 구현 - - 시스템/테넌트 게시판 분리 로직 - -### 7.3 Phase 3: mng 화면 개발 - -1. 게시판 목록 (`/mng/boards`) -2. 게시판 생성/수정 폼 -3. 게시판 필드 관리 - -### 7.4 Phase 4: sam API 개발 - -1. 게시판 API (`/v1/boards`) -2. 게시글 API (`/v1/boards/{code}/posts`) -3. Swagger 문서 - ---- - -## 8. 관련 문서 - -- [데이터베이스 스키마](./database-schema.md) -- [API 개발 규칙](../reference/api-rules.md) -- [MNG Critical Rules](../../mng/docs/MNG_CRITICAL_RULES.md) - ---- - -**최종 업데이트**: 2025-11-27 -**버전**: 1.0 -**상태**: 설계 완료 diff --git a/specs/database-schema.md b/specs/database-schema.md deleted file mode 100644 index 21b676c..0000000 --- a/specs/database-schema.md +++ /dev/null @@ -1,545 +0,0 @@ -# SAM 데이터베이스 스키마 - -**업데이트**: 2026-01-29 -**데이터베이스**: samdb (MySQL 8.0.44) -**전체 테이블**: 219개 - ---- - -## Multi-tenant 데이터 아키텍처 - -### 데이터 격리 방식 - -- **방식**: `tenant_id` 컬럼 기반 격리 -- **스코프**: BelongsToTenant global scope 자동 적용 -- **모델**: `shared/Models/` 디렉토리의 공통 모델 사용 -- **Soft Deletes**: 대부분의 엔티티에 적용 -- **감사 컬럼**: `created_by`, `updated_by`, `deleted_by` - -## 핵심 테이블 구조 - -### 인증 및 권한 - -#### users (24 컬럼) - Phase 4 완료 -**용도**: 시스템 사용자 정보 (관리자, 일반 사용자) - -주요 컬럼: -- `id` (PK), `user_id` (UK), `name`, `email` (UK), `password` -- `phone`, `role` (deprecated), `is_active`, `is_super_admin` -- `email_verified_at`, `last_login_at` -- 2FA: `two_factor_secret`, `two_factor_recovery_codes`, `two_factor_confirmed_at` -- `remember_token`, `current_team_id`, `profile_photo_path` -- `options` (JSON) -- Audit: `created_by`, `updated_by`, `deleted_by` -- Timestamps: `created_at`, `updated_at`, `deleted_at` (Soft Delete) - -특징: -- Laravel Sanctum 인증 -- Multi-tenant via `user_tenants` pivot -- 2FA 지원 -- Soft Delete 지원 - -#### roles (11 컬럼) - Phase 4 완료, Spatie Permission -**용도**: 사용자 역할 정의 - -주요 컬럼: -- `id` (PK), `tenant_id`, `name`, `guard_name`, `description` -- Audit: `created_by`, `updated_by`, `deleted_by` -- Timestamps: `created_at`, `updated_at`, `deleted_at` - -인덱스: -- `UNIQUE (tenant_id, name, guard_name)` -- `INDEX (tenant_id)` - -특징: -- Spatie Laravel Permission 패키지 -- Multi-tenant 지원 -- Soft Delete 지원 - -#### permissions (8 컬럼) - Phase 4 완료, Spatie Permission -**용도**: 시스템 권한 정의 - -주요 컬럼: -- `id` (PK), `tenant_id` (nullable), `name`, `guard_name` -- Audit: `created_by`, `updated_by` -- Timestamps: `created_at`, `updated_at` - -인덱스: -- `UNIQUE (name, guard_name, tenant_id)` -- `INDEX (tenant_id)` - -특징: -- tenant_id nullable (마스터 권한 지원) -- Spatie Laravel Permission 패키지 - -#### model_has_roles (4 컬럼) - Spatie Permission -**용도**: 사용자-역할 연결 (Many-to-Many) - -주요 컬럼: -- `role_id` (PK, FK), `model_type` (PK), `model_id` (PK), `tenant_id` (PK) - -외래키: -- `role_id` → `roles.id` (ON DELETE CASCADE) - -특징: -- Polymorphic 관계 -- Multi-tenant 지원 - -#### role_has_permissions (2 컬럼) - Spatie Permission -**용도**: 역할-권한 연결 (Many-to-Many) - -주요 컬럼: -- `permission_id` (PK, FK), `role_id` (PK, FK) - -외래키: -- `permission_id` → `permissions.id` (ON DELETE CASCADE) -- `role_id` → `roles.id` (ON DELETE CASCADE) - -#### user_tenants -- 사용자-테넌트 다대다 관계 -- `active`, `default` 플래그 - -#### personal_access_tokens -- Sanctum 토큰 저장 - -#### api_keys -- API 키 관리 -- `is_active` 상태 관리 - -#### permission_overrides -- 수동 권한 허용/거부 -- 시간 기반 유효성 - -### 멀티테넌트 조직 - -#### tenants (32 컬럼) - Phase 4 완료 -**용도**: 다중 회사/조직 관리 (Multi-tenant 핵심) - -주요 컬럼: -- `id` (PK), `company_name`, `code` (UK) -- `email`, `phone`, `address`, `business_num`, `corp_reg_no`, `ceo_name` -- `homepage`, `fax`, `logo`, `admin_memo`, `options` (JSON) -- `tenant_st_code` (trial/active/none), `plan_id`, `subscription_id` -- `max_users`, `trial_ends_at`, `expires_at`, `last_paid_at`, `billing_tp_code` -- 저장소: `storage_limit`, `storage_used`, `storage_warning_sent_at`, `storage_grace_period_until` -- Audit: `created_by`, `updated_by`, `deleted_by` -- Timestamps: `created_at`, `updated_at`, `deleted_at` - -인덱스: -- `UNIQUE (code)` -- `INDEX (storage_used)` - -특징: -- Multi-tenant 시스템의 핵심 테이블 -- 구독/결제 관리 -- 저장소 용량 관리 (기본 10GB) -- Soft Delete 지원 - -#### departments (14 컬럼) - Phase 4 완료 -**용도**: 조직 부서 정보 (계층 구조) - -주요 컬럼: -- `id` (PK), `tenant_id`, `parent_id` (Self-referential) -- `code`, `name`, `description` -- `is_active`, `sort_order` -- Audit: `created_by`, `updated_by`, `deleted_by` -- Timestamps: `created_at`, `updated_at`, `deleted_at` - -인덱스: -- `UNIQUE (tenant_id, code)` -- `INDEX (tenant_id, name)` -- `INDEX (tenant_id, is_active)` -- `INDEX (parent_id)` - -특징: -- Self-referential 관계 (무제한 depth) -- 활성 상태 관리 -- 정렬 순서 지원 -- Soft Delete 지원 - -#### tenant_user_profiles -- 테넌트별 확장 사용자 프로필 - -#### department_user -- 사용자-부서 할당 -- `primary` 부서 플래그 - -### 제품 관리 - -#### categories -- 계층적 제품 분류 -- Soft Deletes 적용 - -#### category_fields -- 카테고리별 동적 필드 정의 - -#### category_templates -- 버전 관리된 카테고리 필드 스냅샷 - -#### products -- 제품 카탈로그 -- 타입 분류: `PRODUCT`, `PART`, `SUBASSEMBLY` - -#### product_components -- BOM 관계 -- `MATERIAL` 또는 `PRODUCT` 참조 - -#### materials -- 자재 마스터 -- 동적 속성 지원 - -#### classifications -- 그룹별 플랫 코드 테이블 -- 예: `product_type`, `payment_method` - -### 디자인 및 제조 - -#### models -- 디자인 모델 마스터 -- 생명주기 상태 관리 - -#### model_versions -- 버전 관리된 모델 릴리스 -- 상태: `DRAFT`, `RELEASED` - -#### bom_templates -- 모델 버전에 연결된 BOM 템플릿 - -#### bom_template_items -- 템플릿 BOM 라인 항목 -- 수량 및 낭비율 포함 - -### 주문 및 운영 - -#### orders -- 주문/견적 마스터 -- 워크플로우 상태 - -#### order_items -- 주문 라인 항목 -- 디자인 코드 포함 - -#### order_item_components -- 주문 항목별 필수 자재/제품 - -#### order_histories -- 주문 변경 추적 및 메모 - -#### clients -- 고객/벤더 마스터 - -### 재고 및 자재 - -#### material_receipts -- 입고 자재 수령 -- 로트 추적 - -#### material_inspections -- 품질 검사 기록 - -#### material_inspection_items -- 검사 체크리스트 항목 - -#### lots -- 자재 로트 관리 - -#### lot_sales -- 로트 소비 추적 - -#### price_histories -- 시간 기반 유효성을 가진 가격 이력 - -### 시스템 및 설정 - -#### menus (17 컬럼) - Phase 4 완료 -**용도**: 시스템 메뉴 트리 구조 (사이드바, 권한 연동) - -주요 컬럼: -- `id` (PK), `tenant_id` (nullable), `parent_id` (Self-referential) -- `name`, `url`, `icon` -- `is_active`, `hidden`, `is_external`, `external_url` -- `sort_order` -- Audit: `created_by`, `updated_by`, `deleted_by` -- Timestamps: `created_at`, `updated_at`, `deleted_at` - -인덱스: -- `INDEX (tenant_id)` -- `INDEX (parent_id)` -- `INDEX (sort_order)` -- `INDEX (tenant_id, is_active, hidden)` -- `INDEX (tenant_id, deleted_at)` -- `INDEX (deleted_at)` - -특징: -- Self-referential 관계 (무제한 depth) -- tenant_id nullable (마스터 메뉴 지원) -- 활성/숨김 상태 토글 -- 내부/외부 링크 지원 -- Soft Delete 지원 - -#### common_codes -- 계층적 마스터 코드 -- 테넌트 지원 - -#### files -- 다형성 파일 첨부 - -#### audit_logs -- 포괄적인 감사 추적 -- 13개월 보관 - -#### setting_field_defs -- 전역 필드 정의 - -#### tenant_field_settings -- 테넌트별 필드 설정 - -#### tenant_option_groups / tenant_option_values -- 테넌트 관리 드롭다운 옵션 - -### 콘텐츠 관리 - -#### boards -- 설정 가능한 게시판 시스템 - -#### posts -- 커스텀 필드를 가진 게시판 게시물 - -#### board_settings -- 게시판별 동적 필드 정의 - -#### board_comments -- 계층적 댓글 시스템 - -## 주요 모델 관계 - -### 관계 구조 - -``` -Tenant → Users (many-to-many via user_tenants) -Products ↔ Materials (via product_components with ref_type) -Models → Versions → BOM Templates (design workflow) -Orders → Items → Components (order breakdown) -Categories ↔ Fields ↔ Templates (dynamic forms with versioning) -Audit Logs (polymorphic tracking across all major entities) -``` - -## 공통 컬럼 패턴 - -### 필수 컬럼 - -모든 테이블에 포함되어야 하는 컬럼: - -```php -Schema::create('products', function (Blueprint $table) { - $table->id()->comment('ID'); - $table->foreignId('tenant_id')->comment('테넌트 ID'); - - // 비즈니스 컬럼... - - $table->foreignId('created_by')->nullable()->comment('생성자 ID'); - $table->foreignId('updated_by')->nullable()->comment('수정자 ID'); - $table->foreignId('deleted_by')->nullable()->comment('삭제자 ID'); - $table->timestamps(); - $table->softDeletes(); -}); -``` - -### 컬럼 규칙 - -- **tenant_id**: 필수, 인덱스 권장 -- **created_by, updated_by, deleted_by**: nullable, COMMENT 필수 -- **deleted_at**: Soft Delete용 -- **timestamps**: created_at, updated_at - -## 인덱스 최적화 - -### 필수 인덱스 - -- `tenant_id` - 모든 테이블에 권장 -- 검색/정렬에 사용되는 컬럼 -- 복합 인덱스 고려 - -### 주요 유니크 제약 - -- `models(code)` - 모델 코드 -- `model_versions(version_no)` - 버전 번호 -- `bom_items(parent, order)` - BOM 항목 순서 - -## Foreign Key 제약조건 - -### 정책 - -- **개발 환경**: 설계 단계에서 제약조건 생성 -- **운영 환경**: 최소화 또는 제거 - -### 이유 - -- 성능 최적화 -- 유연한 데이터 관리 -- 마이그레이션 복잡도 감소 - -## 감사 로그 - -### 테이블 구조 - -**audit_logs:** -- `tenant_id` - 테넌트 ID -- `target_type` - 대상 모델 타입 (polymorphic) -- `target_id` - 대상 ID -- `action` - 액션 타입 -- `before` - 변경 전 데이터 (JSON) -- `after` - 변경 후 데이터 (JSON) -- `actor_id` - 수행자 ID -- `ip` - IP 주소 -- `ua` - User Agent -- `created_at` - 생성 시간 - -### 보관 정책 - -- **기본 보관 기간**: 13개월 -- **정리**: `audit:prune` 스케줄러 (매일 03:10) -- **실패 허용**: 감사 로그 실패 시 비즈니스 로직 계속 진행 - -## 데이터베이스 작업 시 주의사항 - -### 마이그레이션 작성 - -``` -✓ 명확한 파일명 (YYYY_MM_DD_HHMMSS_action_table.php) -✓ up/down 메서드 모두 구현 -✓ 롤백 테스트 완료 -✓ COMMENT 추가 (tenant_id, created_by 등) -``` - -### 모델 작성 - -``` -✓ BelongsToTenant scope 적용 -✓ ModelTrait 사용 -✓ SoftDeletes 적용 -✓ tenant_id 필터링 확인 -``` - -### 쿼리 작성 - -``` -✓ tenant_id 필터링 필수 -✓ Eager Loading 사용 (N+1 문제 방지) -✓ 인덱스 활용 고려 -``` - -## 관련 문서 - -- [API 개발 규칙](./api_rules.md) -- [아키텍처](./architecture.md) - ---- - -## Phase 4 구현 상세 (2025-11-24) - -### 완료된 테이블 (8개) -1. **users** - 사용자 관리 (Sanctum 인증, 2FA) -2. **roles** - 역할 관리 (Spatie Permission) -3. **permissions** - 권한 관리 (Spatie Permission) -4. **model_has_roles** - 사용자-역할 연결 -5. **role_has_permissions** - 역할-권한 연결 -6. **departments** - 부서 관리 (계층 구조) -7. **menus** - 메뉴 관리 (트리 구조) -8. **tenants** - 테넌트 관리 (구독/저장소) - -### Spatie Permission 통합 -```php -// 역할 할당 -$user->assignRole('admin'); - -// 권한 확인 -$user->hasPermissionTo('users.view'); - -// 역할에 권한 할당 -$role->syncPermissions(['users.view', 'users.create']); -``` - -### 공통 패턴 -- **Soft Delete**: deleted_at, deleted_by -- **Audit**: created_by, updated_by, deleted_by -- **Multi-tenant**: tenant_id (nullable for master data) -- **Self-referential**: parent_id (departments, menus) -- **Active Status**: is_active -- **Sort Order**: sort_order - ---- - -**최종 업데이트**: 2026-01-30 -**Phase 4**: 완료 (8개 테이블 상세화) -**테이블 수 갱신**: samdb 219개 + sam_stat 20개 = 239개 - ---- - -## sam_stat 데이터베이스 (통계 전용) - -> 별도 MySQL 데이터베이스. Laravel `sam_stat` 커넥션 사용. 마이그레이션 경로: `database/migrations/stats/` - -### 메타/관리 테이블 - -| 테이블 | 설명 | 주요 컬럼 | -|--------|------|----------| -| `stat_definitions` | 통계 정의 마스터 | domain, stat_type, table_name, is_active | -| `stat_job_logs` | 집계 작업 로그 | tenant_id, job_type, target_date, status, records_processed, duration_ms | - -### 차원 테이블 - -| 테이블 | 설명 | 주요 컬럼 | -|--------|------|----------| -| `dim_date` | 날짜 차원 (2020~2030) | date, year, quarter, month, day, day_of_week, is_weekend, is_holiday | -| `dim_client` | 고객 차원 (samdb 동기화) | tenant_id, source_client_id, client_name, group_name | -| `dim_product` | 제품 차원 (samdb 동기화) | tenant_id, source_product_id, product_name, product_type | - -### 일간 팩트 테이블 (7개) - -| 테이블 | 도메인 | UK | 주요 지표 | -|--------|--------|------|----------| -| `stat_sales_daily` | 매출/수주 | (tenant_id, stat_date) | order_count/amount, sales_count/amount, new/active_client_count, shipment_count/amount | -| `stat_finance_daily` | 재무/회계 | (tenant_id, stat_date) | deposit/withdrawal count/amount, net_cashflow, purchase_count/amount, bank_balance_total | -| `stat_production_daily` | 생산/작업 | (tenant_id, stat_date) | work_order_count, completed/in_progress_count, defect_count/rate, total_quantity | -| `stat_inventory_daily` | 재고 | (tenant_id, stat_date) | receipt_count/quantity, shipment_count/quantity, total_stock_value, low_stock_count | -| `stat_quote_pipeline_daily` | 견적/영업 | (tenant_id, stat_date) | new/sent/won/lost_quote_count, pipeline_value, conversion_rate, avg_quote_amount | -| `stat_hr_attendance_daily` | 인사/근태 | (tenant_id, stat_date) | total/present/absent/late/leave_count, overtime_hours, attendance_rate | -| `stat_system_daily` | 시스템/감사 | (tenant_id, stat_date) | api_request/error_count, active_user_count, audit_create/update/delete_count, fcm_sent/failed_count | - -### 월간 요약 테이블 (4개) - -| 테이블 | 도메인 | UK | 주요 지표 | -|--------|--------|------|----------| -| `stat_sales_monthly` | 매출/수주 | (tenant_id, stat_year, stat_month) | order/sales/shipment count/amount, unique_client_count, avg_order_amount, mom/yoy_growth_rate | -| `stat_finance_monthly` | 재무/회계 | (tenant_id, stat_year, stat_month) | deposit/withdrawal/purchase_total, net_cashflow, bank_balance_end, mom_cashflow_change | -| `stat_production_monthly` | 생산/작업 | (tenant_id, stat_year, stat_month) | total_work_orders, completed/in_progress_count, avg_defect_rate, total_production_quantity | -| `stat_project_monthly` | 건설/프로젝트 | (tenant_id, stat_year, stat_month) | active/completed_site_count, new_contract_count/amount, gross_profit/rate | - -### KPI/알림/이벤트 테이블 - -| 테이블 | 설명 | 주요 컬럼 | -|--------|------|----------| -| `stat_kpi_targets` | KPI 목표값 | tenant_id, domain, metric_code, target_year/month, target_value, actual_value | -| `stat_alerts` | 통계 알림 | tenant_id, domain, alert_type, severity(enum: info/warning/critical), title, message, is_read, is_resolved | -| `stat_events` | 실시간 이벤트 로그 | tenant_id, domain, event_type, entity_type, entity_id, payload(JSON), occurred_at | -| `stat_snapshots` | 상태 스냅샷 | tenant_id, snapshot_date, domain, snapshot_type, data(JSON) | - -### Artisan 커맨드 - -| 커맨드 | 설명 | -|--------|------| -| `stat:aggregate-daily` | 일간 통계 집계 (스케줄러: 매일 01:00) | -| `stat:aggregate-monthly` | 월간 통계 집계 (스케줄러: 매월 1일 02:00) | -| `stat:sync-dimensions` | 차원 테이블 동기화 (스케줄러: 매일 00:30) | -| `stat:backfill --from= --to=` | 과거 데이터 일괄 백필 | -| `stat:verify --date=` | 원본 DB vs sam_stat 정합성 검증 | - -### API 엔드포인트 - -| Method | Path | 설명 | -|--------|------|------| -| GET | `/api/v1/stats/summary` | 대시보드 통계 요약 | -| GET | `/api/v1/stats/daily` | 도메인별 일간 통계 (domain, start_date, end_date) | -| GET | `/api/v1/stats/monthly` | 도메인별 월간 통계 (domain, year, month?) | -| GET | `/api/v1/stats/alerts` | 통계 알림 목록 (limit?, unread_only?) | \ No newline at end of file diff --git a/specs/docker-setup.md b/specs/docker-setup.md deleted file mode 100644 index 2ced83f..0000000 --- a/specs/docker-setup.md +++ /dev/null @@ -1,342 +0,0 @@ -# Docker 설정 가이드 - -## 개요 - -SAM 프로젝트는 Docker Compose를 사용하여 로컬 개발 환경을 구성합니다. - -## 서비스 구성 - -### docker-compose.yml 구조 - -```yaml -services: - nginx: # 리버스 프록시 - api: # Laravel 12 API (PHP 8.4) - mng: # Laravel 12 관리자 패널 (PHP 8.4) - react: # Next.js 15 (Node 20) - design: # 디자인 시스템 (Storybook) - mysql: # MySQL 8.0 -``` - -## 서비스별 상세 - -### 1. nginx - 리버스 프록시 - -**이미지**: `nginx:latest` - -**포트**: 80 - -**도메인 매핑**: -- `api.sam.kr` → Laravel API 서버 -- `mng.sam.kr`, `admin.sam.kr` → Laravel 관리자 패널 -- `dev.sam.kr` → Next.js 프론트엔드 - -**주요 기능**: -- 보안 규칙 적용 (경로 탐색 공격 차단) -- User-Agent 필터링 (보안 스캔 도구 차단) -- WebSocket 지원 (Next.js HMR) -- 정적 자산 캐싱 - -**설정 파일**: `docker/nginx/nginx.conf` - -### 2. api - Laravel 12 API 서버 - -**이미지**: `php:8.4-fpm` - -**기술 스택**: -- PHP 8.4-fpm -- Composer 2 -- Supervisor (nginx + php-fpm) - -**PHP 확장**: -- zip -- mysqli -- pdo -- pdo_mysql -- intl - -**환경 변수**: -- `DB_HOST=sam-mysql-1` -- `DB_PORT=3306` -- `DB_DATABASE=samdb` -- `DB_USERNAME=samuser` -- `DB_PASSWORD=sampass` - -**볼륨**: -- `../api:/var/www/api` - 소스 코드 -- `../docker/api/nginx.conf` - Nginx 설정 -- `../docker/api/supervisord.conf` - Supervisor 설정 -- `../docker/api/uploads.ini` - PHP 업로드 설정 - -**작업 디렉토리**: `/var/www/api` - -### 3. mng - Laravel 12 관리자 패널 - -**이미지**: `php:8.4-fpm` - -**기술 스택**: -- PHP 8.4-fpm -- Pure Blade + Tailwind CSS -- Composer 2 -- Supervisor (nginx + php-fpm) - -**환경 변수**: api와 동일 - -**볼륨**: -- `../mng:/var/www/mng` - 소스 코드 -- `../docker/mng/nginx.conf` - Nginx 설정 -- `../docker/mng/supervisord.conf` - Supervisor 설정 -- `../docker/mng/uploads.ini` - PHP 업로드 설정 - -**작업 디렉토리**: `/var/www/mng` - -### 4. react - Next.js 15 프론트엔드 - -**이미지**: `node:20-alpine` - -**기술 스택**: -- Node.js 20 -- Next.js 15 -- React 19.2.0 - -**포트**: 3000 (내부) - -**환경 변수**: -- `NEXT_PUBLIC_API_BASE_URL=http://api.sam.kr` -- `NEXT_PUBLIC_ADMIN_URL=http://admin.sam.kr` -- `NEXT_PUBLIC_API_KEY` (선택) -- `NEXT_PUBLIC_APP_NAME=SAM` -- `NODE_ENV=development` - -**볼륨**: -- `../react:/app` - 소스 코드 -- `/app/node_modules` - node_modules 격리 -- `/app/.next` - Next.js 빌드 캐시 - -**작업 디렉토리**: `/app` - -**개발 서버**: `npm run dev` (포트 3000) - -### 5. mysql - MySQL 데이터베이스 - -**이미지**: `mysql:8.0` - -**포트**: 3306 - -**환경 변수**: -- `MYSQL_DATABASE=samdb` -- `MYSQL_USER=samuser` -- `MYSQL_PASSWORD=sampass` -- `MYSQL_ROOT_PASSWORD=root` - -**볼륨**: -- `db_data:/var/lib/mysql` - 데이터 영구 저장 -- `../docker/mysql/init.sql` - 초기화 스크립트 - -## 네트워크 - -### samnet (bridge network) - -모든 서비스가 `samnet` 네트워크에 연결되어 서로 통신할 수 있습니다. - -**서비스 간 통신**: -- `api.sam.kr` → `mysql:3306` -- `mng.sam.kr` → `mysql:3306` -- `nginx` → `api:9000` (PHP-FPM) -- `nginx` → `mng:9000` (PHP-FPM) -- `nginx` → `react:3000` (Next.js) - -## 사용 방법 - -### 초기 설정 - -```bash -# 1. Docker 디렉토리로 이동 -cd docker - -# 2. 서비스 시작 -docker-compose up -d - -# 3. 서비스 상태 확인 -docker-compose ps -``` - -### 개발 워크플로우 - -```bash -# 서비스 시작 -docker-compose up -d - -# 로그 확인 -docker-compose logs -f - -# 특정 서비스 재시작 -docker-compose restart api - -# 서비스 중지 -docker-compose down -``` - -### 컨테이너 내부 작업 - -```bash -# API 컨테이너에서 마이그레이션 -docker-compose exec api php artisan migrate - -# MNG 컨테이너에서 Composer 설치 -docker-compose exec mng composer install - -# React 컨테이너에서 npm 설치 -docker-compose exec react npm install - -# MySQL 접속 -docker-compose exec mysql mysql -u samuser -psampass samdb -``` - -## 환경 변수 설정 - -### .env 파일 - -각 애플리케이션 디렉토리(`api/`, `mng/`, `react/`)에 `.env` 파일을 생성해야 합니다. - -**api/.env 예시**: -```env -APP_NAME=SAM API -APP_ENV=local -APP_KEY= -APP_DEBUG=true -APP_URL=http://api.sam.kr - -DB_CONNECTION=mysql -DB_HOST=sam-mysql-1 -DB_PORT=3306 -DB_DATABASE=samdb -DB_USERNAME=samuser -DB_PASSWORD=sampass -``` - -**mng/.env 예시**: -```env -APP_NAME=SAM MNG -APP_ENV=local -APP_KEY= -APP_DEBUG=true -APP_URL=http://mng.sam.kr - -DB_CONNECTION=mysql -DB_HOST=sam-mysql-1 -DB_PORT=3306 -DB_DATABASE=samdb -DB_USERNAME=samuser -DB_PASSWORD=sampass -``` - -**react/.env.local 예시**: -```env -NEXT_PUBLIC_API_BASE_URL=http://api.sam.kr -NEXT_PUBLIC_ADMIN_URL=http://admin.sam.kr -NEXT_PUBLIC_API_KEY=your-api-key -NEXT_PUBLIC_APP_NAME=SAM -``` - -## 호스트 파일 설정 - -로컬에서 도메인 접근을 위해 `/etc/hosts` 파일에 다음을 추가: - -```bash -127.0.0.1 api.sam.kr -127.0.0.1 mng.sam.kr -127.0.0.1 admin.sam.kr -127.0.0.1 dev.sam.kr -``` - -## 트러블슈팅 - -### 포트 충돌 - -```bash -# 포트 사용 확인 -lsof -i :80 -lsof -i :3306 - -# 포트를 사용하는 프로세스 종료 -kill -9 -``` - -### 볼륨 권한 문제 - -```bash -# storage 디렉토리 권한 설정 -docker-compose exec api chmod -R 775 storage -docker-compose exec mng chmod -R 775 storage -``` - -### 컨테이너 재빌드 - -```bash -# 특정 서비스 재빌드 -docker-compose build --no-cache api - -# 모든 서비스 재빌드 -docker-compose build --no-cache -``` - -### 로그 확인 - -```bash -# 모든 서비스 로그 -docker-compose logs -f - -# 특정 서비스 로그 -docker-compose logs -f api -docker-compose logs -f react - -# Nginx 에러 로그 -docker-compose exec nginx tail -f /var/log/nginx/api.sam.kr_error.log -``` - -### 데이터베이스 초기화 - -```bash -# 볼륨 삭제 (주의: 모든 데이터 삭제) -docker-compose down -v - -# 재시작 -docker-compose up -d -``` - -## 보안 설정 - -### Nginx 보안 규칙 - -`docker/nginx/nginx.conf`에 다음 보안 규칙이 적용되어 있습니다: - -1. **경로 탐색 공격 차단**: - - `../`, `..\`, `etc/passwd`, `.env`, `.git` 등 차단 - -2. **보안 스캔 도구 차단**: - - sqlmap, nikto, nmap, masscan 등 User-Agent 필터링 - -3. **정적 자산 캐싱**: - - 30일 캐시 설정 - -## 프로덕션 배포 - -프로덕션 환경에서는 다음을 고려해야 합니다: - -1. **HTTPS 설정**: SSL/TLS 인증서 적용 -2. **환경 변수**: `.env` 파일 보안 관리 -3. **볼륨 백업**: 데이터베이스 정기 백업 -4. **리소스 제한**: 컨테이너 메모리/CPU 제한 설정 -5. **로그 관리**: 로그 로테이션 설정 - -## 관련 문서 - -- [시스템 아키텍처](./02-architecture.md) -- [개발 명령어](./05-development.md) -- [보안 가이드](./08-security.md) - ---- - -**업데이트**: 2025-12-26 (admin→mng 전환, design 서비스 추가) - diff --git a/specs/erp-analysis/00-overview.md b/specs/erp-analysis/00-overview.md deleted file mode 100644 index 14c35ce..0000000 --- a/specs/erp-analysis/00-overview.md +++ /dev/null @@ -1,155 +0,0 @@ -# SAM ERP 스토리보드 분석 개요 - -> 분석 대상: SAM_ERP_Storyboard_D0.8_251216 (113 슬라이드) -> 분석일: 2025-12-17 -> 버전: D0.8 - -## 1. 문서 개요 - -### 1.1 버전 히스토리 -| 날짜 | 버전 | 내용 | -|------|------|------| -| 2025.12.01 | D0.6 | 프론트 초안 - 인사관리 & 전자결재 작성 | -| 2025.12.01 | D0.7 | 프론트 작성 - 인사관리 & 전자결재 피드백 반영 | -| 2025.12.16 | D0.8 | 회계 & 보고서 작성, GPS 출퇴근, 카드/계좌관리, 보고서 추가 | - -### 1.2 슬라이드 구성 -- **총 113 슬라이드** -- 공통 UI 가이드 + 8개 주요 기능 모듈 - -## 2. 메뉴 구조 (GNB/LNB) - -``` -SAM ERP -├── 대시보드 -├── MES 메뉴 (영업관리, 판매관리, 구매관리 등) -├── 인사관리 -│ ├── 부서관리 -│ ├── 사원관리 -│ ├── 근태관리 -│ └── 휴가관리 -├── 전자결재 -│ ├── 기안함 -│ ├── 결재함 -│ └── 참조함 -├── 게시판 -├── 회계관리 -│ ├── 거래처관리 -│ ├── 매출관리 -│ ├── 매입관리 -│ ├── 입금관리 -│ ├── 출금관리 -│ ├── 어음관리 -│ ├── 거래처원장 -│ ├── 일일 일보 -│ ├── 지출 예상 내역서 -│ ├── 미수금 현황 -│ ├── 악성채권 추심관리 -│ ├── 입출금 계좌 조회 -│ └── 카드 내역 조회 -├── 기준정보 -│ ├── 직급관리 -│ ├── 직책관리 -│ ├── 권한관리 -│ ├── 근무관리 -│ ├── 출퇴근관리 -│ ├── 휴가관리 -│ ├── 카드관리 -│ ├── 계좌관리 -│ ├── 팝업관리 -│ ├── 게시판관리 -│ ├── 일반설정 -│ └── 알림설정 -├── 보고서 및 분석 -├── 계정정보 -├── 회사정보 -├── 구독관리 -├── 결제내역 -└── 고객센터 -``` - -## 3. 기능 그룹별 슬라이드 매핑 - -| 그룹 | 슬라이드 범위 | 주요 내용 | 분석 문서 | -|------|---------------|----------|----------| -| 공통 | 3-13 | UI 컴포넌트, 인터랙션, 알림 | [01-common.md](./01-common.md) | -| 인증/영업 | 14-22 | 가입, 로그인, 약관동의 | [02-auth.md](./02-auth.md) | -| GPS 출퇴근 | 23-27 | 모바일 출퇴근 | [03-gps-attendance.md](./03-gps-attendance.md) | -| 인사관리 | 28-46 | 부서/사원/근태/휴가 | [04-hr-management.md](./04-hr-management.md) | -| 전자결재 | 47-59 | 기안/결재/참조함 | [05-approval.md](./05-approval.md) | -| 회계관리 | 60-91 | 거래처/매출/매입/입출금 | [06-accounting.md](./06-accounting.md) | -| 기준정보 | 92-104 | 직급/직책/휴가/카드/계좌 | [07-master-data.md](./07-master-data.md) | -| 보고서 | 105-113 | 분석/AI 리포트 | [08-reports.md](./08-reports.md) | - -## 4. 사용자 역할 - -### 4.1 영업사원 (Sales) -- 운영 로그인 -- 회사 등록 신청 -- 테넌트 추가 알림 - -### 4.2 관리자 (Admin) -- 자료 확인 -- 가입 승인/거절 -- 이메일로 URL 발송 - -### 4.3 고객사 (Customer/Tenant) -- 약관 동의 -- 비밀번호 설정 -- SAM 로그인 -- 테넌트 추가 - -## 5. 핵심 비즈니스 플로우 - -### 5.1 가입 및 로그인 플로우 (슬라이드 15) -``` -영업사원: 운영 로그인 → 사업자등록번호 입력 → 회사정보 등록 → 가입신청 완료 - ↓ (거절) -관리자: 자료 확인 → 승인? → 이메일로 URL 발송 거절 알림 - ↓ -고객사: 약관 동의 → 비밀번호 설정 → SAM 로그인 → 테넌트 추가? - ↓ -매니저: 테넌트 추가 알림 → 사업자등록번호 입력 -``` - -### 5.2 회계관리 플로우 (슬라이드 61) -``` -매출: 거래처 선택 → 매출 등록 → 세금계산서 발행 -입금: 입금 등록 → 전액 입금? → 어음 수취? -매입: 거래처 선택 → 매입 등록 → 세금계산서 수취 -출금: 출금 등록 → 전액 출금? → 어음 발행? -추심: 미수금 현황 → 연체? → 악성주심? → 악성 추심 -조회: 입출금 계좌 조회, 카드 내역 조회 -장부/보고서: 거래처원장, 지출 예상 내역서, 일일 일보 -``` - -## 6. 기술 스펙 - -### 6.1 반응형 웹 브레이크포인트 -- 모바일: < 640px (기본) -- 태블릿: 768px ~ 1023px (md) -- 데스크탑: 1024px+ (lg) -- 대형 모니터: 1280px+ (xl) - -### 6.2 인터랙션 -| 타입 | 적용 | -|------|------| -| Tap | Yes | -| Touch & Hold | No | -| Double Tap | No | -| Drag & Drop | Yes | -| Scroll Up/Down | Yes | -| Swipe Left/Right | Yes | -| Pinch Zoom In/Out | Yes | - -### 6.3 알림 타입 -- Alert (알림): 사용자에게 상황 알림 -- Confirm Alert (확인): 확인/취소 선택 -- Toast Message: 2-3초 후 Fade out - -## 7. 다음 단계 - -1. 각 기능 그룹별 상세 분석 문서 작성 -2. API 엔드포인트 도출 -3. 데이터 모델 설계 -4. 개발 우선순위 결정 \ No newline at end of file diff --git a/specs/erp-analysis/01-common.md b/specs/erp-analysis/01-common.md deleted file mode 100644 index f78e1f9..0000000 --- a/specs/erp-analysis/01-common.md +++ /dev/null @@ -1,143 +0,0 @@ -# 공통 UI 컴포넌트 (슬라이드 3-13) - -## 1. 화면 템플릿 (슬라이드 6) - -### 1.1 모바일 화면 구조 -``` -┌─────────────────────────────┐ -│ A. Status bar (OS 관리) │ -├─────────────────────────────┤ -│ B. Browser 영역 │ -├──────┬──────────────────────┤ -│Button│ Title │Button│ C. Title 영역 -├──────┴──────────────────────┤ -│ │ -│ D. Content 영역 │ -│ │ -├─────────────────────────────┤ -│ E. Browser bar 영역 │ -├─────────────────────────────┤ -│ F. Keypad 영역 (입력 시) │ -└─────────────────────────────┘ -``` - -### 1.2 영역 설명 -- **A. Status bar**: 안테나, 통화, 배터리 등 시스템 OS 관리 영역 -- **B. Browser 영역**: 브라우저 기능 영역 -- **C. Title 영역**: 텍스트 또는 기능 버튼으로 구현, 텍스트 기본 가운데 정렬 -- **D. Content 영역**: 컨텐츠 내용 표시, 컨텐츠 길이가 길어질 경우 스크롤 제공 -- **E. Browser bar 영역**: 브라우저 유틸 바 영역 -- **F. Keypad 영역**: 키보드 입력할 때 활성화, 모든 페이지 위에 덮어쓰기 구현 - -## 2. GNB/LNB/푸터 (슬라이드 8) - -### 2.1 알림 버튼 -- 클릭: 알림 팝업 표시 - -### 2.2 개인 정보 버튼 -- 등록: 디폴트 이미지, 이름, 직급 -- 클릭: 마이페이지 팝업 표시 - -### 2.3 회사 로고 -- 회사정보 화면에서 등록한 로고 표시 -- 회사 변경 선택 시 해당 로고 변경 - -### 2.4 메뉴 영역 -- 메뉴 클릭: - - 하위 메뉴가 있을 경우: 하위 메뉴 하단에 표시 - - 하위 메뉴 없을 경우: 해당 메뉴 화면으로 이동 - - 목록 길 경우 해당 영역 내 스크롤 처리 - -### 2.5 MES 메뉴 영역 -- 영업관리, 판매관리, 구매관리 등 해당하는 MES 메뉴 영역 표시 - -### 2.6 푸터 영역 -- 모든 화면 하단 공통 표시 - -## 3. 알림 팝업 (슬라이드 9) - -### 3.1 알림 목록 -- 항목: 디폴트 원형일, 종류(공지사항), 안내/제목/내용, 전송일시 표시 -- 클릭: 해당 상세 화면으로 이동 -- 최신순 10개까지 표시 - -### 3.2 New 아이콘 -- 새 알림일 경우 New 아이콘 표시 -- 해당 알림 클릭 시 사라짐 - -### 3.3 빨간 점 아이콘 -- 새 알림이 있을 경우 표시 -- 해당 알림 모두 클릭 시 사라짐 - -## 4. 마이페이지 팝업 (슬라이드 10) - -### 4.1 계정 아이디 (이메일) 표시 - -### 4.2 회사 셀렉트 박스 -- 종류: 회사명, 회사명... (해당 계정이 생성한 회사(테넌트) 목록 표시) -- 정렬: 등록순 -- 한 회사만 소유중일 경우에는 해당 영역 숨김 - -### 4.3 로그아웃 버튼 -- 클릭: "정말 로그아웃하시겠습니까?" 로그아웃 확인 Alert 표시 -- 확인 버튼 클릭 시 로그아웃 처리 - -## 5. 셀렉트 박스 (슬라이드 11) - -### 5.1 기본 셀렉트 박스 -- 클릭: 하단에 종류 목록 표시 - -### 5.2 종류 목록 -- 목록 중 하나만 선택 가능 - -### 5.3 다중 선택 셀렉트 박스 -- 선택된 첫번째 항목명 + 추가 수 표시 -- 텍스트 영역 부족할 경우 '항목..+3' 형태로 표시 - -### 5.4 다중 선택 종류 목록 -- 목록 중 복수 선택 가능 -- 전체 선택 시 전체 선택/해제 토글 - -### 5.5 검색 영역 -- 검색어 입력 후 엔터 또는 검색 아이콘 클릭 시 (5-1) 형태로 표시되며 (5-2) 영역에 검색 결과 표시 - -### 5.6 삭제 버튼 -- 클릭: 검색어 삭제 처리, 전체 종류 목록 표시 - -## 6. 입력 필드 가이드 메시지 (슬라이드 12) - -### 6.1 가이드 메시지 표시 위치 -- 상황에 따라 입력 필드 하단 또는 Alert에 표시 - -### 6.2 가이드 메시지 색상 -- 긍정일 경우: 녹색 -- (1-1) 부정일 경우: 붉은색 - -## 7. 공지 팝업 (슬라이드 13) - -### 7.1 대상 -- 전체, 설정 부서 -- 내용: 설정 기간동안 대상에게 팝업 표시 - -### 7.2 팝업 내용 영역 -- 이미지, 텍스트 - -### 7.3 "1일간 이 창을 열지 않음" 체크박스 -- 클릭: 체크 설정/해제 토글 -- 디폴트: 체크 해제 상태 -- 체크 설정 시 1일 동안 팝업 미표시 (차정 기준) - ---- - -## API 도출 - -### 공통 API -``` -GET /api/notifications # 알림 목록 조회 -POST /api/notifications/{id}/read # 알림 읽음 처리 -GET /api/user/profile # 마이페이지 정보 -GET /api/user/companies # 사용자 소속 회사 목록 -POST /api/auth/logout # 로그아웃 -GET /api/announcements # 공지 팝업 조회 -POST /api/announcements/{id}/dismiss # 공지 팝업 닫기 (1일간 안보기) -``` \ No newline at end of file diff --git a/specs/erp-analysis/02-auth.md b/specs/erp-analysis/02-auth.md deleted file mode 100644 index 1d9728d..0000000 --- a/specs/erp-analysis/02-auth.md +++ /dev/null @@ -1,205 +0,0 @@ -# 인증/영업 (슬라이드 14-22) - -## 1. 가입 및 로그인 플로우차트 (슬라이드 15) - -### 1.1 영업사원 플로우 -``` -운영 로그인 → 사업자등록번호 입력 → 사업자번호 조회? - ↓ Yes - 회사정보 등록 → 가입신청 완료 - ↓ (거절) - 거절 알림 -``` - -### 1.2 관리자 플로우 -``` -자료 확인 → 승인? → (Yes) → 이메일로 URL 발송 - ↓ (No) - 계약금50% 결제 확인 -``` - -### 1.3 고객사 플로우 -``` -약관 동의 → 비밀번호 설정 → SAM 로그인 → 테넌트 추가? - ↓ (Yes) - 매니저: 테넌트 추가 알림 - ↓ - 사업자등록번호 입력 -``` - -## 2. 운영 로그인 (슬라이드 16) - -### 2.1 아이디 인풋박스 -- 테넌트 생성자일 경우 이메일 -- 사용자일 경우 이메일 또는 아이디 -- (1-1) 상황별 가이드 메시지 - -### 2.2 비밀번호 인풋박스 -- 입력 시 마지막 글자 제외 후 마스킹 처리 -- (2-1) 상황별 가이드 메시지 - -### 2.3 열람 버튼 -- 클릭: 열람/숨김 토글 -- 디폴트: 숨김 상태 -- 열람 상태일 시 (2) 영역 마스킹 해제 처리 - -### 2.4 자동 로그인 체크박스 -- 클릭: 체크 설정/해제 토글 -- 체크 시 로그아웃 전까지 세션 유지 - -### 2.5 로그인 버튼 -- 클릭: 유효할 경우 대시보드 화면으로 이동 - -### 2.6 가이드 메시지 -| 상황 | 가이드 메시지 | -|------|---------------| -| 필수 정보 미 입력 시 | 필수 정보입니다. | -| 4글자 미만 입력 시 | 이메일은 4자 이상 가능합니다 | -| 이메일 형식에 유효 하지 않을 경우 | 이메일 주소를 다시 확인해주세요. | -| 8자 미만 입력 시 | 8자 이상으로 만들어주세요. | -| 영문+숫자+특수문자 조합이 아닐 경우 | 영문, 숫자, 특수문자를 포함해주세요. 다음의 특수기호는 보안 사항을 가능합니다., ; - @ ! | - -## 3. 사업자등록번호 조회 (슬라이드 17) - -### 3.1 제조 데모 -- 클릭: 제조 데모 화면으로 이동 - -### 3.2 시공 데모 -- 클릭: 시공 데모 화면으로 이동 - -### 3.3 사업자등록번호 인풋박스 -- 숫자만 가능, 10자리 - -### 3.4 다음 버튼 -- 클릭: - 1. 바로 빌 사업자등록번호 조회 후 사용 불가 경우: "중복된 사업자등록번호입니다." 알림 Alert 표시 - 2. 바로 빌 사업자등록번호 조회 후 사용 가능한 경우: - - [1] 테넌트 등록된 사업자등록번호일 경우: 테넌트 등록 전이어도 다른 영업사원이 등록중을 경우에는 사업자등록번호 사용 불가 (어드민에서는 해제 가능) - - "등록된 사업자등록번호 입니다." 알림 Alert 표시 - - [2] 등록되지 않은 사업자등록번호일 경우: 회사정보 등록 화면으로 이동 - -## 4. 회사정보 등록 (슬라이드 18) - -### 4.1 회사(테넌트) 상태 -- 신청: 신청 완료 입력 -- 승인: 자동 입금 외 계약금 50% 입금, 이메일로 URL 발송 선택 -- 최초 로그인 시 ERP만 표시 -- 거절: 프로젝트 설정 완료, 잔금 50% 입금 및 인도, 당월 말일까지는 무료, 익월부터 익월말까지 사용하고 구독료 청구 -- 만료: 기간 종료, 안료외 연체 상태 구분?? 영업사원에게 알림, 서비스에는 접근 불가, 배너 -- 해지: 오퍼 대기기간 단계 필요?? -- 해지: 서비스 이용 불가 -- 탈퇴: 로그인 불가, 복구 불가?? -- 미사: 서비스 이용 불가 - -### 4.2 회사 로고 이미지 영역 -- 디폴드 이미지 표시 -- 클릭: 파일탐색기 팝업 표시, 10MB 이하의 PNG, JPEG, GIF 중 하나 선택 가능 - -### 4.3 우편번호 찾기 버튼 -- 클릭: 선정한 주소 팝업 표시 - -### 4.4 찾기 버튼 -- 클릭: 파일탐색기 팝업 표시, 이미지 또는 파일 하나 선택 가능 - -### 4.5 가입 신청 버튼 -- 클릭: 사업자등록번호 조회 화면으로 이동 -- 회사 로고만 선택, 나머지는 필수 정보 -- 클릭: 가입 신청 완료 화면으로 이동 - -### 4.6 입력 필드 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 회사 로고 | N | 750x250px, 10MB 이하 PNG, JPEG, GIF | -| 회사명 | Y | | -| 대표자명 | Y | | -| 업태 | Y | | -| 업종 | Y | | -| 주소 | Y | 우편번호 찾기 + 상세주소 | -| 이메일 (아이디) | Y | | -| 세금계산서 이메일 | Y | | -| 담당자명 | Y | | -| 담당자 연락처 | Y | | -| 사업자등록증 | Y | 파일 첨부 | - -## 5. 가입 신청 완료 (슬라이드 19) - -### 5.1 가입 신청 완료 안내 문구 표시 -- SAM은 폐쇄형 네트워크이므로 플랫폼의 무결성을 보장하기 위해 모든 계정을 검토해야 합니다. -- (회사명)의 계정 세부 정보를 추가로 확인하기 위해 추가 정보를 요청할 수 있습니다. -- 영업일 기준 3일 이내에 계정에 대한 업데이트를 받게 됩니다. - -### 5.2 가입 신청 취소 버튼 -- 클릭: "가입 신청 취소 시 등록한 모든 정보가 삭제됩니다. 정말 가입 신청을 취소하시겠습니까?" 확인 Alert 표시 - -## 6. 가입 신청 승인 성공 이메일 (슬라이드 20) - -### 6.1 계정 활성화 버튼 -- 클릭: 약관 동의 화면으로 이동 - -### 6.2 지원, 블로그 버튼 -- 클릭: 해당 운영 노션 링크로 이동 - -## 7. 약관 동의 (슬라이드 21) - -### 7.1 약관 영역 -- 클릭: (1-1) 약관 내용 영역 열림/닫힘 토글 -- 디폴트: 닫힘 - -### 7.2 체크박스 -- 클릭: 체크 설정/해제 토글 -- 디폴트: 체크 설정 해제 - -### 7.3 약관에 동의합니다 버튼 -- 모든 필수 약관 동의 시 버튼 활성화 -- 클릭: 비밀번호 설정 화면으로 이동 - -### 7.4 약관에 동의합니다 버튼 -- 클릭: 모든 필수, 선택 약관에 동의 처리, 비밀번호 설정 화면으로 이동 - -### 7.5 약관 목록 -| 약관명 | 필수 | -|--------|------| -| [필수] 서비스 이용약관 | Y | -| [필수] 개인정보 취급방침 | Y | -| [필수] 약관명 | Y | -| 마케팅 정보 수신 동의 (선택) | N | -| - 이메일 수신 동의 | N | -| - SMS 수신 동의 | N | - -## 8. 비밀번호 설정 (슬라이드 22) - -### 8.1 계정 활성화 버튼 -- 클릭: 로그인 화면으로 이동 - -### 8.2 비밀번호 요구사항 -- 최소 8자 이상 영문+숫자+특수문자 조합 - ---- - -## API 도출 - -### 인증 API -``` -POST /api/auth/login # 로그인 -POST /api/auth/logout # 로그아웃 -POST /api/auth/password/reset # 비밀번호 재설정 -POST /api/auth/password/change # 비밀번호 변경 -``` - -### 회원가입/영업 API -``` -GET /api/business-registration/verify # 사업자등록번호 조회 -POST /api/registration/company # 회사정보 등록 -POST /api/registration/cancel # 가입신청 취소 -GET /api/terms # 약관 목록 조회 -POST /api/terms/agree # 약관 동의 -POST /api/account/activate # 계정 활성화 -``` - -### 테넌트 API -``` -GET /api/tenants # 테넌트 목록 -POST /api/tenants # 테넌트 추가 -PUT /api/tenants/{id} # 테넌트 수정 -GET /api/tenants/{id}/switch # 테넌트 전환 -``` diff --git a/specs/erp-analysis/03-gps-attendance.md b/specs/erp-analysis/03-gps-attendance.md deleted file mode 100644 index 4903e27..0000000 --- a/specs/erp-analysis/03-gps-attendance.md +++ /dev/null @@ -1,144 +0,0 @@ -# GPS 출퇴근 (슬라이드 23-27) - -## 1. 개요 - -GPS 기반 모바일 출퇴근 관리 시스템으로, 위치 정보를 활용하여 출근/퇴근을 기록합니다. - -## 2. 마이페이지 팝업 > 출퇴근하기 (슬라이드 24) - -### 2.1 출퇴근 버튼 -- GPS 출퇴근 사용 시에만 표시 -- 모바일일 경우에만 버튼 활성화 -- 클릭: 출퇴근하기 화면으로 이동 - -### 2.2 출퇴근 허용 반경 -- 기준 화표로부터의 출퇴근 허용 반경을 m 형으로 표시 (기준정보 > 출퇴근관리에서 설정) - -### 2.3 현재 위치 버튼 -- 클릭: (3-1) 해당 현재 위치를 지도 중심으로 표시 - -### 2.4 [+] 버튼 -- 클릭: 지도 영역 확대 - -### 2.5 확대/축소 슬라이드바 -- 드래그&드랍 또는 클릭: 지도 영역 확대/축소 - -### 2.6 [-] 버튼 -- 클릭: 지도 영역 축소 - -### 2.7 개인 정보 영역 -- 항목: 프로필 이미지, 이름, 부서명, 직급명 - -### 2.8 현재 시:분:초 표시 -- HH:MM:SS - -### 2.9 출근하기 버튼 -- 클릭: - 1) 출근 위치 미설정 상태일 경우: "출근 위치를 설정해주세요." 알림 Alert 표시 - 2) 출근 위치 설정 상태일 경우: - - (1) 출근 위치가 기준 설정 반경 초과일 경우: "출근 가능 위치가 아닙니다. 출근 위치를 확인해주세요." 알림 Alert 표시 - - [2] GPS 출근 위치 기준 설정 반경 이내: 출근하기 화면으로 이동 (출근 기록 저장) - -## 3. 출근하기 (슬라이드 25) - -### 3.1 퇴근하기 버튼 -- 클릭: - 1) 퇴근 위치 미설정 상태일 경우: "퇴근 위치를 설정해주세요." 알림 Alert 표시 - 2) 퇴근 위치 설정 상태일 경우: - - (1) 퇴근 위치가 기준 설정 반경 초과일 경우: "퇴근 가능 위치가 아닙니다. 퇴근 위치를 확인해주세요." 알림 Alert 표시 - - [2] GPS 퇴근 위치 기준 설정 반경 이내: 퇴근하기 화면으로 이동 (퇴근 기록 저장) - -### 3.2 출근 완료 아이콘 이미지 표시 - -### 3.3 출근 완료 정보 -- 항목: 출근 완료 문구, 시:분:초, 일자(요일) - -### 3.4 출근 화표의 본사/현장명 표시 - -### 3.5 확인 버튼 -- 클릭: 대시보드로 이동 - -## 4. 퇴근하기 (슬라이드 26) - -### 4.1 퇴근 완료 아이콘 이미지 표시 - -### 4.2 퇴근 완료 정보 -- 항목: 퇴근 완료 문구, 시:분:초, 일자(요일) - -### 4.3 퇴근 화표의 본사/현장명 표시 - -### 4.4 확인 버튼 -- 클릭: 대시보드로 이동 - -## 5. 현장 등록 (슬라이드 27) - -### 5.1 위치 정보 설정 -- 각 현장의 GPS 중심값으로 설정 - -### 5.2 입력 필드 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 주소 | Y | 우편번호 찾기 + 상세주소 | -| 경도 | Y | | -| 위도 | Y | | -| 첨부파일 | N | | - ---- - -## 데이터 모델 - -### Attendance (출퇴근 기록) -``` -- id: bigint -- user_id: bigint (FK) -- tenant_id: bigint (FK) -- type: enum('check_in', 'check_out') -- check_time: datetime -- latitude: decimal(10,8) -- longitude: decimal(11,8) -- location_id: bigint (FK, nullable) # 본사/현장 -- location_name: string -- is_valid: boolean # 유효 위치 여부 -- created_at: timestamp -``` - -### Location (본사/현장) -``` -- id: bigint -- tenant_id: bigint (FK) -- name: string -- address: string -- detail_address: string -- latitude: decimal(10,8) -- longitude: decimal(11,8) -- allowed_radius: int # 허용 반경 (m) -- is_active: boolean -- created_at: timestamp -``` - ---- - -## API 도출 - -### GPS 출퇴근 API -``` -POST /api/attendance/check-in # 출근 기록 -POST /api/attendance/check-out # 퇴근 기록 -GET /api/attendance/today # 오늘 출퇴근 현황 -GET /api/attendance/status # 현재 출퇴근 상태 -GET /api/attendance/location/validate # 위치 유효성 검증 -``` - -### 현장 관리 API -``` -GET /api/locations # 현장 목록 -POST /api/locations # 현장 등록 -PUT /api/locations/{id} # 현장 수정 -DELETE /api/locations/{id} # 현장 삭제 -``` - -### 출퇴근 설정 API -``` -GET /api/settings/attendance # 출퇴근 설정 조회 -PUT /api/settings/attendance # 출퇴근 설정 수정 -``` diff --git a/specs/erp-analysis/04-hr-management.md b/specs/erp-analysis/04-hr-management.md deleted file mode 100644 index f70a093..0000000 --- a/specs/erp-analysis/04-hr-management.md +++ /dev/null @@ -1,381 +0,0 @@ -# 인사관리 (슬라이드 28-46) - -## 1. 개요 - -인사관리 모듈은 부서, 사원, 근태, 휴가를 관리합니다. - -## 2. 부서관리 (슬라이드 30-31) - -### 2.1 전체 선택 체크박스 -- 클릭: 전체 선택 설정/해제 토글 -- 디폴트: 설정 해제 상태 - -### 2.2 개별 선택 체크박스 -- 클릭: 개별 선택 설정/해제 토글 -- 디폴트: 설정 해제 상태 - -### 2.3 추가 버튼 -- 클릭: 선택된 부서의 하위 부서 일괄 생성 -- 관리 권한이 없을 경우 숨김 - -### 2.4 삭제 버튼 -- 클릭: "선택한 부서 N개를 삭제하시겠습니까?" 확인 Alert 표시 -- 확인 선택 시 삭제된 부서 사원의 인원은 회사(기본) 인원으로 변경 - -### 2.5 확대 버튼 -- 클릭: (6) 확대 버튼으로 변경, 하위 부서 숨김 처리 - -### 2.6 축소 버튼 -- 클릭: (5) 축소 버튼으로 변경, 하위 부서 표시 처리 - -### 2.7 추가 버튼 -- 클릭: 부서 추가 팝업 표시 - -### 2.8 수정 버튼 -- 클릭: 부서 수정 팝업 표시 - -### 2.9 부서 추가/수정 팝업 -- 부서명 인풋박스: 기존 부서명 표시, 수정 가능 - -## 3. 사원관리 (슬라이드 32-40) - -### 3.1 기간 설정 영역 -- 입사일 기준 - -### 3.2 기간 설정 버튼 영역 -- 종류: 당해년도, 전전월, 전월, 당월, 어제, 오늘 -- 클릭: 해당 기간이 (1) 영역에 설정되며 화면 전체에 적용 처리 - -### 3.3 CSV 일괄 등록 버튼 -- 클릭: CSV 일괄 등록 화면으로 이동 - -### 3.4 사원 등록 버튼 -- 클릭: 사원 상세 화면으로 이동 - -### 3.5 사용자 초대 버튼 -- 클릭: 사용자 초대 팝업 표시 - -### 3.6 필터 셀렉트 박스 -- 종류: 전체, 사용자 아이디 보유, 사용자 아이디 미보유, 재직, 휴직, 퇴직 -- 디폴트: 전체 - -### 3.7 정렬 셀렉트 박스 -- 종류: 직급순, 부서 오름차순, 부서 내림차순, 이름 오름차순, 이름 내림차순 -- 디폴트: 직급순 - -### 3.8 현황 카드 -| 항목 | 설명 | -|------|------| -| 현직 | 전체 현직 사원 수 | -| 휴직 | 전체 휴직 사원 수 | -| 퇴직 | (1) 해당 기간의 퇴직 사원 수 | -| 평균근속년수 | 전체 현직 사원 기준 | - -## 4. 사원 상세 (슬라이드 33-36) - -### 4.1 사원 정보 영역 (필수) -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 이름 | Y | | -| 주민등록번호 | Y | | -| 휴대폰 | Y | | -| 이메일 | Y | | -| 연봉 | N | | -| 급여계좌 은행 | N | 은행 선택 | -| 계좌 | N | | -| 예금주 | N | | - -### 4.2 사용자 정보 영역 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 아이디 | N | 이메일 또는 아이디 | -| 비밀번호 | N | 최소 8자 이상 영문+숫자+특수문자 조합 | -| 권한 | N | 권한관리의 목록 표시 | -| 상태 | N | 종류: 정상, 재직, 중지. 재직 상태인 경우 로그아웃 처리, 로그인 시 '재정중인 아이디입니다.' 팝업 | - -### 4.3 사원 상세 영역 (선택) -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 프로필 사진 | N | 1250x250px, 10MB 이하 PNG, JPEG, GIF | -| 사원코드 | N | | -| 성별 | N | 남성/여성 | -| 주소 | N | 우편번호 찾기 + 상세주소 | - -### 4.4 인사 정보 영역 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 입사일 | N | | -| 고용 형태 | N | 종류: 정규직, 계약직, 파견직, 용역직, 시간제 근로자 | -| 직급 | N | 직급관리 화면에서 설정 | -| 상태 | N | 종류: 재직, 병가휴직, 육아휴직, 개인사정휴직, 무급휴직, 퇴사, 해고, 권고사직, 계약만료, 정년퇴직 | -| 부서 | N | 부서관리 화면에서 설정 | -| 직책 | N | 직책관리 화면에서 설정 | -| 출근 위치 | N | 본사, 현장 목록 | -| 퇴근 위치 | N | 본사, 현장 목록 | -| 퇴사일 | N | | -| 퇴사 사유 | N | | - -### 4.5 항목 설정 버튼 -- 클릭: 항목 설정 팝업 표시 - -### 4.6 항목 설정 팝업 (슬라이드 34) -- 전체 설정 ON/OFF 버튼 -- 개별 설정 ON/OFF 버튼 -- 디폴트: 설정 OFF 상태 - -## 5. CSV 일괄 등록 (슬라이드 39-40) - -### 5.1 양식 다운로드 버튼 -- 클릭: 등록된 양식 CSV 다운로드 - -### 5.2 파일 선택 버튼 -- 클릭: 파일 탐색기 팝업, CSV 1개만 등록 - -### 5.3 파일 변환 버튼 -- 클릭: CSV 데이터를 (3-1) 정보 등록 영역에 변환값 표시 -- 범위: 사원 상세 화면의 전체 항목 - -### 5.4 등록 버튼 -- 파일변환 완료 & (2) 체크 설정 항목 있을 경우에만 버튼 활성화 -- 클릭: "(등록)의 정보를 정말 등록하시겠습니까?" 확인 Alert 표시 -- 확인 클릭 시 (2) 체크 된 정보만 등록, "정보 등록이 완료되었습니다." 알림 Alert 표시 - -## 6. 사용자 초대 (슬라이드 37-38) - -### 6.1 사용자 초대 프로세스 -- 초대 이메일로 발송 → 약관 동의 (아이디를 이메일로 사용) → 비밀번호 설정 → 로그인 - -### 6.2 초대할 이메일 주소 인풋박스 -- ','로 구분하여 여러 주소 입력 가능 - -### 6.3 권한 셀렉트 박스, 검색 -- 종류: 권한관리의 목록 표시 - -### 6.4 초대 메시지 인풋박스 - -### 6.5 초대 버튼 -- 클릭: 사용자 초대 이메일 발송 -- 이메일 주소 기준 사원 정보가 있을 경우에는 대량하여 사용자 등록 처리 -- 없을 경우에는 사용자에만 등록하고 나머지 사원 정보는 직접 입력 필요 -- 사용자 아이디 중복 불가 - -## 7. 근태관리 (슬라이드 41-42) - -### 7.1 근태관리 현황 카드 -| 항목 | 설명 | -|------|------| -| 정시 출근 | 전체 정시 출근 수 | -| 지각 | 전체 지각 수 | -| 결근 | 전체 결근 수 | -| 휴가 | 전체 휴가 수 | - -### 7.2 기간 설정 버튼 영역 -- 종류: 당해년도, 전전월, 전월, 당월, 어제, 오늘 -- 클릭: 해당 기간이 설정되며 화면 전체에 적용 처리 -- 근태관리 자동 설정 시: 모든 사원이 정시 출퇴근한 것으로 기록, 예외사항만 경우 작성 - -### 7.3 근태 등록 버튼 -- 클릭: 근태 정보 팝업 표시 - -### 7.4 사유 등록 버튼 -- 클릭: 사유 정보 팝업 표시 - -### 7.5 필터 셀렉트 박스 -- 종류: 전체, 정시 출근, 지각, 결근, 휴가, 출장, 외근, 연장근무 -- 디폴트: 전체 - -### 7.6 정렬 셀렉트 박스 -- 종류: 직급순, 부서 오름차순, 부서 내림차순, 이름 오름차순, 이름 내림차순 -- 디폴트: 직급순 - -### 7.7 근태 정보 팝업 -| 필드명 | 설명 | -|--------|------| -| 대상 | 사원 셀렉트 박스, 검색&다중 선택 | -| 기준일 | 달력 팝업 표시, 일자 다중 선택 가능, 디폴트: 당일 | -| 출근 시간 | 시/분 선택 | -| 퇴근 시간 | 시/분 선택 | -| 야간 연장 시간 | 주당 연장 근로 시간에서 주말 연장 시간을 차감한 이내에만 설정 가능 | -| 주말 연장 시간 | 주당 연장 근로 시간에서 야간 연장 시간을 차감한 이내에만 설정 가능 | - -### 7.8 사유 정보 팝업 -| 필드명 | 설명 | -|--------|------| -| 대상 | 사원 셀렉트 박스 | -| 기준일 | 달력 팝업 | -| 내용 | 내용 입력 | - -## 8. 휴가관리 (슬라이드 43-46) - -### 8.1 휴가관리 탭 -- 휴가 사용 현황 -- 휴가 부여 현황 -- 휴가 신청 현황 - -### 8.2 휴가관리 현황 카드 -| 항목 | 설명 | -|------|------| -| 휴가 승인 대기 | | -| 연차 | 전체 연차 사원 수 | -| 결조사 | | -| 연간 연차 사용률 | | - -### 8.3 필터 셀렉트 박스 -- 종류: 전체, 모든 사원 목록 -- 항목: 부서명, 직급명, 사원명 표시 -- 디폴트: 전체 - -### 8.4 정렬 셀렉트 박스 -- 종류: 직급순, 부서 오름차순, 부서 내림차순, 이름 오름차순, 이름 내림차순 -- 디폴트: 직급순 - -### 8.5 휴가 부여 팝업 -| 필드명 | 설명 | -|--------|------| -| 유형 | 종류: 연차, 보상, 경조, 보건, 병가, 반차, 반수 선택 | -| 사유 | | -| 일수 | 개월/일/시간 선택 | - -### 8.6 휴가 신청 팝업 -| 필드명 | 설명 | -|--------|------| -| 잔여 | 잔여 일수 표시 | -| 유형 | 종류: 연차, 보상, 경조, 보건, 병가, 반차 | -| 기간 | 날짜 선택, (5) 반차 선택 시에는 시간으로 변경 | - -### 8.7 휴가 신청 현황 필터 -- 종류: 승인, 거절 -- 1/3 완료: 결재선 승인 진행도에 따라 표시 - ---- - -## 데이터 모델 - -### Department (부서) -``` -- id: bigint -- tenant_id: bigint (FK) -- parent_id: bigint (FK, nullable) -- name: string -- order: int -- is_active: boolean -- created_at: timestamp -``` - -### Employee (사원) -``` -- id: bigint -- tenant_id: bigint (FK) -- user_id: bigint (FK, nullable) -- department_id: bigint (FK, nullable) -- employee_code: string -- name: string -- resident_number: string (encrypted) -- phone: string -- email: string -- salary: decimal -- bank_code: string -- account_number: string -- account_holder: string -- profile_image: string -- gender: enum('male', 'female') -- address: string -- hire_date: date -- employment_type: enum('regular', 'contract', 'dispatch', 'service', 'part_time') -- position_id: bigint (FK) -- job_title_id: bigint (FK) -- status: enum('active', 'leave', 'sick_leave', 'parental_leave', 'personal_leave', 'unpaid_leave', 'resigned', 'dismissed', 'recommended_resignation', 'contract_expired', 'retired') -- check_in_location_id: bigint (FK, nullable) -- check_out_location_id: bigint (FK, nullable) -- resignation_date: date -- resignation_reason: text -- created_at: timestamp -``` - -### AttendanceRecord (근태 기록) -``` -- id: bigint -- tenant_id: bigint (FK) -- employee_id: bigint (FK) -- date: date -- check_in_time: time -- check_out_time: time -- status: enum('on_time', 'late', 'absent', 'leave', 'business_trip', 'outside_work', 'overtime') -- night_overtime_hours: decimal -- weekend_overtime_hours: decimal -- reason: text -- created_at: timestamp -``` - -### Leave (휴가) -``` -- id: bigint -- tenant_id: bigint (FK) -- employee_id: bigint (FK) -- type: enum('annual', 'reward', 'congratulation', 'health', 'sick', 'half_day', 'half_day_am', 'half_day_pm') -- start_date: date -- end_date: date -- days: decimal -- reason: text -- status: enum('pending', 'approved', 'rejected') -- created_at: timestamp -``` - -### LeaveBalance (휴가 잔여) -``` -- id: bigint -- tenant_id: bigint (FK) -- employee_id: bigint (FK) -- year: int -- type: enum('annual', 'reward', ...) -- granted: decimal -- used: decimal -- remaining: decimal -``` - ---- - -## API 도출 - -### 부서관리 API -``` -GET /api/departments # 부서 목록 (트리 구조) -POST /api/departments # 부서 추가 -PUT /api/departments/{id} # 부서 수정 -DELETE /api/departments/{id} # 부서 삭제 -DELETE /api/departments/bulk # 부서 일괄 삭제 -``` - -### 사원관리 API -``` -GET /api/employees # 사원 목록 -POST /api/employees # 사원 등록 -GET /api/employees/{id} # 사원 상세 -PUT /api/employees/{id} # 사원 수정 -DELETE /api/employees/{id} # 사원 삭제 -POST /api/employees/import # CSV 일괄 등록 -GET /api/employees/template # CSV 템플릿 다운로드 -POST /api/employees/invite # 사용자 초대 -``` - -### 근태관리 API -``` -GET /api/attendance # 근태 목록 -POST /api/attendance # 근태 등록 -PUT /api/attendance/{id} # 근태 수정 -GET /api/attendance/summary # 근태 현황 요약 -POST /api/attendance/reason # 사유 등록 -``` - -### 휴가관리 API -``` -GET /api/leaves # 휴가 목록 -POST /api/leaves # 휴가 신청 -PUT /api/leaves/{id} # 휴가 수정 -DELETE /api/leaves/{id} # 휴가 취소 -POST /api/leaves/{id}/approve # 휴가 승인 -POST /api/leaves/{id}/reject # 휴가 거절 -GET /api/leaves/balance/{employee_id} # 휴가 잔여 조회 -POST /api/leaves/grant # 휴가 부여 -GET /api/leaves/summary # 휴가 현황 요약 -``` \ No newline at end of file diff --git a/specs/erp-analysis/05-approval.md b/specs/erp-analysis/05-approval.md deleted file mode 100644 index 5f31d96..0000000 --- a/specs/erp-analysis/05-approval.md +++ /dev/null @@ -1,296 +0,0 @@ -# 전자결재 (슬라이드 47-59) - -## 1. 개요 - -전자결재 모듈은 기안함, 결재함, 참조함으로 구성되며, 품의서, 지출결의서, 지출 예상 내역서 등의 문서를 처리합니다. - -## 2. 기안함 (슬라이드 48-54) - -### 2.1 문서 상태 -| 상태 | 설명 | -|------|------| -| 임시저장 | 문서 작성 중, 임시저장된 상태 | -| 진행 | 모든 결재자 중 일부 승인된 상태, 결재 요청을 받은 상태 | -| 결재요청 | 결재 요청을 받은 상태 | -| 반려 | 결재자 중 반려한 사람이 있는 상태 | - -### 2.2 기안함 현황 카드 -| 항목 | 설명 | -|------|------| -| 진행 | 진행 중인 문서 수 | -| 전체 | 전체 문서 수 | -| 반려 | 반려된 문서 수 | -| 임시 저장 | 임시저장 문서 수 | - -### 2.3 문서 작성 버튼 -- 클릭: 문서 작성 화면으로 이동 - -### 2.4 상세 버튼 -- 클릭: 문서 상세 팝업 표시 - -### 2.5 삭제 버튼 -- 클릭: - 1) 임시저장 상태일 경우: "정말 이(1)건을 삭제 처리하시겠습니까?" 확인 Alert 표시, 확인 시 해당 문서 삭제 처리 - 2) 임시저장 상태가 아닐 경우: "임시저장 상태만 삭제가 가능합니다." 알림 Alert 표시 - -### 2.6 수정 버튼 -- 클릭: - 1) 임시저장 상태일 경우: 문서 작성 화면으로 이동 - 2) 임시저장 상태가 아닐 경우: 문서 상세 팝업 표시 - -### 2.7 필터 셀렉트 박스 -- 종류: 전체, 임시저장, 진행, 완료, 반려 -- 디폴트: 전체 - -### 2.8 정렬 셀렉트 박스 -- 종류: 최신순, 등록순 -- 디폴트: 최신순 - -## 3. 문서 작성 (슬라이드 49-54) - -### 3.1 상세 버튼 -- 클릭: 문서 상세 팝업 표시 - -### 3.2 문서 유형 셀렉트 박스, 검색 -- 종류: 품의서, 지출결의서, 지출 예상 내역서 -- 선택한 문서 유형의 화면으로 변경 표시 - -### 3.3 결재자 셀렉트 박스, 검색&다중 선택 -- 항목: 부서명, 직책명, 사원명 표시 -- 종류: 전체, 모든 사원 목록 -- 디폴트: 전체 - -### 3.4 참조자 셀렉트 박스, 검색&다중 선택 -- 항목: 부서명, 직책명, 사원명 표시 -- 종류: 전체, 모든 사원 목록 -- 디폴트: 전체 - -### 3.5 버튼 영역 -| 버튼 | 설명 | -|------|------| -| 상세 | 문서 상세 팝업 표시 | -| 삭제 | 임시저장 상태만 삭제 가능 | -| 삼신 | 결재선 마감 경우 숨김 | -| 임시저장 | 임시저장 처리 | - -## 4. 품의서 (슬라이드 50) - -### 4.1 구매처 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 구매처 | Y | | -| 구매처 결제일 | Y | | - -### 4.2 품의서 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 제목 | Y | | -| 품의 내역 | Y | 녹음 버튼: 마이크 사용 가능할 경우에만 버튼 활성화, 녹음 중지 버튼으로 변경, 음성 내용을 텍스트로 변경하여 (1-1) 인풋박스 영역에 표시 | -| 품의 사유 | Y | | -| 예상 비용 | Y | | - -### 4.3 참고 이미지 정보 -- 첨부파일 찾기 - -## 5. 지출결의서 (슬라이드 51-52) - -### 5.1 지출 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 지출 요청일 | Y | | -| 결제일 | Y | | - -### 5.2 지출결의서 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 적요 | Y | | -| 금액 | Y | | -| 비고 | N | | - -### 5.3 결제 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 카드 | Y | 종류: 등록된 카드 목록, 디폴트: 첫번째 카드 | -| 총 비용 | - | 지출결의서 정보의 금액 합계 표시 | - -### 5.4 참고 이미지 정보 -- 첨부파일 찾기 - -## 6. 지출 예상 내역서 (슬라이드 53-54) - -### 6.1 지출 예상 내역서 목록 -- 체크 설정/해제 토글 -- 1) 지출 예상 내역서 화면에서 찾을 경우: 설정된 체크 상태 유지 -- 2) 문서 작성 화면에서 설정했을 경우: 모든 체크 항목 설정된 상태 - -### 6.2 항목 -| 필드명 | 설명 | -|--------|------| -| 예상 지급일 | | -| 품목 | | -| 지출금액 | | -| 거래처 | | -| 계좌 | | - -### 6.3 합계 -| 항목 | 설명 | -|------|------| -| 지출 합계 | | -| 계좌 잔액 | | -| 최종 차액 | | - -## 7. 결재함 (슬라이드 55-58) - -### 7.1 상태 -| 상태 | 설명 | -|------|------| -| 진행 | 결재 하위 상태 | -| 예정 | 결재 순번에 의한 대기 | -| 결재요청 | 결재 요청을 받은 상태 | - -### 7.2 결재함 현황 카드 -| 항목 | 설명 | -|------|------| -| 결재 요청 | 결재 요청 문서 수 | -| 완료 | 완료 문서 수 | -| 반려 | 반려 문서 수 | -| 예정 | 예정 문서 수 | - -### 7.3 승인 버튼 -- 클릭: "정말 (1)건을 승인하시겠습니까?" 확인 Alert 표시 -- 확인 버튼 클릭 시 "승인이 완료되었습니다." 알림 Alert 표시 - -### 7.4 반려 버튼 -- 클릭: "정말 (1)건을 반려하시겠습니까?" 확인 Alert 표시 -- 확인 버튼 클릭 시 "반려가 완료되었습니다." 알림 Alert 표시 - -### 7.5 필터 셀렉트 박스 -- 종류: 전체, 결재 요청, 예정, 완료, 반려 -- 1/3 완료: 결재선 승인 진행도에 따라 표시 -- 디폴트: 전체 - -### 7.6 수정 버튼 -- 클릭: 문서 상세 팝업 표시 - -## 8. 참조함 (슬라이드 59) - -### 8.1 열람 버튼 -- 클릭: "정말 (1)건을 열람 처리하시겠습니까?" 확인 Alert 표시 -- 확인 버튼 클릭 시 "열람 처리가 완료되었습니다." 알림 Alert 표시 - -### 8.2 미열람 버튼 -- 클릭: "정말 (1)건을 미열람 처리하시겠습니까?" 확인 Alert 표시 -- 확인 버튼 클릭 시 "미열람 처리가 완료되었습니다." 알림 Alert 표시 - -### 8.3 필터 셀렉트 박스 -- 종류: 전체, 열람, 미열람 -- 디폴트: 전체 - -## 9. 문서 상세 팝업 (슬라이드 56-58) - -### 9.1 버튼 영역 -| 버튼 | 설명 | -|------|------| -| 복제 | 문서 작성 화면으로 이동 (새글) | -| 수정 | 결재선 중에서는 누구나 수정 가능, 해당 문서 작성 화면으로 이동 | -| 반려 | 결재선 마감 경우 숨김 | -| 승인 | 결재선 마감 경우 숨김 | -| 인쇄 | | -| 공유 | (5-1) 팝업 표시 | -| 닫기 | | - -### 9.2 결재선 영역 -- 승인/반려 시 해당 아이콘 표시 - -### 9.3 공유 버튼 -| 공유 방식 | 설명 | -|-----------|------| -| PDF | | -| 이메일 | | -| 카카오톡 | | - ---- - -## 데이터 모델 - -### ApprovalDocument (결재 문서) -``` -- id: bigint -- tenant_id: bigint (FK) -- document_number: string -- document_type: enum('request', 'expense', 'expense_estimate') -- title: string -- status: enum('draft', 'pending', 'in_progress', 'approved', 'rejected') -- drafter_id: bigint (FK) # 기안자 -- content: json # 문서 내용 -- attachments: json -- created_at: timestamp -- submitted_at: timestamp -``` - -### ApprovalLine (결재선) -``` -- id: bigint -- document_id: bigint (FK) -- approver_id: bigint (FK) -- order: int -- status: enum('pending', 'approved', 'rejected') -- comment: text -- approved_at: timestamp -``` - -### ApprovalReference (참조자) -``` -- id: bigint -- document_id: bigint (FK) -- referee_id: bigint (FK) -- is_read: boolean -- read_at: timestamp -``` - -### ExpenseItem (지출 항목) -``` -- id: bigint -- document_id: bigint (FK) -- description: string -- amount: decimal -- note: text -``` - ---- - -## API 도출 - -### 기안함 API -``` -GET /api/approvals/drafts # 기안 목록 -POST /api/approvals # 문서 작성 -PUT /api/approvals/{id} # 문서 수정 -DELETE /api/approvals/{id} # 문서 삭제 -POST /api/approvals/{id}/submit # 문서 제출 (결재 요청) -POST /api/approvals/{id}/save-draft # 임시저장 -GET /api/approvals/{id} # 문서 상세 -GET /api/approvals/drafts/summary # 기안함 현황 -``` - -### 결재함 API -``` -GET /api/approvals/inbox # 결재함 목록 -POST /api/approvals/{id}/approve # 승인 -POST /api/approvals/{id}/reject # 반려 -GET /api/approvals/inbox/summary # 결재함 현황 -``` - -### 참조함 API -``` -GET /api/approvals/references # 참조함 목록 -POST /api/approvals/{id}/mark-read # 열람 처리 -POST /api/approvals/{id}/mark-unread # 미열람 처리 -``` - -### 문서 공유 API -``` -GET /api/approvals/{id}/pdf # PDF 다운로드 -POST /api/approvals/{id}/share/email # 이메일 공유 -POST /api/approvals/{id}/share/kakao # 카카오톡 공유 -``` \ No newline at end of file diff --git a/specs/erp-analysis/06-accounting.md b/specs/erp-analysis/06-accounting.md deleted file mode 100644 index abe4c9d..0000000 --- a/specs/erp-analysis/06-accounting.md +++ /dev/null @@ -1,427 +0,0 @@ -# 회계관리 (슬라이드 60-91) - -## 1. 개요 - -회계관리 모듈은 거래처, 매출, 매입, 입금, 출금, 어음, 거래처원장, 미수금 현황, 입출금 계좌 조회 등을 관리합니다. - -## 2. 회계관리 플로우차트 (슬라이드 61) - -### 2.1 매출 플로우 -``` -거래처 선택 → 매출 등록 → 세금계산서 발행 -``` - -### 2.2 입금 플로우 -``` -입금 등록 → 전액 입금? → 어음 수취? - ↓ ↓ - 입출금 계좌 조회 어음관리 -``` - -### 2.3 매입 플로우 -``` -거래처 선택 → 매입 등록 → 세금계산서 수취 -``` - -### 2.4 출금 플로우 -``` -출금 등록 → 전액 출금? → 어음 발행? - ↓ ↓ - 입출금 계좌 조회 어음관리 -``` - -### 2.5 추심 플로우 -``` -미수금 현황 → 연체? → 악성주심? → 악성 추심 - ↓ - 미지급 알림 -``` - -### 2.6 조회 -- 입출금 계좌 조회 -- 카드 내역 조회 - -### 2.7 장부/보고서 -- 거래처원장 -- 지출 예상 내역서 -- 일일 일보 - -## 3. 거래처관리 (슬라이드 62-65) - -### 3.1 현황 카드 -| 항목 | 설명 | -|------|------| -| 전체 거래처 | | -| 매출 거래처 | | -| 매입 거래처 | | - -### 3.2 삭제 버튼 -- 관리 권한이 없을 경우 숨김 -- 클릭: "선택한 거래처 N개를 삭제하시겠습니까?" 확인 Alert 표시 -- 확인 선택 시 삭제 - -### 3.3 구분 필터 셀렉트 박스 -- 종류: 전체, 매출, 매입, 매입매출 -- 디폴트: 전체 - -### 3.4 신용등급 필터 셀렉트 박스 -- 종류: 전체, AAA, AA, A, BBB, BB, B, CCC, CC, C, D -- 디폴트: 전체 - -### 3.5 거래등급 필터 셀렉트 박스 -- 종류: 전체, A(우수), B(양호), C(보통), D(주의), E(위험) -- 디폴트: 전체 - -### 3.6 약정체결 필터 셀렉트 박스 -- 종류: 전체, 약정체결, 정상 -- 디폴트: 전체 - -### 3.7 정렬 셀렉트 박스 -- 종류: 최신순, 등록순, 거래처명 오름차순, 거래처명 내림차순, 미수금 높은순, 미수금 낮은순 -- 디폴트: 최신순 - -## 4. 거래처 상세 (슬라이드 63-65) - -### 4.1 기본 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 사업자등록번호 | Y | | -| 거래처 코드 | N | | -| 거래처명 | Y | | -| 대표자명 | Y | | -| 거래처 유형 | Y | 매출매입 선택 | -| 업태 | N | | -| 업종 | N | | - -### 4.2 연락처 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 주소 | N | 우편번호 찾기 + 상세주소 | -| 전화번호 | N | | -| 모바일 | N | | -| 팩스 | N | | -| 이메일 | N | | - -### 4.3 담당자 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 담당자명 | N | | -| 담당자 전화 | N | | - -### 4.4 시스템 관리자 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 관리자명 | N | | - -### 4.5 회사 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 회사 로고 | N | 750x250px, 10MB 이하 PNG, JPEG, GIF | - -### 4.6 결제 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 매입 결제일 | N | 종류: 1일~31일, 말일. 디폴트: 10일. 거래처 유형이 '매입' 또는 '매입매출'일 경우 해당 | -| 매출 결제일 | N | 종류: 1일~31일, 말일. 디폴트: 15일. 거래처 유형이 '매출' 또는 '매입매출'일 경우 표시 | - -### 4.7 신용 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 신용등급 | N | 외부 신용평가 등급 표시. 예: AAA, AA, A, BBB, BB, B, CCC, CC, C, D | -| 거래등급 | N | 종류: A(우수), B(양호), C(보통), D(주의), E(위험). 디폴트: A(우수). 자사 기준 거래처 평가 등급 | - -### 4.8 계좌 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 세금계산서 이메일 | N | | -| 입금계좌 은행 | N | 은행 선택 | -| 계좌 | N | | -| 예금주 | N | | - -### 4.9 추가 정보 -| 필드명 | 설명 | -|--------|------| -| 미수금 | 해당 거래처의 현재 미수금 잠게 표시. 읽기 전용 | -| 연체 | - ON: 연체 상태로 표시, 연체일수 표시 | -| | - OFF: 정상 상태 | -| | - 거래처 상세에서 연체 설정과 연동 | -| | - (4-1) 연체 등록 이후부터 경과일 표시 | -| 미지급 | 해당 거래처에 대한 미지급금 잠게 표시. 읽기 전용 | -| 악성채권 | - ON: 악성채권으로 등록, 악성채권 추심관리 목록에 표시 | -| | - OFF: 정상 상태 | -| | - 디폴트: OFF | -| 메모 | 추가 버튼 클릭 시 목록 최상단에 추가 | - -## 5. 매출관리 (슬라이드 66-71) - -### 5.1 매출 유형 -- 필드 매출 시 매출 직접 등록 (삭제 가능) -- 필드 매출: 용역 매출, 공사 매출, 임대 수익, 기타 매출 - -### 5.2 매출 상세 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 매출번호 | - | 자동 채번 | -| 매출일 | Y | | -| 거래처명 | Y | 거래처 선택 | -| 매출 유형 | Y | 선택 | - -### 5.3 품목 정보 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 품목명 | Y | | -| 수량 | Y | | -| 단가 | Y | | -| 공급가액 | - | 자동 계산 | -| 부가세 | - | 자동 계산 | -| 적요 | N | | - -### 5.4 세금계산서 -| 필드명 | 설명 | -|--------|------| -| 세금계산서 발행 | 토글 | - -### 5.5 거래명세서 -| 필드명 | 설명 | -|--------|------| -| 거래명세서 | 토글 | - -## 6. 입금관리 (슬라이드 74-76) - -### 6.1 입금 유형 -- 종류: 매출대금, 선수금, 가수금, 입대수익, 미자수익, 보증금 반환, 차입금, 자본금, 부가세 환급, 기타, 미상정 - -### 6.2 입금 상세 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 입금일 | Y | | -| 입금계좌 | Y | 국민은행 1234 (계좌명) | -| 입금자명 | Y | | -| 입금금액 | Y | | -| 적요 | N | | -| 거래처 | N | 선택 | -| 입금 유형 | Y | | - -## 7. 출금관리 (슬라이드 77-79) - -### 7.1 출금 유형 -- 종류: 매입대금, 선급금, 가지급금, 임대비용, 보증금 지급, 차입금 상환, 배당금 지급, 세금, 공과금, 경비, 4대보험, 급여 - -### 7.2 출금 상세 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 출금일 | Y | | -| 출금계좌 | Y | | -| 받는 분 | Y | | -| 출금금액 | Y | | -| 적요 | N | | -| 거래처 | N | | -| 출금 유형 | Y | | - -## 8. 거래처원장 (슬라이드 80) - -### 8.1 현황 카드 -| 항목 | 설명 | -|------|------| -| 전기 이월 | | -| 매출 | | -| 수금 | | -| 잔액 | | - -### 8.2 거래처원장 목록 -- 거래처별 기간별 합계 금액 표시 -- 클릭: 거래처원장 상세 화면으로 이동 - -### 8.3 엑셀 다운로드 버튼 -- 클릭: 엑셀 파일 다운로드 - -## 9. 미수금 현황 (슬라이드 85) - -### 9.1 미수금 현황 목록 -- 거래처별 월별 미수금 현황 (매출, 입금, 어음, 미수금, 메모) - -### 9.2 수취 어음 등록 시 표시 -- 회계에는 미반영 - -### 9.3 연체 표시 -- ON: 연체 상태로 표시, 연체일수 표시 -- OFF: 정상 상태 -- 거래처 상세에서 연체 설정과 연동 - -### 9.4 엑셀 다운로드 버튼 - -### 9.5 저장 버튼 - -## 10. 입출금 계좌 조회 (슬라이드 90) - -### 10.1 설명 -- 기준 정보 > 계좌 관리에 등록된 계좌의 자동 입출금 내역 수집 - -### 10.2 새로고침 버튼 -- 클릭: 은행 계좌 입출금 내역 최신 데이터 조회 -- 바로빌 API 연동 시 실시간 조회 - -### 10.3 구분 필터 셀렉트 박스 -- 종류: 전체, 출금, 입금 -- 디폴트: 전체 - -### 10.4 계정과목 필터 셀렉트 박스, 검색&다중 선택 -- (2) 선택에 따른 계정과목 목록 표시 -- 입금 종류: 전체, 매출대금, 선수금, 가수금, 임대수익, 이자수익, 보증금 반환, 차입금, 자본금, 부가세 환급, 기타, 미상정 -- 출금 종류: 전체, 매입대금, 선급금, 가지급금, 임대비용, 이자비용, 보증금 지급, 차입금 상환, 배당금 지급, 세금, 공과금, 경비, 4대보험, 급여 -- 디폴트: 전체 - -### 10.5 정렬 셀렉트 박스 -- 종류: 최신순, 등록순, 금액순 -- 디폴트: 최신순 - -### 10.6 수정 버튼 -- 클릭: 해당 입금/출금 상세 화면으로 이동 - ---- - -## 데이터 모델 - -### Vendor (거래처) -``` -- id: bigint -- tenant_id: bigint (FK) -- business_number: string -- vendor_code: string -- name: string -- representative: string -- type: enum('sales', 'purchase', 'both') -- business_type: string -- business_category: string -- address: string -- phone: string -- mobile: string -- fax: string -- email: string -- manager_name: string -- manager_phone: string -- logo: string -- purchase_payment_day: int -- sales_payment_day: int -- credit_rating: enum('AAA', 'AA', 'A', 'BBB', 'BB', 'B', 'CCC', 'CC', 'C', 'D') -- trade_rating: enum('A', 'B', 'C', 'D', 'E') -- tax_invoice_email: string -- bank_code: string -- account_number: string -- account_holder: string -- is_overdue: boolean -- overdue_start_date: date -- is_bad_debt: boolean -- notes: json -- created_at: timestamp -``` - -### Sales (매출) -``` -- id: bigint -- tenant_id: bigint (FK) -- vendor_id: bigint (FK) -- sales_number: string -- sales_date: date -- sales_type: enum('product', 'service', 'construction', 'rental', 'other') -- total_amount: decimal -- tax_amount: decimal -- is_tax_invoice_issued: boolean -- is_statement_issued: boolean -- created_at: timestamp -``` - -### SalesItem (매출 품목) -``` -- id: bigint -- sales_id: bigint (FK) -- item_name: string -- quantity: int -- unit_price: decimal -- supply_amount: decimal -- tax_amount: decimal -- description: string -``` - -### Deposit (입금) -``` -- id: bigint -- tenant_id: bigint (FK) -- vendor_id: bigint (FK, nullable) -- account_id: bigint (FK) -- deposit_date: date -- depositor_name: string -- amount: decimal -- description: string -- deposit_type: enum('sales', 'advance', 'suspense', 'rental', 'interest', 'deposit_return', 'loan', 'capital', 'vat_refund', 'other', 'unidentified') -- created_at: timestamp -``` - -### Withdrawal (출금) -``` -- id: bigint -- tenant_id: bigint (FK) -- vendor_id: bigint (FK, nullable) -- account_id: bigint (FK) -- withdrawal_date: date -- recipient_name: string -- amount: decimal -- description: string -- withdrawal_type: enum('purchase', 'advance', 'suspense', 'rental', 'interest', 'deposit', 'loan_repayment', 'dividend', 'tax', 'utility', 'expense', 'insurance', 'salary') -- created_at: timestamp -``` - ---- - -## API 도출 - -### 거래처 API -``` -GET /api/vendors # 거래처 목록 -POST /api/vendors # 거래처 등록 -GET /api/vendors/{id} # 거래처 상세 -PUT /api/vendors/{id} # 거래처 수정 -DELETE /api/vendors/{id} # 거래처 삭제 -DELETE /api/vendors/bulk # 거래처 일괄 삭제 -GET /api/vendors/summary # 거래처 현황 -``` - -### 매출 API -``` -GET /api/sales # 매출 목록 -POST /api/sales # 매출 등록 -GET /api/sales/{id} # 매출 상세 -PUT /api/sales/{id} # 매출 수정 -DELETE /api/sales/{id} # 매출 삭제 -POST /api/sales/{id}/tax-invoice # 세금계산서 발행 -GET /api/sales/summary # 매출 현황 -``` - -### 입금 API -``` -GET /api/deposits # 입금 목록 -POST /api/deposits # 입금 등록 -GET /api/deposits/{id} # 입금 상세 -PUT /api/deposits/{id} # 입금 수정 -DELETE /api/deposits/{id} # 입금 삭제 -``` - -### 출금 API -``` -GET /api/withdrawals # 출금 목록 -POST /api/withdrawals # 출금 등록 -GET /api/withdrawals/{id} # 출금 상세 -PUT /api/withdrawals/{id} # 출금 수정 -DELETE /api/withdrawals/{id} # 출금 삭제 -``` - -### 장부/보고서 API -``` -GET /api/ledger/vendor # 거래처원장 -GET /api/ledger/vendor/{vendor_id} # 거래처원장 상세 -GET /api/ledger/vendor/export # 거래처원장 엑셀 다운로드 -GET /api/receivables # 미수금 현황 -GET /api/receivables/export # 미수금 현황 엑셀 다운로드 -GET /api/bank-transactions # 입출금 계좌 조회 -POST /api/bank-transactions/sync # 입출금 내역 동기화 -``` \ No newline at end of file diff --git a/specs/erp-analysis/07-master-data.md b/specs/erp-analysis/07-master-data.md deleted file mode 100644 index daa9182..0000000 --- a/specs/erp-analysis/07-master-data.md +++ /dev/null @@ -1,332 +0,0 @@ -# 기준정보 (슬라이드 92-104) - -## 1. 개요 - -기준정보 모듈은 직급, 직책, 권한, 근무, 출퇴근, 휴가, 카드, 계좌, 팝업, 게시판, 일반설정, 알림설정을 관리합니다. - -## 2. 직급관리 (슬라이드 93, 95) - -### 2.1 직급 인풋박스 -- 직급 입력 후 추가 버튼 클릭 - -### 2.2 추가 버튼 -- 클릭: (2-1) 직급 목록 최하단에 표시 - -### 2.3 직급 목록 -- 디폴트: 사원, 대리, 과장, 차장, 부장, 이사, 상무, 전무, 부사장, 사장 - -### 2.4 순서 변경 버튼 -- 드래그&드랍: 해당 위치로 순서 변경 - -### 2.5 수정 버튼 -- 클릭: 직급 수정 팝업 표시 - -### 2.6 삭제 버튼 -- 클릭: - 1) 해당 직급으로 사원 설정된 경우: "'직급명'을 사용하고 있는 사원이 있습니다. 다 변경 후 삭제가 가능합니다." 알림 Alert 표시 - 2) 해당 직급으로 사원 미설정된 경우: "정말 삭제하시겠습니까?" 확인 Alert 표시, 확인 클릭 시 "삭제가 완료되었습니다." 알림 Alert 표시 - -### 2.7 직급 수정 팝업 -- 직급명 인풋박스: 기존 직급명 표시, 수정 가능 - -## 3. 직책관리 (슬라이드 94-95) - -### 3.1 기능 -- 직급관리와 동일한 구조 - -### 3.2 디폴트 직책 -- (없음) - -### 3.3 직책 수정 팝업 -- 직책명 인풋박스: 기존 직책명 표시, 수정 가능 - -## 4. 권한관리 (슬라이드 96) - -### 4.1 관리자 -- 디폴트: 모든 메뉴 권한 설정 -- 수정 불가, 삭제 불가 - -### 4.2 일반 -- 디폴트: 대시보드 제외 모든 메뉴 접근 불가 - -### 4.3 추가 버튼 -- 클릭: 권한 추가 팝업 표시 - -### 4.4 삭제 버튼 -- 클릭: - 1) 해당 권한으로 사원 설정된 경우: "'권한명'을 사용하고 있는 사원이 있습니다. 다 변경 후 삭제가 가능합니다." 알림 Alert 표시 - 2) 해당 권한으로 사원 미설정된 경우: "정말 삭제하시겠습니까?" 확인 Alert 표시 - -### 4.5 체크박스 -- 클릭: 체크 설정/해제 토글 -- 디폴트: 체크 해제 상태 - -### 4.6 관리 -- 읽기 및 수정 권한 - -### 4.7 읽기 -- 읽기만 권한 - -## 5. 근무관리 (슬라이드 97) - -### 5.1 근무 정보 -| 필드명 | 설명 | -|--------|------| -| 근무 유형 | 종류: 고정형, 변형, 맞춤형 | -| 기본 소정 근로 시간 | 주 00시간 | -| 연장 근로 시간 | 주 00시간 | -| 연장 근로 한도 | 52시간 미만 | -| 근무 요일 설정 | 클릭: 설정된 체크 활성/비활성 토글, 디폴트: 월~금 활성 | - -### 5.2 출근 시간 -- 09:00 - -### 5.3 퇴근 시간 -- 18:00 - -### 5.4 휴게 시간 -| 필드명 | 설명 | -|--------|------| -| 총 휴게 시간 | 1시간 | -| 휴게 시간 | 12:00 ~ 13:00 | - -## 6. 출퇴근관리 (슬라이드 99) - -### 6.1 출퇴근 설정 -| 필드명 | 설명 | -|--------|------| -| GPS 출퇴근 | 토글: 기준 좌표로 정해진 거리 기준 이내에 있을 때만 출근/퇴근 등록 가능 | -| 허용 반경 | 주 00m | - -### 6.2 본사 위치 정보 -| 필드명 | 설명 | -|--------|------| -| 본사 주소 | 우편번호 찾기 + 상세주소 | -| 경도 | | -| 위도 | | - -### 6.3 현장 목록 -- 추가 버튼: 현장 등록 팝업 표시 -- 현장명, 주소, 삭제 버튼 - -## 7. 휴가관리 (슬라이드 100) - -### 7.1 기준 셀렉트 박스 -- 종류: 회계연도, 입사일 -- 디폴트: 회계연도 -- 입사일 선택 시 (2) 영역 비활성화 -- 회계연도 기준: 회사의 회계연도를 기준으로 휴가를 부여하고 조회할 수 있습니다. -- 입사일 기준: 사원의 입사일 회계연도 기준으로 휴가를 부여하고 조회할 수 있습니다. - -### 7.2 기준일 월/일 설정 영역 -- 회계연도 기준 시에만 활성화 - -### 7.3 기본 연차 설정 -- 1년간 출근율 80% 이상이면 15일 -- 3년 이상 근속 시 2년에 1일 추가 (최대 25일) -- 1년 미만 또는 출근율 80% 이하인 경우 1일 - - 입사일~회계연도 기준일 사정: 회년도 출근율로 판정 80% 이상이면 15일 - - (3-1) 연차+1년+1일 시작, 이후 2년에 1일 추가 - - 입사일~회계연도 기준으로 전환할 때는 취업규칙 변경, 노사 의견수렴, 전환 시 충북 연차 정산(입사일 기준 vs 회계연도 기준 비교 후 부족분 보전)을 반드시 검토 필요 - -## 8. 카드관리 (슬라이드 101-102) - -### 8.1 카드 목록 -| 필드명 | 설명 | -|--------|------| -| 카드사 | | -| 카드번호 | 앞4자리, 끝4자리 표시 | -| 카드명 | | -| 상태 | | -| 사용자 | 부서명 / 이름 / 직책 | -| 작업 | 상세 버튼 | - -### 8.2 필터 -- 종류: 전체, 사용, 정지 -- 디폴트: 전체 - -### 8.3 카드 상세 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 카드사 | Y | 카드사명 선택 | -| 카드번호 | Y | 1234-1234-1234-1234 | -| 유효기간 | Y | MM/YY | -| 카드 비밀번호 앞 2자리 | Y | 입력 시 마스킹 처리 | -| 카드명 | Y | | -| 상태 | Y | 종류: 사용, 정지. 정지 시 해당 카드의 자동 조회 중단 | -| 사용자 | N | 부서명 / 이름 / 직책. 선택 시 해당 카드의 사용자로 설정 | - -## 9. 계좌관리 (슬라이드 103-104) - -### 9.1 계좌 목록 -| 필드명 | 설명 | -|--------|------| -| 은행 | | -| 계좌번호 | | -| 예금주 | | -| 상태 | | -| 사용자 | 부서명 / 이름 / 직책 | -| 작업 | 상세 버튼 | - -### 9.2 필터 -- 종류: 전체, 사용, 정지 -- 디폴트: 전체 - -### 9.3 계좌 상세 -| 필드명 | 필수 | 설명 | -|--------|------|------| -| 은행 | Y | 은행 선택 | -| 계좌번호 | Y | | -| 예금주 | Y | | -| 계좌명 | Y | | -| 상태 | Y | 종류: 사용, 정지. 정지 시 해당 계좌의 자동 조회 중단 | -| 사용자 | N | 부서명 / 이름 / 직책. 선택 시 해당 계좌의 사용자로 설정 | - ---- - -## 데이터 모델 - -### Position (직급) -``` -- id: bigint -- tenant_id: bigint (FK) -- name: string -- order: int -- created_at: timestamp -``` - -### JobTitle (직책) -``` -- id: bigint -- tenant_id: bigint (FK) -- name: string -- order: int -- created_at: timestamp -``` - -### Role (권한) -``` -- id: bigint -- tenant_id: bigint (FK) -- name: string -- is_system: boolean # 시스템 기본 권한 여부 -- permissions: json # 메뉴별 권한 설정 -- created_at: timestamp -``` - -### WorkSetting (근무 설정) -``` -- id: bigint -- tenant_id: bigint (FK) -- work_type: enum('fixed', 'flexible', 'custom') -- standard_hours: int # 주당 소정 근로 시간 -- overtime_hours: int # 주당 연장 근로 시간 -- overtime_limit: int # 연장 근로 한도 -- work_days: json # ['mon', 'tue', 'wed', 'thu', 'fri'] -- start_time: time -- end_time: time -- break_hours: int -- break_start: time -- break_end: time -``` - -### AttendanceSetting (출퇴근 설정) -``` -- id: bigint -- tenant_id: bigint (FK) -- use_gps: boolean -- allowed_radius: int # 허용 반경 (m) -- headquarters_address: string -- headquarters_latitude: decimal(10,8) -- headquarters_longitude: decimal(11,8) -``` - -### LeaveSetting (휴가 설정) -``` -- id: bigint -- tenant_id: bigint (FK) -- base_type: enum('fiscal_year', 'hire_date') -- fiscal_start_month: int -- fiscal_start_day: int -``` - -### Card (카드) -``` -- id: bigint -- tenant_id: bigint (FK) -- card_company: string -- card_number: string (encrypted) -- expiry_date: string -- card_password: string (encrypted) -- card_name: string -- status: enum('active', 'inactive') -- user_id: bigint (FK, nullable) -- created_at: timestamp -``` - -### BankAccount (계좌) -``` -- id: bigint -- tenant_id: bigint (FK) -- bank_code: string -- account_number: string -- account_holder: string -- account_name: string -- status: enum('active', 'inactive') -- user_id: bigint (FK, nullable) -- created_at: timestamp -``` - ---- - -## API 도출 - -### 직급/직책 API -``` -GET /api/positions # 직급 목록 -POST /api/positions # 직급 추가 -PUT /api/positions/{id} # 직급 수정 -DELETE /api/positions/{id} # 직급 삭제 -PUT /api/positions/reorder # 직급 순서 변경 - -GET /api/job-titles # 직책 목록 -POST /api/job-titles # 직책 추가 -PUT /api/job-titles/{id} # 직책 수정 -DELETE /api/job-titles/{id} # 직책 삭제 -PUT /api/job-titles/reorder # 직책 순서 변경 -``` - -### 권한 API -``` -GET /api/roles # 권한 목록 -POST /api/roles # 권한 추가 -GET /api/roles/{id} # 권한 상세 -PUT /api/roles/{id} # 권한 수정 -DELETE /api/roles/{id} # 권한 삭제 -GET /api/menus # 메뉴 목록 (권한 설정용) -``` - -### 설정 API -``` -GET /api/settings/work # 근무 설정 조회 -PUT /api/settings/work # 근무 설정 수정 -GET /api/settings/attendance # 출퇴근 설정 조회 -PUT /api/settings/attendance # 출퇴근 설정 수정 -GET /api/settings/leave # 휴가 설정 조회 -PUT /api/settings/leave # 휴가 설정 수정 -``` - -### 카드/계좌 API -``` -GET /api/cards # 카드 목록 -POST /api/cards # 카드 등록 -GET /api/cards/{id} # 카드 상세 -PUT /api/cards/{id} # 카드 수정 -DELETE /api/cards/{id} # 카드 삭제 - -GET /api/bank-accounts # 계좌 목록 -POST /api/bank-accounts # 계좌 등록 -GET /api/bank-accounts/{id} # 계좌 상세 -PUT /api/bank-accounts/{id} # 계좌 수정 -DELETE /api/bank-accounts/{id} # 계좌 삭제 -``` diff --git a/specs/erp-analysis/08-reports.md b/specs/erp-analysis/08-reports.md deleted file mode 100644 index 51e9597..0000000 --- a/specs/erp-analysis/08-reports.md +++ /dev/null @@ -1,225 +0,0 @@ -# 보고서 및 분석 (슬라이드 105-113) - -## 1. 개요 - -보고서 및 분석 모듈은 일일 일보, 지출 예상 내역서, 가지급금 인정이자 계산, AI 리포트 생성 등을 제공합니다. - -## 2. 일일 일보 (슬라이드 106-107) - -### 2.1 일일 일보 조회 -- 매일 전일의 입출금 및 매출 매입 현황 자동 집계 - -### 2.2 현황 카드 -| 항목 | 설명 | -|------|------| -| 전일 잔액 | 조회 기준일 전일 잔액 | -| 당일 입금액 | 전일 입금 합계 | -| 당일 출금액 | 전일 출금 합계 | -| 당일 잔액 | 조회 기준일 잔액 | - -### 2.3 일일 일보 목록 -| 필드명 | 설명 | -|--------|------| -| 구분 | 입금/출금 | -| 거래처명 | | -| 계정과목 | | -| 입금액 | | -| 출금액 | | -| 적요 | | - -### 2.4 엑셀 다운로드 버튼 - -## 3. 지출 예상 내역서 (슬라이드 108-109) - -### 3.1 지출 예상 내역서 조회 -- 예상 지출 금액 및 일정 조회 - -### 3.2 현황 카드 -| 항목 | 설명 | -|------|------| -| 예상 지출 합계 | 월별 예상 지출 합계 | -| 계좌 잔액 | 현재 계좌 잔액 | -| 예상 잔액 | 계좌 잔액 - 예상 지출 합계 | - -### 3.3 지출 예상 내역서 목록 -| 필드명 | 설명 | -|--------|------| -| 예상 지급일 | | -| 품목 | | -| 지출금액 | | -| 거래처 | | -| 계좌 | | - -### 3.4 엑셀 다운로드 버튼 - -### 3.5 월별 합계 -| 항목 | 설명 | -|------|------| -| 2025/11 계 | 11월 지출 합계 | -| 2025/12 계 | 12월 지출 합계 | -| 지출 합계 | 전체 지출 합계 | -| 계좌 잔액 | | -| 최종 차액 | | - -## 4. 가지급금 인정이자 계산 (슬라이드 110-112) - -### 4.1 가지급금 인정이자 계산 예시 (2024년 기준) -- 인정이자율 4.6% (당좌대출이자율 기준, 매년 고시) - -### 4.2 계산 예시 -| 항목 | 금액 | -|------|------| -| 가지급금 잔액 | 15,200,000원 | -| 인정이자 | 699,200원 | -| 법인세 추가 (19%) | 132,848원 | -| 대표자 소득세 추가 (35%) | 244,720원 | -| 대표자 지방소득세 (10%) | 24,472원 | -| **총 세금 부담** | **402,040원** | - -### 4.3 계산식 -``` -잔액 × 0.046 = 인정이자 -인정이자 × 0.19 = 법인세 추가 -인정이자 × 0.35 = 대표자 소득세 추가 -``` - -### 4.4 기본 정산 공식 -``` -정산차액 = 가지급금 총액 - 실사용 총액 -``` - -### 4.5 인정이자 계산 공식 (법인세법 기준) -``` -경과일수 = 정산일 - 지급일 -일이자율 = 연이자율 ÷ 365 -인정이자 = 가지급금 × 일이자율 × 경과일수 -``` - -## 5. AI 리포트 생성 (슬라이드 113) - -### 5.1 AI 리포트 생성 프롬프트 - -#### 작성 규칙 -1. 문장은 간결하고 명확하게 작성 -2. 숫자는 읽기 쉽게 "3,123,000원", "15%" 형식 사용 -3. 계정과목명, 거래처명은 구체적으로 명시 -4. 조치가 필요한 경우 구체적인 행동 권한 포함 -5. 긍정적 변화도 반드시 실상 포함 -6. 법인세, 소득세 영향이 있는 경우 세무 리스크 명시 - -#### 키워드 강조 규칙 -출력 메시지 내 다음 키워드는 프론트엔드에서 색상 강조됩니다: -- **빨간색(경고)**: 초과, 증가, 발생, 필요, 불가 -- **주황색(주의)**: 점검, 확인, 주의, 검토 -- **녹색(긍정)**: 감소, 완료, 정상 -- **파란색(양호)**: 여유, 적정, 양호 - -#### 예시 출력 -입력 데이터 예시에 대한 출력: - -```json -{"리포트": [ - {"영역": "지출분석", "상태": "경고", "메시지": "이번 달 예상 지출이 전월 대비 15% 증가했습니다.", "상세": "매입 비용 증가가 주요 원인입니다."}, - {"영역": "가지급금", "상태": "주의", "메시지": "50일 이상 잔기 미수금 3건(2,500만원) 발생.", "상세": "회수 조치가 필요합니다."}, - {"영역": "카드/계좌", "상태": "경고", "메시지": "법인카드 사용 한도 85% 도달, 잔여 한도 600만원입니다.", "상세": "사용 계획을 점검해 주세요."}, - {"영역": "미수금", "상태": "주의", "메시지": "미수금에 대한 관리가 필요한 상태입니다.", "상세": ""} -], -"요약": "지출 증가와 정기 미수금에 대한 관리가 필요한 상태입니다."} -``` - ---- - -## 데이터 모델 - -### DailyReport (일일 일보) -``` -- id: bigint -- tenant_id: bigint (FK) -- report_date: date -- previous_balance: decimal -- daily_deposit: decimal -- daily_withdrawal: decimal -- current_balance: decimal -- details: json # 입출금 상세 내역 -- created_at: timestamp -``` - -### ExpenseEstimate (지출 예상 내역서) -``` -- id: bigint -- tenant_id: bigint (FK) -- expected_date: date -- item_name: string -- amount: decimal -- vendor_id: bigint (FK, nullable) -- account_id: bigint (FK, nullable) -- created_at: timestamp -``` - -### LoanInterestCalculation (가지급금 인정이자 계산) -``` -- id: bigint -- tenant_id: bigint (FK) -- calculation_date: date -- loan_balance: decimal -- interest_rate: decimal -- recognized_interest: decimal -- corporate_tax_addition: decimal -- income_tax_addition: decimal -- local_tax_addition: decimal -- total_tax_burden: decimal -- created_at: timestamp -``` - -### AIReport (AI 리포트) -``` -- id: bigint -- tenant_id: bigint (FK) -- report_date: date -- report_type: string -- content: json # 리포트 내용 -- summary: text -- created_at: timestamp -``` - ---- - -## API 도출 - -### 일일 일보 API -``` -GET /api/reports/daily # 일일 일보 조회 -GET /api/reports/daily/export # 일일 일보 엑셀 다운로드 -``` - -### 지출 예상 내역서 API -``` -GET /api/reports/expense-estimate # 지출 예상 내역서 조회 -POST /api/reports/expense-estimate # 지출 예상 내역 등록 -PUT /api/reports/expense-estimate/{id}# 지출 예상 내역 수정 -DELETE /api/reports/expense-estimate/{id}# 지출 예상 내역 삭제 -GET /api/reports/expense-estimate/export # 지출 예상 내역서 엑셀 다운로드 -``` - -### 가지급금 인정이자 API -``` -GET /api/reports/loan-interest # 가지급금 인정이자 계산 조회 -POST /api/reports/loan-interest/calculate # 가지급금 인정이자 계산 실행 -``` - -### AI 리포트 API -``` -GET /api/reports/ai # AI 리포트 목록 -POST /api/reports/ai/generate # AI 리포트 생성 -GET /api/reports/ai/{id} # AI 리포트 상세 -DELETE /api/reports/ai/{id} # AI 리포트 삭제 -``` - -### 대시보드/분석 API -``` -GET /api/dashboard/summary # 대시보드 요약 -GET /api/dashboard/charts # 대시보드 차트 데이터 -GET /api/analytics/sales # 매출 분석 -GET /api/analytics/expense # 지출 분석 -GET /api/analytics/receivables # 미수금 분석 -``` \ No newline at end of file diff --git a/specs/erp-analysis/99-gap-analysis.md b/specs/erp-analysis/99-gap-analysis.md deleted file mode 100644 index c068c27..0000000 --- a/specs/erp-analysis/99-gap-analysis.md +++ /dev/null @@ -1,1048 +0,0 @@ -# SAM ERP API 개발 명세서 - -> 기준 문서: SAM_ERP_Storyboard_D0.8_251216 -> 작성일: 2025-12-17 -> 상태: 개발 준비 완료 - ---- - -## 개발 범위 요약 - -| 구분 | 항목수 | 작업 | -|------|--------|------| -| 기존 API 활용 | 12개 | 프론트엔드 연동만 진행 | -| 확장 개발 | 6개 | 기존 구조 활용, API 추가 | -| 신규 개발 | 8개 | 테이블 + API 신규 생성 | - ---- - -# Part 1: 기존 API (프론트엔드 연동) - -> 아래 영역은 API 개발 완료. 프론트엔드 연동 시 참고. - -| 영역 | 기존 API | 스토리보드 참조 | -|------|----------|-----------------| -| 사원관리 | `/v1/employees/*` | 슬라이드 28-35 | -| 부서관리 | `/v1/departments/*` | 슬라이드 36-38 | -| 근태관리 | `/v1/attendances/*` | 슬라이드 23-27, 39-42 | -| 게시판 | `/v1/boards/*` | - | -| 권한관리 | `/v1/roles/*`, `/v1/permissions/*` | 슬라이드 96 | -| 테넌트 | `/v1/tenants/*` | 슬라이드 14-22 | -| 메뉴 | `/v1/menus/*` | 슬라이드 8-13 | -| 거래처 | `/v1/clients/*` | 슬라이드 60-67 | -| 공통코드 | `/v1/settings/common/*` | 슬라이드 93-95 | -| 파일 | `/v1/files/*` | - | -| 설정 | `/v1/settings/*` | - | -| 프로필 | `/v1/users/me/*`, `/v1/profiles/*` | - | - ---- - -# Part 2: 확장 개발 (기존 구조 활용) - -## 2.1 휴가 관리 - -### 스펙 -- 스토리보드: 슬라이드 43-46, 100 -- 의존성: `attendances` 테이블 참조 - -### 테이블: `leaves` -```sql -CREATE TABLE leaves ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - user_id BIGINT NOT NULL, - leave_type VARCHAR(20) NOT NULL COMMENT '연차/반차/병가/경조사/출산/육아', - start_date DATE NOT NULL, - end_date DATE NOT NULL, - days DECIMAL(3,1) NOT NULL COMMENT '사용일수', - reason TEXT, - status VARCHAR(20) DEFAULT 'pending' COMMENT 'pending/approved/rejected/cancelled', - approved_by BIGINT NULL, - approved_at TIMESTAMP NULL, - reject_reason TEXT NULL, - created_by BIGINT, - updated_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant_user (tenant_id, user_id), - INDEX idx_status (status), - INDEX idx_dates (start_date, end_date) -); -``` - -### 테이블: `leave_balances` -```sql -CREATE TABLE leave_balances ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - user_id BIGINT NOT NULL, - year INT NOT NULL, - total_days DECIMAL(4,1) NOT NULL DEFAULT 15 COMMENT '연간 부여일수', - used_days DECIMAL(4,1) NOT NULL DEFAULT 0 COMMENT '사용일수', - remaining_days DECIMAL(4,1) GENERATED ALWAYS AS (total_days - used_days) STORED, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_tenant_user_year (tenant_id, user_id, year) -); -``` - -### API 엔드포인트 -``` -GET /v1/leaves # 목록 (필터: status, user_id, date_range) -POST /v1/leaves # 신청 -GET /v1/leaves/{id} # 상세 -PATCH /v1/leaves/{id} # 수정 (pending 상태만) -DELETE /v1/leaves/{id} # 취소 (pending 상태만) -POST /v1/leaves/{id}/approve # 승인 -POST /v1/leaves/{id}/reject # 반려 (reject_reason 필수) - -GET /v1/leaves/balance # 내 잔여휴가 -GET /v1/leaves/balance/{userId} # 특정 사용자 잔여휴가 - -GET /v1/settings/leave # 휴가 설정 -PUT /v1/settings/leave # 휴가 설정 수정 -``` - -### Request/Response 예시 -```json -// POST /v1/leaves -{ - "leave_type": "annual", - "start_date": "2025-01-20", - "end_date": "2025-01-21", - "days": 2, - "reason": "개인 사유" -} - -// GET /v1/leaves/balance -{ - "year": 2025, - "total_days": 15, - "used_days": 3, - "remaining_days": 12 -} -``` - ---- - -## 2.2 근무/출퇴근 설정 - -### 스펙 -- 스토리보드: 슬라이드 97-99 -- 의존성: `tenant_field_settings` 활용 가능 - -### 테이블: `work_settings` -```sql -CREATE TABLE work_settings ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL UNIQUE, - work_type VARCHAR(20) DEFAULT 'fixed' COMMENT 'fixed/flexible/custom', - standard_hours INT DEFAULT 40 COMMENT '주당 소정근로시간', - overtime_hours INT DEFAULT 12 COMMENT '주당 연장근로시간', - overtime_limit INT DEFAULT 52 COMMENT '연장근로한도', - work_days JSON COMMENT '["mon","tue","wed","thu","fri"]', - start_time TIME DEFAULT '09:00:00', - end_time TIME DEFAULT '18:00:00', - break_minutes INT DEFAULT 60, - break_start TIME DEFAULT '12:00:00', - break_end TIME DEFAULT '13:00:00', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -); -``` - -### 테이블: `attendance_settings` -```sql -CREATE TABLE attendance_settings ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL UNIQUE, - use_gps BOOLEAN DEFAULT FALSE, - allowed_radius INT DEFAULT 100 COMMENT '허용반경(m)', - hq_address VARCHAR(255), - hq_latitude DECIMAL(10,8), - hq_longitude DECIMAL(11,8), - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -); -``` - -### 테이블: `sites` (현장) -```sql -CREATE TABLE sites ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - name VARCHAR(100) NOT NULL, - address VARCHAR(255), - latitude DECIMAL(10,8), - longitude DECIMAL(11,8), - is_active BOOLEAN DEFAULT TRUE, - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant (tenant_id) -); -``` - -### API 엔드포인트 -``` -GET /v1/settings/work # 근무 설정 조회 -PUT /v1/settings/work # 근무 설정 수정 - -GET /v1/settings/attendance # 출퇴근 설정 조회 -PUT /v1/settings/attendance # 출퇴근 설정 수정 - -GET /v1/sites # 현장 목록 -POST /v1/sites # 현장 등록 -GET /v1/sites/{id} # 현장 상세 -PUT /v1/sites/{id} # 현장 수정 -DELETE /v1/sites/{id} # 현장 삭제 -``` - ---- - -## 2.3 카드/계좌 관리 - -### 스펙 -- 스토리보드: 슬라이드 101-104 -- 보안: 카드번호/비밀번호 암호화 필수 - -### 테이블: `cards` -```sql -CREATE TABLE cards ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - card_company VARCHAR(50) NOT NULL COMMENT '카드사', - card_number_encrypted TEXT NOT NULL COMMENT '암호화된 카드번호', - card_number_last4 VARCHAR(4) NOT NULL COMMENT '끝 4자리', - expiry_date VARCHAR(5) NOT NULL COMMENT 'MM/YY', - card_password_encrypted TEXT COMMENT '암호화된 비밀번호 앞2자리', - card_name VARCHAR(100) NOT NULL, - status VARCHAR(20) DEFAULT 'active' COMMENT 'active/inactive', - assigned_user_id BIGINT NULL, - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant (tenant_id), - INDEX idx_status (status) -); -``` - -### 테이블: `bank_accounts` -```sql -CREATE TABLE bank_accounts ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - bank_code VARCHAR(10) NOT NULL, - bank_name VARCHAR(50) NOT NULL, - account_number VARCHAR(30) NOT NULL, - account_holder VARCHAR(50) NOT NULL, - account_name VARCHAR(100) NOT NULL COMMENT '계좌별칭', - status VARCHAR(20) DEFAULT 'active' COMMENT 'active/inactive', - assigned_user_id BIGINT NULL, - is_primary BOOLEAN DEFAULT FALSE COMMENT '대표계좌', - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant (tenant_id), - INDEX idx_status (status) -); -``` - -### API 엔드포인트 -``` -GET /v1/cards # 카드 목록 (필터: status) -POST /v1/cards # 카드 등록 -GET /v1/cards/{id} # 카드 상세 -PUT /v1/cards/{id} # 카드 수정 -DELETE /v1/cards/{id} # 카드 삭제 -PATCH /v1/cards/{id}/toggle # 사용/정지 토글 - -GET /v1/bank-accounts # 계좌 목록 (필터: status) -POST /v1/bank-accounts # 계좌 등록 -GET /v1/bank-accounts/{id} # 계좌 상세 -PUT /v1/bank-accounts/{id} # 계좌 수정 -DELETE /v1/bank-accounts/{id} # 계좌 삭제 -PATCH /v1/bank-accounts/{id}/toggle # 사용/정지 토글 -PATCH /v1/bank-accounts/{id}/set-primary # 대표계좌 설정 -``` - ---- - -## 2.4 입금/출금 관리 - -### 스펙 -- 스토리보드: 슬라이드 68-77 -- 의존성: `clients`, `bank_accounts` 참조 - -### 테이블: `deposits` (입금) -```sql -CREATE TABLE deposits ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - deposit_date DATE NOT NULL, - client_id BIGINT NULL, - client_name VARCHAR(100) COMMENT '비회원 거래처명', - bank_account_id BIGINT NULL, - amount DECIMAL(15,2) NOT NULL, - payment_method VARCHAR(20) NOT NULL COMMENT 'cash/transfer/card/check', - account_code VARCHAR(20) COMMENT '계정과목', - description TEXT, - reference_type VARCHAR(50) NULL COMMENT 'sales/receivable/etc', - reference_id BIGINT NULL, - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant_date (tenant_id, deposit_date), - INDEX idx_client (client_id) -); -``` - -### 테이블: `withdrawals` (출금) -```sql -CREATE TABLE withdrawals ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - withdrawal_date DATE NOT NULL, - client_id BIGINT NULL, - client_name VARCHAR(100), - bank_account_id BIGINT NULL, - amount DECIMAL(15,2) NOT NULL, - payment_method VARCHAR(20) NOT NULL COMMENT 'cash/transfer/card/check', - account_code VARCHAR(20) COMMENT '계정과목', - description TEXT, - reference_type VARCHAR(50) NULL COMMENT 'purchase/payable/payroll/etc', - reference_id BIGINT NULL, - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant_date (tenant_id, withdrawal_date), - INDEX idx_client (client_id) -); -``` - -### API 엔드포인트 -``` -GET /v1/deposits # 입금 목록 (필터: date_range, client_id, payment_method) -POST /v1/deposits # 입금 등록 -GET /v1/deposits/{id} # 입금 상세 -PUT /v1/deposits/{id} # 입금 수정 -DELETE /v1/deposits/{id} # 입금 삭제 -GET /v1/deposits/summary # 입금 요약 (기간별 합계) - -GET /v1/withdrawals # 출금 목록 -POST /v1/withdrawals # 출금 등록 -GET /v1/withdrawals/{id} # 출금 상세 -PUT /v1/withdrawals/{id} # 출금 수정 -DELETE /v1/withdrawals/{id} # 출금 삭제 -GET /v1/withdrawals/summary # 출금 요약 -``` - ---- - -## 2.5 매출/매입 관리 - -### 스펙 -- 스토리보드: 슬라이드 78-87 -- 의존성: `clients`, `deposits`, `withdrawals` 참조 - -### 테이블: `sales` (매출) -```sql -CREATE TABLE sales ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - sale_number VARCHAR(30) NOT NULL COMMENT '매출번호', - sale_date DATE NOT NULL, - client_id BIGINT NOT NULL, - supply_amount DECIMAL(15,2) NOT NULL COMMENT '공급가액', - tax_amount DECIMAL(15,2) NOT NULL COMMENT '세액', - total_amount DECIMAL(15,2) NOT NULL COMMENT '합계', - description TEXT, - status VARCHAR(20) DEFAULT 'draft' COMMENT 'draft/confirmed/invoiced', - tax_invoice_id BIGINT NULL COMMENT '세금계산서 ID', - deposit_id BIGINT NULL COMMENT '입금 연결', - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_tenant_number (tenant_id, sale_number), - INDEX idx_tenant_date (tenant_id, sale_date), - INDEX idx_client (client_id) -); -``` - -### 테이블: `purchases` (매입) -```sql -CREATE TABLE purchases ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - purchase_number VARCHAR(30) NOT NULL, - purchase_date DATE NOT NULL, - client_id BIGINT NOT NULL, - supply_amount DECIMAL(15,2) NOT NULL, - tax_amount DECIMAL(15,2) NOT NULL, - total_amount DECIMAL(15,2) NOT NULL, - description TEXT, - status VARCHAR(20) DEFAULT 'draft' COMMENT 'draft/confirmed', - withdrawal_id BIGINT NULL COMMENT '출금 연결', - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_tenant_number (tenant_id, purchase_number), - INDEX idx_tenant_date (tenant_id, purchase_date), - INDEX idx_client (client_id) -); -``` - -### API 엔드포인트 -``` -GET /v1/sales # 매출 목록 -POST /v1/sales # 매출 등록 -GET /v1/sales/{id} # 매출 상세 -PUT /v1/sales/{id} # 매출 수정 -DELETE /v1/sales/{id} # 매출 삭제 -POST /v1/sales/{id}/confirm # 매출 확정 -POST /v1/sales/{id}/tax-invoice # 세금계산서 발행 (바로빌 연동) - -GET /v1/purchases # 매입 목록 -POST /v1/purchases # 매입 등록 -GET /v1/purchases/{id} # 매입 상세 -PUT /v1/purchases/{id} # 매입 수정 -DELETE /v1/purchases/{id} # 매입 삭제 -POST /v1/purchases/{id}/confirm # 매입 확정 -``` - ---- - -## 2.6 보고서 - -### 스펙 -- 스토리보드: 슬라이드 106-109 -- 의존성: `deposits`, `withdrawals`, `sales`, `purchases` 집계 - -### API 엔드포인트 -``` -GET /v1/reports/daily # 일일 일보 - Query: date (기준일) - Response: { - previous_balance, daily_deposit, daily_withdrawal, current_balance, - details: [{ type, client_name, account_code, deposit_amount, withdrawal_amount, description }] - } - -GET /v1/reports/daily/export # 일일 일보 엑셀 다운로드 - Query: date - Response: Excel file - -GET /v1/reports/expense-estimate # 지출 예상 내역서 - Query: year_month - Response: { - total_estimate, account_balance, expected_balance, - items: [{ expected_date, item_name, amount, client_name, account_name }], - monthly_summary: [{ month, total }] - } - -GET /v1/reports/expense-estimate/export # 엑셀 다운로드 - Query: year_month - Response: Excel file -``` - ---- - -# Part 3: 신규 개발 - -## 3.1 전자결재 모듈 - -### 스펙 -- 스토리보드: 슬라이드 47-59 -- 핵심 기능: 기안/결재/반려/참조 - -### 테이블: `approval_forms` (결재 양식) -```sql -CREATE TABLE approval_forms ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - name VARCHAR(100) NOT NULL COMMENT '양식명', - code VARCHAR(50) NOT NULL COMMENT '양식코드', - category VARCHAR(50) COMMENT '분류', - template JSON NOT NULL COMMENT '양식 템플릿 (필드 정의)', - is_active BOOLEAN DEFAULT TRUE, - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_tenant_code (tenant_id, code), - INDEX idx_tenant (tenant_id) -); -``` - -### 테이블: `approval_lines` (결재선 템플릿) -```sql -CREATE TABLE approval_lines ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - name VARCHAR(100) NOT NULL, - steps JSON NOT NULL COMMENT '[{order, type: approval/agreement/reference, user_id, position}]', - is_default BOOLEAN DEFAULT FALSE, - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant (tenant_id) -); -``` - -### 테이블: `approvals` (결재 문서) -```sql -CREATE TABLE approvals ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - document_number VARCHAR(50) NOT NULL, - form_id BIGINT NOT NULL, - title VARCHAR(200) NOT NULL, - content JSON NOT NULL COMMENT '양식 데이터', - status VARCHAR(20) DEFAULT 'draft' COMMENT 'draft/pending/approved/rejected/cancelled', - drafter_id BIGINT NOT NULL COMMENT '기안자', - drafted_at TIMESTAMP NULL, - completed_at TIMESTAMP NULL, - current_step INT DEFAULT 0, - attachments JSON COMMENT '첨부파일 IDs', - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_tenant_number (tenant_id, document_number), - INDEX idx_tenant_status (tenant_id, status), - INDEX idx_drafter (drafter_id) -); -``` - -### 테이블: `approval_steps` (결재 단계) -```sql -CREATE TABLE approval_steps ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - approval_id BIGINT NOT NULL, - step_order INT NOT NULL, - step_type VARCHAR(20) NOT NULL COMMENT 'approval/agreement/reference', - approver_id BIGINT NOT NULL, - status VARCHAR(20) DEFAULT 'pending' COMMENT 'pending/approved/rejected/skipped', - comment TEXT, - acted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - INDEX idx_approval (approval_id), - INDEX idx_approver_status (approver_id, status) -); -``` - -### API 엔드포인트 -``` -# 결재 문서 -GET /v1/approvals/drafts # 기안함 (내가 기안한 문서) -GET /v1/approvals/inbox # 결재함 (내 결재 대기) -GET /v1/approvals/completed # 결재 완료함 -GET /v1/approvals/reference # 참조함 -POST /v1/approvals # 문서 기안 -GET /v1/approvals/{id} # 문서 상세 -PUT /v1/approvals/{id} # 문서 수정 (draft만) -DELETE /v1/approvals/{id} # 문서 삭제/회수 -POST /v1/approvals/{id}/submit # 결재 상신 -POST /v1/approvals/{id}/approve # 승인 (comment 선택) -POST /v1/approvals/{id}/reject # 반려 (comment 필수) - -# 결재선 템플릿 -GET /v1/approval-lines # 결재선 목록 -POST /v1/approval-lines # 결재선 생성 -PUT /v1/approval-lines/{id} # 결재선 수정 -DELETE /v1/approval-lines/{id} # 결재선 삭제 - -# 결재 양식 -GET /v1/approval-forms # 양식 목록 -POST /v1/approval-forms # 양식 생성 -GET /v1/approval-forms/{id} # 양식 상세 -PUT /v1/approval-forms/{id} # 양식 수정 -DELETE /v1/approval-forms/{id} # 양식 삭제 -``` - -### 상태 전이 -``` -draft → pending (상신) → approved (전체 승인) - → rejected (반려) -pending → cancelled (회수, 기안자만) -rejected → draft (재기안 시 새 문서 생성) -``` - ---- - -## 3.2 급여 관리 - -### 스펙 -- 스토리보드: 미상세 (회계관리 연계) -- 의존성: `employees`, `attendances`, `leaves` - -### 테이블: `payrolls` -```sql -CREATE TABLE payrolls ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - user_id BIGINT NOT NULL, - pay_year INT NOT NULL, - pay_month INT NOT NULL, - base_salary DECIMAL(15,2) NOT NULL COMMENT '기본급', - overtime_pay DECIMAL(15,2) DEFAULT 0 COMMENT '연장근로수당', - bonus DECIMAL(15,2) DEFAULT 0 COMMENT '상여금', - allowances JSON COMMENT '수당 상세 [{name, amount}]', - gross_salary DECIMAL(15,2) NOT NULL COMMENT '총지급액', - income_tax DECIMAL(15,2) DEFAULT 0 COMMENT '소득세', - resident_tax DECIMAL(15,2) DEFAULT 0 COMMENT '주민세', - health_insurance DECIMAL(15,2) DEFAULT 0 COMMENT '건강보험', - pension DECIMAL(15,2) DEFAULT 0 COMMENT '국민연금', - employment_insurance DECIMAL(15,2) DEFAULT 0 COMMENT '고용보험', - deductions JSON COMMENT '공제 상세', - total_deductions DECIMAL(15,2) NOT NULL COMMENT '총공제액', - net_salary DECIMAL(15,2) NOT NULL COMMENT '실수령액', - status VARCHAR(20) DEFAULT 'draft' COMMENT 'draft/confirmed/paid', - paid_at TIMESTAMP NULL, - withdrawal_id BIGINT NULL COMMENT '출금 연결', - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_tenant_user_month (tenant_id, user_id, pay_year, pay_month), - INDEX idx_tenant_month (tenant_id, pay_year, pay_month) -); -``` - -### API 엔드포인트 -``` -GET /v1/payrolls # 급여 목록 (필터: year, month, user_id, status) -POST /v1/payrolls # 급여 등록 -GET /v1/payrolls/{id} # 급여 상세 -PUT /v1/payrolls/{id} # 급여 수정 (draft만) -DELETE /v1/payrolls/{id} # 급여 삭제 (draft만) -POST /v1/payrolls/{id}/confirm # 급여 확정 -POST /v1/payrolls/{id}/pay # 지급 처리 (출금 연결) -GET /v1/payrolls/{id}/payslip # 급여명세서 조회 -GET /v1/payrolls/{id}/payslip/pdf # 급여명세서 PDF - -POST /v1/payrolls/calculate # 급여 일괄 계산 - Body: { year, month, user_ids?: [] } // user_ids 없으면 전체 - -GET /v1/settings/payroll # 급여 설정 (세율, 보험료율 등) -PUT /v1/settings/payroll # 급여 설정 수정 -``` - ---- - -## 3.3 대시보드 - -### 스펙 -- 스토리보드: 미상세 (진입점 화면) -- 의존성: 전 모듈 집계 - -### API 엔드포인트 -``` -GET /v1/dashboard/summary - Response: { - today: { date, attendances_count, leaves_count, approvals_pending }, - finance: { monthly_deposit, monthly_withdrawal, balance }, - sales: { monthly_sales, monthly_purchases }, - tasks: { pending_approvals, pending_leaves } - } - -GET /v1/dashboard/charts - Query: period (week/month/quarter) - Response: { - deposit_trend: [{ date, amount }], - withdrawal_trend: [{ date, amount }], - sales_by_client: [{ client_name, amount }] - } - -GET /v1/dashboard/notifications - Query: limit (default 10) - Response: { - items: [{ id, type, message, is_read, created_at }] - } - -GET /v1/dashboard/approvals - Response: { - items: [{ id, title, drafter_name, status, created_at }] - } -``` - ---- - -## 3.4 AI 리포트 - -### 스펙 -- 스토리보드: 슬라이드 113 -- 의존성: 전 모듈 데이터 분석 - -### 테이블: `ai_reports` -```sql -CREATE TABLE ai_reports ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - report_date DATE NOT NULL, - report_type VARCHAR(50) NOT NULL COMMENT 'daily/weekly/monthly', - content JSON NOT NULL COMMENT '리포트 내용', - summary TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - INDEX idx_tenant_date (tenant_id, report_date) -); -``` - -### API 엔드포인트 -``` -GET /v1/reports/ai # AI 리포트 목록 -POST /v1/reports/ai/generate # AI 리포트 생성 - Body: { report_type: 'daily'|'weekly'|'monthly', target_date? } -GET /v1/reports/ai/{id} # AI 리포트 상세 -DELETE /v1/reports/ai/{id} # AI 리포트 삭제 -``` - -### AI 리포트 출력 형식 -```json -{ - "report": [ - { "area": "지출분석", "status": "warning", "message": "...", "detail": "..." }, - { "area": "미수금", "status": "caution", "message": "...", "detail": "..." } - ], - "summary": "전체 요약 메시지" -} -``` -- status: `warning`(빨강), `caution`(주황), `positive`(녹색), `normal`(파랑) - ---- - -## 3.5 가지급금 관리 - -### 스펙 -- 스토리보드: 슬라이드 110-112 -- 인정이자율: 4.6% (연도별 변동) - -### 테이블: `loans` (가지급금) -```sql -CREATE TABLE loans ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - user_id BIGINT NOT NULL COMMENT '가지급금 수령자', - loan_date DATE NOT NULL COMMENT '지급일', - amount DECIMAL(15,2) NOT NULL COMMENT '가지급금액', - purpose TEXT COMMENT '사용목적', - settlement_date DATE NULL COMMENT '정산일', - settlement_amount DECIMAL(15,2) NULL COMMENT '정산금액', - status VARCHAR(20) DEFAULT 'outstanding' COMMENT 'outstanding/settled/partial', - withdrawal_id BIGINT NULL COMMENT '출금 연결', - created_by BIGINT, - deleted_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant_user (tenant_id, user_id), - INDEX idx_status (status) -); -``` - -### API 엔드포인트 -``` -GET /v1/loans # 가지급금 목록 -POST /v1/loans # 가지급금 등록 -GET /v1/loans/{id} # 가지급금 상세 -PUT /v1/loans/{id} # 가지급금 수정 -DELETE /v1/loans/{id} # 가지급금 삭제 -POST /v1/loans/{id}/settle # 정산 처리 - Body: { settlement_date, settlement_amount } - -POST /v1/loans/calculate-interest # 인정이자 계산 - Body: { year, user_id? } - Response: { - balance, interest_rate, recognized_interest, - corporate_tax, income_tax, local_tax, total_tax - } - -GET /v1/reports/loan-interest # 인정이자 리포트 - Query: year -``` - -### 계산 공식 -``` -경과일수 = 정산일 - 지급일 -일이자율 = 연이자율 / 365 -인정이자 = 가지급금 × 일이자율 × 경과일수 -법인세추가 = 인정이자 × 0.19 -소득세추가 = 인정이자 × 0.35 -지방소득세 = 소득세추가 × 0.10 -``` - ---- - -## 3.6 구독/결제 관리 - -### 스펙 -- 스토리보드: 미상세 (SaaS 과금) -- 별도 결제 시스템 연동 필요 - -### 테이블: `subscriptions` -```sql -CREATE TABLE subscriptions ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL UNIQUE, - plan_code VARCHAR(50) NOT NULL COMMENT 'basic/standard/premium', - status VARCHAR(20) DEFAULT 'active' COMMENT 'trial/active/expired/cancelled', - started_at DATE NOT NULL, - expires_at DATE NOT NULL, - user_limit INT DEFAULT 5, - storage_limit_mb INT DEFAULT 1024, - auto_renew BOOLEAN DEFAULT TRUE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -); -``` - -### 테이블: `payments` -```sql -CREATE TABLE payments ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - subscription_id BIGINT NOT NULL, - amount DECIMAL(10,2) NOT NULL, - payment_method VARCHAR(20) COMMENT 'card/transfer', - status VARCHAR(20) DEFAULT 'pending' COMMENT 'pending/completed/failed/refunded', - paid_at TIMESTAMP NULL, - pg_transaction_id VARCHAR(100), - receipt_url VARCHAR(500), - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - INDEX idx_tenant (tenant_id), - INDEX idx_status (status) -); -``` - -### API 엔드포인트 -``` -GET /v1/subscriptions # 구독 정보 -POST /v1/subscriptions # 구독 신청/변경 -PUT /v1/subscriptions/{id} # 구독 수정 -DELETE /v1/subscriptions/{id} # 구독 해지 - -GET /v1/payments # 결제 내역 -GET /v1/payments/{id} # 결제 상세 -POST /v1/payments/retry/{id} # 결제 재시도 -``` - ---- - -## 3.7 고객센터 - -### 스펙 -- 스토리보드: 미상세 (CS 기능) - -### 테이블: `support_tickets` -```sql -CREATE TABLE support_tickets ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NULL COMMENT 'NULL이면 비회원 문의', - user_id BIGINT NULL, - ticket_number VARCHAR(20) NOT NULL, - category VARCHAR(50) NOT NULL COMMENT '문의유형', - title VARCHAR(200) NOT NULL, - content TEXT NOT NULL, - status VARCHAR(20) DEFAULT 'open' COMMENT 'open/in_progress/resolved/closed', - priority VARCHAR(20) DEFAULT 'normal' COMMENT 'low/normal/high/urgent', - assigned_to BIGINT NULL COMMENT '담당자', - resolved_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY uk_ticket_number (ticket_number), - INDEX idx_status (status) -); -``` - -### 테이블: `support_ticket_replies` -```sql -CREATE TABLE support_ticket_replies ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - ticket_id BIGINT NOT NULL, - user_id BIGINT NULL COMMENT 'NULL이면 관리자 답변', - is_staff BOOLEAN DEFAULT FALSE, - content TEXT NOT NULL, - attachments JSON, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - INDEX idx_ticket (ticket_id) -); -``` - -### 테이블: `faqs` -```sql -CREATE TABLE faqs ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - category VARCHAR(50) NOT NULL, - question VARCHAR(500) NOT NULL, - answer TEXT NOT NULL, - sort_order INT DEFAULT 0, - is_active BOOLEAN DEFAULT TRUE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_category (category) -); -``` - -### API 엔드포인트 -``` -GET /v1/support/tickets # 문의 목록 -POST /v1/support/tickets # 문의 등록 -GET /v1/support/tickets/{id} # 문의 상세 -PUT /v1/support/tickets/{id} # 문의 수정 -POST /v1/support/tickets/{id}/reply # 답변/추가문의 - -GET /v1/support/faq # FAQ 목록 (필터: category) -GET /v1/support/faq/{id} # FAQ 상세 -``` - ---- - -## 3.8 바로빌 연동 - -### 스펙 -- 스토리보드: 슬라이드 63, 78 -- 외부 API: 바로빌 (사업자조회, 세금계산서) - -### 테이블: `tax_invoices` -```sql -CREATE TABLE tax_invoices ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - tenant_id BIGINT NOT NULL, - invoice_type VARCHAR(20) NOT NULL COMMENT 'sales/purchase', - invoice_number VARCHAR(50) NOT NULL COMMENT '승인번호', - issue_date DATE NOT NULL, - supplier_business_no VARCHAR(20) NOT NULL, - supplier_name VARCHAR(100) NOT NULL, - buyer_business_no VARCHAR(20) NOT NULL, - buyer_name VARCHAR(100) NOT NULL, - supply_amount DECIMAL(15,2) NOT NULL, - tax_amount DECIMAL(15,2) NOT NULL, - total_amount DECIMAL(15,2) NOT NULL, - status VARCHAR(20) DEFAULT 'issued' COMMENT 'issued/cancelled', - barobill_id VARCHAR(100) COMMENT '바로빌 문서 ID', - reference_type VARCHAR(50) NULL COMMENT 'sales/purchases', - reference_id BIGINT NULL, - issued_at TIMESTAMP NULL, - cancelled_at TIMESTAMP NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX idx_tenant_date (tenant_id, issue_date), - INDEX idx_invoice_number (invoice_number) -); -``` - -### API 엔드포인트 -``` -POST /v1/external/barobill/verify-business - Body: { business_number } - Response: { valid, company_name, ceo_name, business_type, ... } - -POST /v1/external/barobill/tax-invoice - Body: { invoice_type, supplier, buyer, items, ... } - Response: { id, invoice_number, barobill_id } - -GET /v1/external/barobill/tax-invoice/{id} - Response: 세금계산서 상세 - -POST /v1/external/barobill/tax-invoice/{id}/cancel - Response: 취소 결과 - -GET /v1/tax-invoices # 세금계산서 목록 (내부 조회용) -GET /v1/tax-invoices/{id} # 세금계산서 상세 -``` - ---- - -# Part 4: 기획 확인 필요 - -> 아래 항목은 API 구현 전 비즈니스 로직 확정 필요 - -## 4.1 상태 전이 조건 - -| 대상 | 확인 항목 | 기본값 (확정 전) | -|------|----------|------------------| -| 테넌트 | 신청→승인→만료→해지 전이 조건 | 수동 전환 | -| 사원 | 휴직→복직/퇴사 전이 조건 | 수동 전환 | -| 결재 | 반려 후 재기안 프로세스 | 새 문서 생성 | -| 미수금 | 연체 판정 기준일 | 30일 | -| 악성채권 | 악성채권 판정 조건 | 90일 + 수동 | - -## 4.2 모듈 간 연동 - -| 연동 | 확인 항목 | 기본값 | -|------|----------|--------| -| 전자결재→회계 | 지출결의서 승인 시 출금 자동 생성 | 수동 연결 | -| 휴가신청→결재 | 휴가가 결재 문서로 생성되는지 | 별도 관리 | -| 휴가승인→근태 | 승인 휴가가 근태 자동 반영 | 자동 반영 | -| GPS출퇴근→근태 | GPS 기록이 근태 자동 반영 | 자동 반영 | -| 급여→출금 | 급여 확정 시 출금 자동 생성 | 수동 연결 | - -## 4.3 외부 연동 - -| 항목 | 확인 필요 | -|------|----------| -| 바로빌 API 비용 | 호출당 비용, 월 한도 | -| 연동 은행 범위 | 지원 은행 목록 | -| 연동 실패 처리 | Retry 정책, fallback | - -## 4.4 MES 메뉴 - -| 메뉴 | 확인 필요 | -|------|----------| -| 영업관리 | 기존 Quote API 활용 여부 | -| 판매관리 | 상세 요구사항 | -| 구매관리 | 상세 요구사항 | - -## 4.5 어음관리 - -| 항목 | 확인 필요 | -|------|----------| -| 기능 필요성 | 사용 여부 | -| 상세 기능 | 등록/만기일/추심/부도 | - ---- - -# 개발 순서 - -``` -Phase 1: 확장 개발 (1-2주) -├── 2.1 휴가 관리 -├── 2.2 근무/출퇴근 설정 -├── 2.3 카드/계좌 관리 -├── 2.4 입금/출금 관리 -├── 2.5 매출/매입 관리 -└── 2.6 보고서 - -Phase 2: 핵심 신규 (2-4주) -├── 3.1 전자결재 모듈 ★ -├── 3.2 급여 관리 -└── 3.3 대시보드 - -Phase 3: 추가 기능 (4-6주) -├── 3.4 AI 리포트 -├── 3.5 가지급금 관리 -└── 3.8 바로빌 연동 - -Phase 4: SaaS 기능 (별도) -├── 3.6 구독/결제 관리 -└── 3.7 고객센터 -``` - ---- - -# 참고 문서 - -| 문서 | 경로 | -|------|------| -| DB 스키마 | `docs/specs/database-schema.md` | -| 시스템 아키텍처 | `docs/architecture/system-overview.md` | -| HR API 분석 | `docs/features/hr/hr-api-analysis.md` | -| 기존 API 라우트 | `api/routes/api.php` | -| 스토리보드 상세 | `docs/specs/erp-analysis/01-common.md` ~ `08-reports.md` | \ No newline at end of file diff --git a/specs/item-master-integration.md b/specs/item-master-integration.md deleted file mode 100644 index 5caf1e9..0000000 --- a/specs/item-master-integration.md +++ /dev/null @@ -1,661 +0,0 @@ -# ItemMaster 연동 설계서 - -**작성일**: 2025-12-05 -**최종 수정**: 2025-12-08 -**버전**: 1.1 -**상태**: Draft - ---- - -## 1. 개요 - -### 1.1 목적 -품목기준관리(ItemMaster)에서 정의한 필드와 실제 엔티티 데이터를 연동하여, 동적 필드 정의 및 값 저장을 가능하게 한다. - -### 1.2 설계 원칙 -- **기존 테이블 활용**: 신규 테이블 추가 없이 기존 `attributes` JSON 컬럼 활용 -- **범용성**: 품목(products, materials) 외에도 다른 엔티티(orders, clients 등) 확장 가능 -- **성능**: JOIN 없이 단일 쿼리로 조회 가능 -- **유연성**: 테넌트/그룹별 다른 필드 구성 지원 - ---- - -## 2. 현재 구조 - -### 2.1 ItemMaster 테이블 구조 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ item_pages (페이지 정의) │ -├─────────────────────────────────────────────────────────────┤ -│ id, tenant_id, page_name, item_type, source_table, │ -│ is_active │ -│ │ -│ item_type: FG(완제품), PT(반제품), SM(부자재), │ -│ RM(원자재), CS(소모품) │ -│ │ -│ source_table: 실제 저장 테이블명 │ -│ - 'products' (FG, PT) │ -│ - 'materials' (SM, RM, CS) │ -└─────────────────────────────────────────────────────────────┘ - │ - │ 1:N - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ item_sections (섹션 정의) │ -├─────────────────────────────────────────────────────────────┤ -│ id, tenant_id, page_id, title, type, order_no │ -│ │ -│ type: fields(필드형), bom(BOM형) │ -└─────────────────────────────────────────────────────────────┘ - │ - │ 1:N - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ item_fields (필드 정의) │ -├─────────────────────────────────────────────────────────────┤ -│ id, tenant_id, group_id, section_id (nullable) │ -│ field_key ← attributes JSON 키와 매핑 │ -│ field_name ← 화면 표시명 │ -│ field_type ← textbox, number, dropdown, checkbox... │ -│ is_required ← 필수 여부 │ -│ default_value ← 기본값 │ -│ placeholder ← 입력 힌트 │ -│ validation_rules ← 검증 규칙 JSON │ -│ options ← 선택 옵션 JSON │ -│ properties ← 추가 속성 JSON │ -│ category ← 필드 카테고리 │ -│ is_common ← 공통 필드 여부 │ -│ is_active ← 활성 여부 │ -│ │ -│ [내부용 매핑 컬럼 - API 응답에서 hidden] │ -│ source_table ← 원본 테이블명 (products, materials 등) │ -│ source_column ← 원본 컬럼명 (code, name 등) │ -│ storage_type ← 저장방식 (column=DB컬럼, json=JSON) │ -│ json_path ← JSON 저장 경로 (예: attributes.size) │ -└─────────────────────────────────────────────────────────────┘ -``` - -### 2.2 엔티티 테이블 구조 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ products │ -├─────────────────────────────────────────────────────────────┤ -│ [고정 필드] │ -│ id, tenant_id, code, name, unit, category_id │ -│ product_type, is_active, is_sellable, is_purchasable... │ -│ │ -│ [동적 필드] │ -│ attributes JSON ← ItemMaster 필드 값 저장 │ -└─────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────┐ -│ materials │ -├─────────────────────────────────────────────────────────────┤ -│ [고정 필드] │ -│ id, tenant_id, material_code, name, unit, category_id │ -│ material_type, is_active... │ -│ │ -│ [동적 필드] │ -│ attributes JSON ← ItemMaster 필드 값 저장 │ -│ options JSON ← 추가 옵션 저장 │ -└─────────────────────────────────────────────────────────────┘ -``` - ---- - -## 3. 연동 설계 - -### 3.1 매핑 규칙 - -``` -ItemMaster Entity.attributes -┌──────────────────────┐ ┌──────────────────────┐ -│ group_id: 1 │ │ │ -│ field_key: "color" │ ◀═══매핑═══▶ │ {"color": "빨강"} │ -│ field_key: "weight" │ ◀═══매핑═══▶ │ {"weight": 1.5} │ -│ field_key: "spec" │ ◀═══매핑═══▶ │ {"spec": "10x20"} │ -└──────────────────────┘ └──────────────────────┘ - -핵심: item_fields.field_key = attributes JSON의 key -``` - -### 3.2 Group ID 정의 - -| group_id | 엔티티 | 대상 테이블 | 비고 | -|----------|--------|-------------|------| -| 1 | 품목-제품 | products | product_type: FG, PT | -| 2 | 품목-자재 | materials | material_type: SM, RM, CS | -| 3 | 주문 | orders | 향후 확장 | -| 4 | 고객 | clients | 향후 확장 | -| ... | ... | ... | 필요 시 추가 | - -> **참고**: group_id는 `common_codes` 테이블에서 관리하거나, 별도 enum으로 정의 가능 - -### 3.3 데이터 흐름 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ 1. 관리자: ItemMaster에서 필드 정의 │ -├─────────────────────────────────────────────────────────────┤ -│ │ -│ POST /api/v1/item-master/fields │ -│ { │ -│ "group_id": 1, │ -│ "field_key": "color", │ -│ "field_name": "색상", │ -│ "field_type": "dropdown", │ -│ "is_required": true, │ -│ "options": [ │ -│ {"label": "빨강", "value": "red"}, │ -│ {"label": "파랑", "value": "blue"} │ -│ ] │ -│ } │ -│ │ -│ → item_fields 테이블에 저장 │ -└─────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ 2. 사용자: 품목 등록 화면 진입 │ -├─────────────────────────────────────────────────────────────┤ -│ │ -│ GET /api/v1/item-master/fields?group_id=1 │ -│ │ -│ → 정의된 필드 목록 반환 │ -│ → 프론트엔드가 동적 폼 렌더링 │ -│ │ -│ ┌────────────────────────────────────┐ │ -│ │ [색상 ▼] ← dropdown으로 표시 │ │ -│ │ 빨강 │ │ -│ │ 파랑 │ │ -│ └────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ 3. 사용자: 품목 저장 │ -├─────────────────────────────────────────────────────────────┤ -│ │ -│ POST /api/v1/products │ -│ { │ -│ "code": "P-001", ← 고정 필드 │ -│ "name": "티셔츠", │ -│ "unit": "EA", │ -│ "product_type": "FG", │ -│ "attributes": { ← 동적 필드 │ -│ "color": "red", (field_key: value) │ -│ "size": "XL" │ -│ } │ -│ } │ -│ │ -│ → products 테이블에 저장 │ -│ → attributes JSON에 동적 필드 값 포함 │ -└─────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────┐ -│ 4. 사용자: 품목 조회 │ -├─────────────────────────────────────────────────────────────┤ -│ │ -│ GET /api/v1/products/1 │ -│ │ -│ { │ -│ "id": 1, │ -│ "code": "P-001", │ -│ "name": "티셔츠", │ -│ "attributes": { │ -│ "color": "red", │ -│ "size": "XL" │ -│ } │ -│ } │ -│ │ -│ → JOIN 없이 한 번에 조회! │ -└─────────────────────────────────────────────────────────────┘ -``` - ---- - -## 4. API 설계 - -### 4.1 ItemMaster API (기존) - -| Method | Endpoint | 설명 | -|--------|----------|------| -| GET | `/api/v1/item-master/fields` | 필드 목록 조회 | -| GET | `/api/v1/item-master/fields/{id}` | 필드 상세 조회 | -| POST | `/api/v1/item-master/fields` | 필드 생성 | -| PUT | `/api/v1/item-master/fields/{id}` | 필드 수정 | -| DELETE | `/api/v1/item-master/fields/{id}` | 필드 삭제 | - -**필터 파라미터**: -- `group_id`: 엔티티 그룹 필터 -- `section_id`: 섹션 필터 -- `is_active`: 활성 필터 -- `is_common`: 공통 필드 필터 - -### 4.2 엔티티 API 수정 - -#### 4.2.1 Products API - -**저장 시 attributes 포함**: -```json -POST /api/v1/products -{ - "code": "P-001", - "name": "제품명", - "unit": "EA", - "product_type": "FG", - "attributes": { - "color": "red", - "weight": 1.5, - "custom_field": "value" - } -} -``` - -**조회 시 필드 메타데이터 포함 (선택)**: -``` -GET /api/v1/products/1?include_field_meta=true -``` - -```json -{ - "id": 1, - "code": "P-001", - "name": "제품명", - "attributes": { - "color": "red", - "weight": 1.5 - }, - "field_meta": [ - { - "field_key": "color", - "field_name": "색상", - "field_type": "dropdown", - "value": "red", - "options": [...] - }, - { - "field_key": "weight", - "field_name": "중량", - "field_type": "number", - "value": 1.5 - } - ] -} -``` - ---- - -## 5. 검증 로직 - -### 5.1 저장 시 검증 흐름 - -```php -class ItemFieldValidationService -{ - /** - * attributes 값을 ItemMaster 기준으로 검증 - */ - public function validate(int $groupId, array $attributes): array - { - $errors = []; - - // 1. 해당 그룹의 필드 정의 조회 - $fields = ItemField::where('group_id', $groupId) - ->where('is_active', true) - ->get() - ->keyBy('field_key'); - - // 2. 필수 필드 체크 - foreach ($fields->where('is_required', true) as $field) { - if (!isset($attributes[$field->field_key])) { - $errors[$field->field_key] = "{$field->field_name}은(는) 필수입니다."; - } - } - - // 3. 타입별 검증 - foreach ($attributes as $key => $value) { - if (!$fields->has($key)) { - continue; // 정의되지 않은 필드는 스킵 (또는 에러) - } - - $field = $fields->get($key); - $fieldError = $this->validateFieldValue($field, $value); - if ($fieldError) { - $errors[$key] = $fieldError; - } - } - - return $errors; - } - - /** - * 필드 타입별 값 검증 - */ - private function validateFieldValue(ItemField $field, mixed $value): ?string - { - return match($field->field_type) { - 'number' => $this->validateNumber($field, $value), - 'dropdown' => $this->validateDropdown($field, $value), - 'date' => $this->validateDate($field, $value), - 'checkbox' => $this->validateCheckbox($field, $value), - default => null - }; - } - - private function validateNumber(ItemField $field, mixed $value): ?string - { - if (!is_numeric($value)) { - return "{$field->field_name}은(는) 숫자여야 합니다."; - } - - $rules = $field->validation_rules ?? []; - if (isset($rules['min']) && $value < $rules['min']) { - return "{$field->field_name}은(는) {$rules['min']} 이상이어야 합니다."; - } - if (isset($rules['max']) && $value > $rules['max']) { - return "{$field->field_name}은(는) {$rules['max']} 이하여야 합니다."; - } - - return null; - } - - private function validateDropdown(ItemField $field, mixed $value): ?string - { - $options = $field->options ?? []; - $validValues = array_column($options, 'value'); - - if (!in_array($value, $validValues)) { - return "{$field->field_name}의 값이 유효하지 않습니다."; - } - - return null; - } -} -``` - -### 5.2 Controller에서 사용 - -```php -class ProductsController extends Controller -{ - public function store(ProductStoreRequest $request) - { - $validated = $request->validated(); - - // attributes 검증 (선택적) - if (isset($validated['attributes'])) { - $groupId = 1; // 품목-제품 그룹 - $errors = $this->fieldValidationService->validate( - $groupId, - $validated['attributes'] - ); - - if (!empty($errors)) { - return ApiResponse::error('검증 실패', $errors, 422); - } - } - - $product = $this->productService->create($validated); - - return ApiResponse::success($product, __('message.created')); - } -} -``` - ---- - -## 6. 프론트엔드 연동 - -### 6.1 동적 폼 렌더링 흐름 - -``` -1. 페이지 로드 시 - GET /api/v1/item-master/fields?group_id=1 - -2. 필드 정의 기반 폼 컴포넌트 렌더링 - field_type: textbox → - field_type: number → - field_type: dropdown →