docs: [projects] 조직도 관리 시스템 기술문서 추가

- projects/org-chart/README.md: 아키텍처, API, DB, 프론트엔드 상세
- index_projects.md: 조직도 프로젝트 등록
- INDEX.md: 조직도 문서 링크 추가
This commit is contained in:
김보곤
2026-03-06 20:34:06 +09:00
parent 6d042f5bfd
commit 5798058125
3 changed files with 598 additions and 1 deletions

View File

@@ -1,7 +1,7 @@
# SAM 프로젝트 문서 인덱스
> **Claude Code 작업 전 필수 확인** — 작업 유형에 맞는 문서를 먼저 읽고 시작하세요.
> **최종 갱신**: 2026-02-28
> **최종 갱신**: 2026-03-06
---
@@ -208,6 +208,7 @@ docs/
| **Legacy** | [draw-module.md](projects/legacy-5130/draw-module.md) | 레거시 드로우 모듈 |
| **견적** | [quotation/](projects/quotation/) | 견적 프로젝트 자료 |
| **전자서명** | [e-sign/](projects/e-sign/) | 전자서명 프로젝트 자료 |
| **조직도** | [org-chart/README.md](projects/org-chart/README.md) | 조직도 관리 (트리형, 드래그앤드롭, 숨기기) |
---
@@ -226,6 +227,7 @@ docs/
| 문서 | 설명 |
|------|------|
| [20260304_eaccount_infinite_loop_fix.md](changes/20260304_eaccount_infinite_loop_fix.md) | 계좌 입출금내역 부분 월 조회 시 무한루프 크래시 수정 |
| [20260306_purchase_request_payment_method.md](changes/20260306_purchase_request_payment_method.md) | 품의서 지급방법 UI 개선 (구매품의서 추가, 비용정산품의서 행별 변경) |
---
@@ -287,6 +289,7 @@ docs/
| **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) | 레거시 드로우 모듈 |
| **조직도** | [README.md](projects/org-chart/README.md) | 조직도 관리 (Alpine.js + SortableJS) |
### history/ - 히스토리

View File

@@ -0,0 +1,277 @@
# 프로젝트 문서 인덱스
> SAM 시스템 개발 프로젝트별 문서 모음
> **최종 업데이트**: 2026-03-06
---
## 프로젝트 현황 요약
| 프로젝트 | 상태 | 설명 |
|---------|------|------|
| [mes](#mes---meserp-프로젝트) | 🟡 진행중 | 차세대 MES/ERP 기능 개발 |
| [quotation](#quotation---견적-기능) | 🟢 Phase 3 완료 | 5130 견적 → SAM 이관 |
| [api-integration](#api-integration---react--api-연동) | 🟡 진행중 | React ↔ API 연동 |
| [5130-migration](#5130-migration---품목-마이그레이션) | 🟡 Phase 1 진행중 | 5130 품목 데이터 마이그레이션 |
| [legacy-5130](#legacy-5130---레거시-분석) | 📚 참조용 | 5130 레거시 모듈 분석 |
| [mng-mobile-responsive](#mng-mobile-responsive---모바일-반응형) | 🟡 진행중 | mng 모바일 반응형 개선 |
| [auto-login](#auto-login---자동-로그인) | ⚪ 대기 | 자동 로그인 기능 |
| [migration-5130-mng](#migration-5130-mng---5130--mng-마이그레이션) | 🟡 진행중 | 5130 → mng 통합 마이그레이션 |
| [e-sign](#e-sign---전자계약-서명) | 🟢 v1.0 구현 완료 | 전자계약 서명 솔루션 (SAM E-Sign) |
| [org-chart](#org-chart---조직도-관리) | 🟢 v1.0 구현 완료 | 트리형 조직도 관리 (드래그앤드롭, 숨기기) |
---
## 프로젝트 상세
### mes - MES/ERP 프로젝트
**경로**: `docs/projects/mes/`
**상태**: 🟡 Phase 0 (베이스라인 분석) 30% 완료
**목표**: SAM 시스템의 차세대 MES/ERP 기능 개발
**핵심 문서**:
- [README.md](./mes/README.md) - 프로젝트 개요 및 문서 안내
- [MES_PROGRESS_TRACKER.md](./mes/MES_PROGRESS_TRACKER.md) - 진행 상황 추적
- [MES_PROJECT_ROADMAP.md](./mes/MES_PROJECT_ROADMAP.md) - 전체 로드맵
**분석 결과**:
- `00_baseline/` - Phase 0 분석 결과
- [PHASE_0_FINAL_REPORT.md](./mes/00_baseline/PHASE_0_FINAL_REPORT.md)
- [BACKEND_DEVELOPMENT_ROADMAP_V2.md](./mes/00_baseline/BACKEND_DEVELOPMENT_ROADMAP_V2.md)
- `docs_breakdown/` - 문서 분석 (7개)
**v2 분석**:
- `v2-analysis/` - MES v2 화면 분석
- `quote-analysis/` - 견적 분석
- `order-analysis/` - 주문 분석
- `production-analysis/` - 생산 분석
- `customer-analysis/` - 거래처 분석
- `site-analysis/` - 현장 분석
- `price-analysis/` - 단가 분석
- `master-data-analysis/` - 기준정보 분석
- `production-userflow/` - 생산 유저플로우
---
### quotation - 견적 기능
**경로**: `docs/projects/quotation/`
**상태**: 🟢 Phase 3 완료 (2025-12-19)
**목표**: 5130 레거시 견적 기능을 SAM 시스템으로 이관
**핵심 문서**:
- [MASTER_PLAN.md](./quotation/MASTER_PLAN.md) - 마스터 플랜
- [PROGRESS.md](./quotation/PROGRESS.md) - 진행 현황
**Phase 문서**:
| Phase | 상태 | 경로 |
|-------|------|------|
| 1. 5130 분석 | ✅ 완료 | `phase-1-5130-analysis/` |
| 2. mng 분석 | ✅ 완료 | `phase-2-mng-analysis/` |
| 3. 구현 | ✅ 완료 | `phase-3-implementation/` |
| 4. API 개발 | ⚪ 대기 | `phase-4-api/` |
**참조 자료**:
- `screenshots/` - MES 프로토타입 화면 캡쳐 (7개)
---
### api-integration - React ↔ API 연동
**경로**: `docs/projects/api-integration/`
**상태**: 🟡 Phase 4 진행중
**목표**: React(dev.sam.kr)와 API(api.sam.kr) 완벽 연동
**핵심 문서**:
- [MASTER_PLAN.md](./api-integration/MASTER_PLAN.md) - 마스터 플랜
- [PROGRESS.md](./api-integration/PROGRESS.md) - 진행 현황
- [WORKFLOW.md](./api-integration/WORKFLOW.md) - 작업 프로세스
**Phase 문서**:
| Phase | 상태 | 경로 |
|-------|------|------|
| 1. 테이블 통합 | 🟢 완료(스킵) | `phase-1-table-migration/` |
| 2. 메뉴 추출 | 🟡 진행중 | `phase-2-menu-extraction/` |
| 3. API 매핑 | 🟡 진행중 | `phase-3-api-mapping/` |
| 4. 연동+검증 | 🟡 진행중 | `phase-4-integration/` |
**TC 파일**: `phase-4-integration/tc/` - 기능별 테스트 케이스 JSON (17개)
---
### 5130-migration - 품목 마이그레이션
**경로**: `docs/projects/5130-migration/`
**상태**: 🟡 Phase 1 진행중
**목표**: 5130 품목(부품, 자재, BOM) 데이터를 SAM DB로 이전
**핵심 문서**:
- [MASTER_PLAN.md](./5130-migration/MASTER_PLAN.md) - 마스터 플랜
- [PROGRESS.md](./5130-migration/PROGRESS.md) - 진행 현황
**Phase 문서**:
| Phase | 상태 | 경로 |
|-------|------|------|
| 1. 소스 분석 | 🟡 진행중 | `phase-1-source-analysis/` |
| 2. 타겟 분석 | ⚪ 대기 | `phase-2-target-analysis/` |
| 3. 매핑 설계 | ⚪ 대기 | `phase-3-mapping/` |
---
### legacy-5130 - 레거시 분석
**경로**: `docs/projects/legacy-5130/`
**상태**: 📚 참조용 문서
**용도**: 5130 레거시 시스템 모듈별 분석
**모듈별 분석 문서**:
| 문서 | 내용 |
|------|------|
| [00_OVERVIEW.md](./legacy-5130/00_OVERVIEW.md) | 시스템 개요 |
| [01_MATERIAL.md](./legacy-5130/01_MATERIAL.md) | 자재 관리 |
| [02_PRODUCT.md](./legacy-5130/02_PRODUCT.md) | 제품 관리 |
| [03_ESTIMATE.md](./legacy-5130/03_ESTIMATE.md) | 견적 관리 |
| [04_PRODUCTION.md](./legacy-5130/04_PRODUCTION.md) | 생산 관리 |
| [05_SHIPPING.md](./legacy-5130/05_SHIPPING.md) | 출하 관리 |
| [06_QUALITY.md](./legacy-5130/06_QUALITY.md) | 품질 관리 |
| [07_ACCOUNTING.md](./legacy-5130/07_ACCOUNTING.md) | 회계 관리 |
| [08_SAM_COMPARISON.md](./legacy-5130/08_SAM_COMPARISON.md) | SAM 비교 분석 |
| [draw-module.md](./legacy-5130/draw-module.md) | 도면 모듈 |
---
### mng-mobile-responsive - 모바일 반응형
**경로**: `docs/projects/mng-mobile-responsive/`
**상태**: 🟡 진행중
**목표**: mng 관리자 패널 모바일 반응형 개선
**문서**:
- [01-analysis.md](./mng-mobile-responsive/01-analysis.md) - 분석
- [02-implementation-plan.md](./mng-mobile-responsive/02-implementation-plan.md) - 구현 계획
- [06-excluded-menus.md](./mng-mobile-responsive/06-excluded-menus.md) - 제외 메뉴
- [PROGRESS.md](./mng-mobile-responsive/PROGRESS.md) - 진행 현황
---
### auto-login - 자동 로그인
**경로**: `docs/projects/auto-login/`
**상태**: ⚪ 대기
**목표**: 자동 로그인 기능 구현
**문서**:
- [PROGRESS.md](./auto-login/PROGRESS.md) - 진행 현황
---
### migration-5130-mng - 5130 → mng 마이그레이션
**경로**: `docs/projects/migration-5130-mng/`
**상태**: 🟡 진행중
**목표**: 5130 기능을 mng로 통합 마이그레이션
**문서**:
- [MIGRATION_TRACKER.md](./migration-5130-mng/MIGRATION_TRACKER.md) - 마이그레이션 추적
---
### e-sign - 전자계약 서명
**경로**: `docs/projects/e-sign/`
**상태**: 🟢 v1.0 구현 완료 (2026-02-12)
**목표**: 모두싸인과 유사한 간편 전자계약 서명 솔루션 자체 구축
**핵심 문서**:
- [technical-design.md](./e-sign/technical-design.md) - 기술 설계 문서
- [implementation-guide.md](./e-sign/implementation-guide.md) - 구현 가이드
**구현 범위**:
| 영역 | 수량 |
|------|------|
| DB 마이그레이션 | 4개 (esign_contracts, esign_signers, esign_sign_fields, esign_audit_logs) |
| API 모델 | 4개 |
| API 서비스 | 4개 |
| API 컨트롤러 | 2개 (16 엔드포인트) |
| MNG 컨트롤러 | 2개 (8 화면) |
| MNG 뷰 | 8개 (React 하이브리드) |
**기술 스택**: Laravel 11 + React 18 + SignaturePad + PDF.js
**참고 자료**:
- `esign-storyboard.pptx` - 화면 스토리보드
- `storyboard-config.json` - 스토리보드 설정
---
### org-chart - 조직도 관리
**경로**: `docs/projects/org-chart/`
**상태**: 🟢 v1.0 구현 완료 (2026-03-06)
**목표**: 테넌트별 조직 구조를 시각적으로 관리하는 트리형 조직도
**핵심 문서**:
- [README.md](./org-chart/README.md) - 기술 문서 (아키텍처, API, DB, 프론트엔드 상세)
**구현 범위**:
| 영역 | 수량 |
|------|------|
| MNG 컨트롤러 메서드 | 7개 (RdController) |
| API 엔드포인트 | 6개 (조회, 배치, 해제, 순서변경, 숨기기) |
| DB 마이그레이션 | 1개 (departments.options JSON 추가) |
| 뷰 | 1개 (Alpine.js + SortableJS) |
**기술 스택**: Alpine.js + SortableJS + 수동 DOM 렌더링 (x-for 미사용)
---
## 디렉토리 구조
```
docs/projects/
├── INDEX.md # 이 파일
├── mes/ # MES/ERP 프로젝트 (핵심)
│ ├── 00_baseline/ # Phase 0 분석
│ ├── v1-analysis/ # v1 분석
│ ├── v2-analysis/ # v2 화면 분석
│ └── phases/ # Phase별 진행
├── quotation/ # 견적 기능
│ ├── phase-1-5130-analysis/
│ ├── phase-2-mng-analysis/
│ ├── phase-3-implementation/
│ └── screenshots/
├── api-integration/ # React ↔ API 연동
│ ├── phase-1-table-migration/
│ ├── phase-2-menu-extraction/
│ ├── phase-3-api-mapping/
│ └── phase-4-integration/tc/
├── 5130-migration/ # 품목 마이그레이션
│ ├── phase-1-source-analysis/
│ ├── phase-2-target-analysis/
│ └── phase-3-mapping/
├── legacy-5130/ # 레거시 분석 (참조용)
├── mng-mobile-responsive/ # 모바일 반응형
├── auto-login/ # 자동 로그인
├── migration-5130-mng/ # 5130→mng 마이그레이션
├── e-sign/ # 전자계약 서명 (SAM E-Sign)
└── org-chart/ # 조직도 관리
```
---
## 관련 문서
- [docs/INDEX.md](../INDEX.md) - 전체 문서 인덱스
- [docs/plans/index_plans.md](../plans/index_plans.md) - 기획 문서 인덱스
- [docs/guides/PROJECT_DEVELOPMENT_POLICY.md](../guides/PROJECT_DEVELOPMENT_POLICY.md) - 공통 개발 정책
- [CURRENT_WORKS.md](../../CURRENT_WORKS.md) - 현재 작업
---
**범례**:
- 🟢 완료
- 🟡 진행중
- ⚪ 대기
- 📚 참조용

View File

@@ -0,0 +1,317 @@
# 조직도 관리 시스템
> **작성일**: 2026-03-06
> **상태**: 🟢 v1.0 구현 완료
> **프로젝트**: MNG 전용 (Blade + Alpine.js + SortableJS)
---
## 1. 개요
### 1.1 목적
테넌트별 조직 구조를 시각적으로 관리하는 트리형 조직도 시스템.
부서 계층 구조와 직원 배치를 드래그 앤 드롭으로 관리한다.
### 1.2 주요 기능
| 기능 | 설명 |
|------|------|
| 트리형 조직도 | 회사 → 부서 → 하위부서 (무한 depth) 계층 표시 |
| 직원 배치 | 드래그 앤 드롭으로 직원을 부서에 배치/해제 |
| 부서 순서 변경 | 같은 레벨 내 부서 순서 드래그로 변경 |
| 부서 계층 이동 | 부서를 다른 부서 아래로 드래그하여 parent 변경 |
| 부서 숨기기 | 더블클릭 → 숨기기 버튼 → DB 저장 (영구) |
| 임원 필터링 | 대표이사/사장 등은 미배치 목록에서 제외 |
---
## 2. 기술 스택
| 구분 | 기술 |
|------|------|
| 백엔드 | Laravel (MNG 프로젝트) |
| 프론트엔드 | Alpine.js + 수동 DOM 렌더링 |
| 드래그 앤 드롭 | SortableJS |
| 스타일 | Tailwind CSS + inline style |
| 데이터 저장 | MySQL `departments`, `employees` 테이블 |
---
## 3. 아키텍처
### 3.1 렌더링 방식
> **핵심**: Alpine.js `x-for` 대신 수동 `innerHTML` 렌더링을 사용한다.
SortableJS와 Alpine.js `x-for` 템플릿이 동시에 DOM을 조작하면 **이중 업데이트 버그**가 발생한다.
이를 해결하기 위해 부서 트리는 JavaScript로 HTML 문자열을 생성하고 `innerHTML`로 삽입한다.
```
Alpine.js 데이터 변경
renderTree() 호출
기존 SortableJS 인스턴스 destroy
buildChildrenHtml(null, 0) → 재귀적 HTML 생성
$refs.deptTree.innerHTML = html
$nextTick → initDeptSortables() + initEmpSortables()
```
### 3.2 이벤트 처리
수동 렌더링된 HTML에는 Alpine 디렉티브가 없으므로 **이벤트 위임(Event Delegation)** 패턴을 사용한다.
```
루트 div @click="handleClick($event)"
@dblclick="handleDblClick($event)"
e.target.closest('[data-action]') 으로 액션 식별
data-action 값에 따라 분기:
- "unassign" → 직원 미배치
- "hide-dept" → 부서 숨기기
- "restore-dept" → 부서 복원
- "dept-dblclick" → 더블클릭 시 숨기기 버튼 토글
```
### 3.3 순환 참조 방지
부서를 자신의 하위로 드래그하면 무한 루프가 발생한다.
`isDescendant(ancestorId, targetId)` 재귀 함수로 이를 차단한다.
```javascript
// 드래그 대상(dragId)의 자손인 곳으로는 이동 불가
onMove: (evt) => {
const dragId = parseInt(evt.dragged.dataset.deptId);
const toPid = evt.to.dataset.parentId ? parseInt(evt.to.dataset.parentId) : null;
if (toPid === dragId || this.isDescendant(dragId, toPid)) return false;
}
```
---
## 4. 파일 구조
### 4.1 MNG 프로젝트
| 파일 | 역할 |
|------|------|
| `app/Http/Controllers/RdController.php` | 컨트롤러 (7개 메서드) |
| `app/Models/Tenants/Department.php` | 부서 모델 (`options` JSON cast) |
| `resources/views/rd/org-chart.blade.php` | 뷰 (Alpine.js + SortableJS) |
| `routes/web.php` | 라우트 (6개 엔드포인트) |
### 4.2 API 프로젝트
| 파일 | 역할 |
|------|------|
| `database/migrations/2026_03_06_201500_add_options_to_departments_table.php` | `options` JSON 컬럼 추가 |
---
## 5. API 엔드포인트
> 모든 엔드포인트는 `rd.` 네임 프리픽스 하위에 위치한다.
| Method | Route | 컨트롤러 메서드 | 설명 |
|--------|-------|---------------|------|
| GET | `/rd/org-chart` | `orgChart` | 조직도 페이지 |
| POST | `/rd/org-chart/assign` | `orgChartAssign` | 직원 부서 배치 |
| POST | `/rd/org-chart/unassign` | `orgChartUnassign` | 직원 부서 해제 |
| POST | `/rd/org-chart/reorder` | `orgChartReorder` | 직원 일괄 이동 |
| POST | `/rd/org-chart/reorder-depts` | `orgChartReorderDepts` | 부서 순서/계층 변경 |
| POST | `/rd/org-chart/toggle-hide` | `orgChartToggleHide` | 부서 숨기기/표시 토글 |
### 5.1 요청/응답 형식
**부서 배치** (`POST /rd/org-chart/assign`):
```json
{ "employee_id": 1, "department_id": 5 }
{ "success": true }
```
**부서 순서 변경** (`POST /rd/org-chart/reorder-depts`):
```json
{
"orders": [
{ "id": 1, "parent_id": null, "sort_order": 1 },
{ "id": 2, "parent_id": null, "sort_order": 2 },
{ "id": 3, "parent_id": 1, "sort_order": 1 }
]
}
{ "success": true }
```
**부서 숨기기** (`POST /rd/org-chart/toggle-hide`):
```json
{ "department_id": 5, "hidden": true }
{ "success": true }
```
---
## 6. DB 구조
### 6.1 departments 테이블 (관련 컬럼)
| 컬럼 | 타입 | 설명 |
|------|------|------|
| `id` | int | PK |
| `tenant_id` | int | 테넌트 FK |
| `parent_id` | int (nullable) | 상위 부서 (null = 최상위) |
| `name` | varchar | 부서명 |
| `code` | varchar | 부서 코드 |
| `is_active` | bool | 활성 여부 |
| `sort_order` | int | 정렬 순서 |
| `options` | json (nullable) | 확장 속성 |
**`options` 키**:
| 키 | 타입 | 설명 |
|----|------|------|
| `orgchart_hidden` | boolean | 조직도에서 숨김 여부 |
### 6.2 employees 테이블 (관련 컬럼)
| 컬럼 | 타입 | 설명 |
|------|------|------|
| `id` | int | PK |
| `tenant_id` | int | 테넌트 FK |
| `department_id` | int (nullable) | 소속 부서 (null = 미배치) |
| `display_name` | varchar | 표시 이름 |
| `position_label` | varchar | 직책/직급 |
| `employee_status` | enum | `active`, `leave`, `resigned` |
---
## 7. 프론트엔드 구현 상세
### 7.1 Alpine.js 컴포넌트 (`orgChart()`)
**데이터**:
| 속성 | 타입 | 설명 |
|------|------|------|
| `departments` | Array | 전체 부서 목록 (서버에서 전달) |
| `employees` | Array | 전체 직원 목록 (서버에서 전달) |
| `hiddenDepts` | Set | 숨긴 부서 ID (DB에서 초기화) |
| `dblClickDept` | int/null | 더블클릭된 부서 ID (숨기기 버튼 표시용) |
| `execTitles` | Array | 임원 직책 목록 (`['대표이사', '사장', '부사장', '회장', '부회장']`) |
**핵심 메서드**:
| 메서드 | 설명 |
|--------|------|
| `renderTree()` | SortableJS 파괴 → HTML 재생성 → SortableJS 재초기화 |
| `buildChildrenHtml(parentId, level)` | 재귀적 자식 부서 HTML 생성 |
| `buildNodeHtml(dept, level)` | 단일 부서 카드 HTML (level별 스타일 차등) |
| `buildEmpHtml(emp, isLarge)` | 직원 카드 HTML |
| `isDeptHidden(deptId)` | 부서 또는 상위 부서가 숨김인지 재귀 체크 |
| `isDescendant(ancestorId, targetId)` | 순환 참조 방지 |
| `isExecutive(emp)` | 임원 여부 판별 |
### 7.2 SortableJS 그룹
| 그룹 | 대상 | 핸들 | 기능 |
|------|------|------|------|
| `departments` | `.org-children`, `.org-drop-target` | `.dept-drag-handle` | 부서 순서/계층 변경 |
| `employees` | `.emp-zone`, `#unassigned-zone` | (전체) | 직원 배치/해제 |
### 7.3 CSS 연결선
부서 간 연결선은 CSS `::before`/`::after` 의사 요소로 구현한다.
```
부모 노드
│ (vertical: div 1px × 24px)
┌───────┼───────┐ (horizontal: ::before + ::after)
│ │ │ (vertical: div 1px × 24px)
자식1 자식2 자식3
```
| 선택자 | 역할 |
|--------|------|
| `.org-node-wrap` 내부 div (1px × 24px) | 세로 연결선 |
| `.org-node-wrap:not(:first-child)::before` | 왼쪽 가로선 (left:0 ~ right:50%) |
| `.org-node-wrap:not(:last-child)::after` | 오른쪽 가로선 (left:50% ~ right:0) |
| `:only-child` | 단일 자식이면 가로선 숨김 |
### 7.4 부서 숨기기 UX 흐름
```
① 부서 헤더 더블클릭
② dblClickDept = dept.id → renderTree()
③ 헤더에 빨간 "숨기기" 버튼 표시
④ "숨기기" 클릭
⑤ hiddenDepts.add(id) → renderTree() → POST /toggle-hide (DB 저장)
⑥ 해당 부서 + 하위 부서가 트리에서 제거
⑦ "숨겨진 부서" 패널에 표시
⑧ 패널에서 👁 아이콘 클릭 → hiddenDepts.delete(id) → POST /toggle-hide
```
### 7.5 부서 레벨별 스타일
| Level | 색상 테마 | 너비 | 아이콘 |
|-------|---------|------|--------|
| 0 (최상위) | 보라 (`#7C3AED`) | 200px | `ri-building-2-line` |
| 1 (중간) | 인디고 (`#6366F1`) | 180px | `ri-git-branch-line` |
| 2+ (하위) | 회색 (`#6B7280`) | 160px | `ri-subtract-line` |
---
## 8. 비즈니스 규칙
### 8.1 임원 필터링
미배치 직원 목록에서 다음 조건에 해당하면 제외:
- `position_label``['대표이사', '사장', '부사장', '회장', '부회장']` 중 하나
- `display_name`이 테넌트의 `ceo_name`과 일치
> 이유: 조직도 최상단에 "대표이사 OOO"이 이미 표시되므로 중복 방지
### 8.2 부서 숨기기
- `departments.options` JSON의 `orgchart_hidden` 키로 저장
- 숨긴 부서의 **하위 부서도 자동으로 숨겨짐** (`isDeptHidden` 재귀 체크)
- 숨겨진 부서 패널에는 **직접 숨긴 부서만** 표시 (자식은 부모 복원 시 같이 복원)
- 숨기기는 **조직도 표시 전용**`is_active`와 무관하며, 부서 데이터에 영향 없음
### 8.3 직원 표시 형식
- 직책이 있으면: `{직책} {이름}` (예: "과장 전진선")
- 직책이 없으면: `{이름}` (예: "김보곤")
---
## 9. 개발 이력
| 날짜 | 커밋 | 내용 |
|------|------|------|
| 2026-03-06 | `a12ee886` | CSS 연결선 수정 + 빈 드롭 타겟 숨김 |
| 2026-03-06 | `9fd72e49` | 부서 숨기기 기능 추가 (프론트 전용) |
| 2026-03-06 | `8c8fd5f6` | 대표이사 미배치 제외 + 숨긴 부서 연결선 제거 |
| 2026-03-06 | `81157a15` | 부서 숨기기 상태 DB 저장 (`options.orgchart_hidden`) |
---
## 관련 문서
- [rules/department-tree-api.md](../../rules/department-tree-api.md) — 부서 트리 API 규칙
- [rules/employee-api.md](../../rules/employee-api.md) — 직원 API 규칙
- [system/database/hr.md](../../system/database/hr.md) — HR 테이블 스키마
- [standards/options-column-policy.md](../../standards/options-column-policy.md) — options JSON 컬럼 정책
---
**최종 업데이트**: 2026-03-06