# Phase 2: 시스템 설정

**기간:** 1주
**우선순위:** 높음 (Phase 3-6의 선행 조건)
**의존성:** Phase 1 (회원관리, 테넌트관리)

## 📋 Phase 개요

다른 기능들이 참조하는 공통 설정 기능을 구축합니다.

**포함 기능:**
1. 설정 - 카테고리 관리
2. 설정 - 관리자 계정 관리

---

## 1️⃣ 설정 - 카테고리 관리

### 기능 목록

#### 1.1 카테고리 목록 조회
- **경로:** `/mng/settings/categories`
- **기능:**
  - 계층 구조 트리 뷰
  - 타입별 필터 (제품, 게시판, 파일 등)
  - 드래그 앤 드롭 정렬 (순서 변경)
  - 검색 (카테고리명)
- **권한:** `settings.categories.index`

#### 1.2 카테고리 생성
- **경로:** `/mng/settings/categories/create`
- **기능:**
  - 카테고리명 입력 (다국어 지원)
  - 타입 선택 (product, board, file, custom)
  - 부모 카테고리 선택 (계층 구조)
  - 정렬 순서 설정
  - 활성/비활성
- **권한:** `settings.categories.create`

#### 1.3 카테고리 수정
- **경로:** `/mng/settings/categories/{id}/edit`
- **기능:**
  - 기본 정보 수정
  - 부모 카테고리 변경
  - 정렬 순서 변경
- **권한:** `settings.categories.update`

#### 1.4 카테고리 삭제
- **경로:** `/mng/settings/categories/{id}`
- **기능:**
  - 하위 카테고리 확인 (있으면 삭제 불가)
  - 사용 중인 항목 확인 (제품, 게시물 등)
  - Soft Delete
- **권한:** `settings.categories.delete`

### DB 스키마

```sql
CREATE TABLE categories (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    tenant_id BIGINT UNSIGNED NOT NULL COMMENT '소속 테넌트',
    parent_id BIGINT UNSIGNED NULL COMMENT '부모 카테고리 ID',
    type ENUM('product', 'board', 'file', 'custom') DEFAULT 'custom' COMMENT '카테고리 타입',
    name VARCHAR(255) NOT NULL COMMENT '카테고리명',
    slug VARCHAR(255) NOT NULL COMMENT 'URL 슬러그',
    description TEXT NULL COMMENT '설명',
    sort_order INT DEFAULT 0 COMMENT '정렬 순서',
    is_active BOOLEAN DEFAULT TRUE COMMENT '활성 여부',
    meta_data JSON NULL COMMENT '추가 메타데이터',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP NULL,

    INDEX idx_tenant_id (tenant_id),
    INDEX idx_parent_id (parent_id),
    INDEX idx_type (type),
    INDEX idx_slug (slug),
    INDEX idx_sort_order (sort_order),
    FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
    FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

### API 엔드포인트

| Method | Endpoint | Description | FormRequest |
|--------|----------|-------------|-------------|
| GET | `/mng/settings/categories` | 카테고리 목록 (트리 구조) | - |
| GET | `/mng/settings/categories/create` | 카테고리 생성 폼 | - |
| POST | `/mng/settings/categories` | 카테고리 생성 | `StoreCategoryRequest` |
| GET | `/mng/settings/categories/{id}/edit` | 카테고리 수정 폼 | - |
| PUT | `/mng/settings/categories/{id}` | 카테고리 수정 | `UpdateCategoryRequest` |
| DELETE | `/mng/settings/categories/{id}` | 카테고리 삭제 | - |
| POST | `/mng/settings/categories/reorder` | 드래그앤드롭 정렬 | `ReorderCategoryRequest` |

### Service 클래스

```php
// app/Services/CategoryService.php
class CategoryService
{
    public function getTree(string $type = null): Collection;
    public function list(array $filters): Collection;
    public function find(int $id): Category;
    public function create(array $data): Category;
    public function update(Category $category, array $data): Category;
    public function delete(Category $category): bool;
    public function reorder(array $order): bool;
    public function getDescendants(Category $category): Collection;
    public function canDelete(Category $category): bool; // 하위/사용 확인
}
```

### UI/UX 와이어프레임 (텍스트)

```
┌─────────────────────────────────────────────────────────┐
│ 카테고리 관리                              [+ 새 카테고리]│
├─────────────────────────────────────────────────────────┤
│ [타입: 전체 ▼] [검색: 카테고리명] [검색]                 │
├─────────────────────────────────────────────────────────┤
│ ▼ 제품 카테고리 (Product)                 [수정][삭제]  │
│   ├─ ▶ 전자제품                           [수정][삭제]  │
│   ├─ ▼ 의류                               [수정][삭제]  │
│   │   ├─ 상의                             [수정][삭제]  │
│   │   └─ 하의                             [수정][삭제]  │
│   └─ ▶ 식품                               [수정][삭제]  │
│                                                         │
│ ▼ 게시판 카테고리 (Board)                 [수정][삭제]  │
│   ├─ 공지사항                             [수정][삭제]  │
│   ├─ FAQ                                  [수정][삭제]  │
│   └─ 자료실                               [수정][삭제]  │
└─────────────────────────────────────────────────────────┘

* 드래그 앤 드롭으로 순서 변경 가능 (Alpine.js + Sortable.js)
```

### 개발 체크리스트

- [ ] `Category` 모델 작성 (BelongsToTenant, 계층 구조)
- [ ] `CategoryService` 클래스 작성
- [ ] FormRequest 작성 (중복 체크, 순환 참조 방지)
- [ ] `CategoryController` 작성
- [ ] Blade 템플릿 작성 (트리 뷰, 재귀 렌더링)
- [ ] Alpine.js + Sortable.js 드래그앤드롭 구현
- [ ] 계층 구조 재귀 쿼리 최적화 (Nested Set 또는 Closure Table)
- [ ] 삭제 전 사용 여부 체크 로직
- [ ] i18n 키 작성
- [ ] 테스트 작성 (계층 구조, 정렬)

---

## 2️⃣ 설정 - 관리자 계정 관리

### 기능 목록

#### 2.1 관리자 목록 조회
- **경로:** `/mng/settings/admins`
- **기능:**
  - 슈퍼관리자 목록 (일반 회원과 구분)
  - 검색 (이름, 이메일)
  - 필터 (활성/비활성, 권한 레벨)
  - 정렬 (생성일, 이름)
- **권한:** `settings.admins.index` (슈퍼관리자만)

#### 2.2 관리자 생성
- **경로:** `/mng/settings/admins/create`
- **기능:**
  - 기본 정보 입력
  - 권한 레벨 선택 (super_admin, admin)
  - 관리 범위 설정 (전체 테넌트 or 특정 테넌트)
- **권한:** `settings.admins.create`

#### 2.3 관리자 수정
- **경로:** `/mng/settings/admins/{id}/edit`
- **기능:**
  - 기본 정보 수정
  - 권한 레벨 변경
  - 활성/비활성 전환
- **권한:** `settings.admins.update`

#### 2.4 관리자 삭제
- **경로:** `/mng/settings/admins/{id}`
- **기능:**
  - Soft Delete
  - 본인 계정 삭제 방지
  - 최소 1명 슈퍼관리자 유지 체크
- **권한:** `settings.admins.delete`

### DB 스키마

```sql
-- users 테이블 확장 (추가 컬럼)
ALTER TABLE users ADD COLUMN is_super_admin BOOLEAN DEFAULT FALSE COMMENT '슈퍼관리자 여부';
ALTER TABLE users ADD COLUMN admin_level ENUM('user', 'admin', 'super_admin') DEFAULT 'user' COMMENT '관리자 레벨';
ALTER TABLE users ADD COLUMN accessible_tenants JSON NULL COMMENT '접근 가능한 테넌트 ID 목록 (super_admin은 전체)';

-- 또는 별도 테이블 생성 (선택적)
CREATE TABLE admins (
    id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT UNSIGNED UNIQUE NOT NULL COMMENT '사용자 ID',
    admin_level ENUM('admin', 'super_admin') DEFAULT 'admin' COMMENT '관리자 레벨',
    accessible_tenants JSON NULL COMMENT '접근 가능한 테넌트 (null = 전체)',
    permissions JSON NULL COMMENT '추가 권한',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

**권장 방식:** `users` 테이블에 `is_super_admin`, `admin_level` 컬럼 추가 (간결함)

### API 엔드포인트

| Method | Endpoint | Description | FormRequest |
|--------|----------|-------------|-------------|
| GET | `/mng/settings/admins` | 관리자 목록 | - |
| GET | `/mng/settings/admins/create` | 관리자 생성 폼 | - |
| POST | `/mng/settings/admins` | 관리자 생성 | `StoreAdminRequest` |
| GET | `/mng/settings/admins/{id}/edit` | 관리자 수정 폼 | - |
| PUT | `/mng/settings/admins/{id}` | 관리자 수정 | `UpdateAdminRequest` |
| DELETE | `/mng/settings/admins/{id}` | 관리자 삭제 | - |

### Service 클래스

```php
// app/Services/AdminService.php
class AdminService
{
    public function list(array $filters): LengthAwarePaginator;
    public function find(int $id): User;
    public function create(array $data): User;
    public function update(User $admin, array $data): User;
    public function delete(User $admin): bool;
    public function grantSuperAdmin(User $user): bool;
    public function revokeSuperAdmin(User $user): bool;
    public function canDelete(User $admin): bool; // 최소 1명 체크
}
```

### 개발 체크리스트

- [ ] `users` 테이블 마이그레이션 (컬럼 추가)
- [ ] `User` 모델에 `isSuperAdmin()`, `isAdmin()` 메서드 추가
- [ ] `AdminService` 클래스 작성
- [ ] FormRequest 작성 (본인 삭제 방지, 최소 1명 체크)
- [ ] `AdminController` 작성
- [ ] Blade 템플릿 작성
- [ ] 미들웨어 작성 (`EnsureSuperAdmin`)
- [ ] 권한 체크 로직 구현
- [ ] i18n 키 작성
- [ ] 테스트 작성

---

## 🎯 Phase 2 완료 조건

### 기능 완성도
- [ ] 카테고리 계층 구조 완벽 동작
- [ ] 드래그앤드롭 정렬 기능 동작
- [ ] 관리자 계정 생성/수정/삭제 동작
- [ ] 슈퍼관리자 권한 체크 정상 작동

### 코드 품질
- [ ] Service-First 패턴 준수
- [ ] FormRequest 검증 구현
- [ ] BelongsToTenant trait 적용 (Category)
- [ ] i18n 키 사용
- [ ] Pint 포맷팅 통과
- [ ] PHPStan Level 5+ 통과

### 데이터 무결성
- [ ] 카테고리 순환 참조 방지
- [ ] 하위 카테고리 있을 때 삭제 방지
- [ ] 최소 1명 슈퍼관리자 유지
- [ ] Soft Delete 동작 확인

### 테스트
- [ ] CategoryService 유닛 테스트
- [ ] AdminService 유닛 테스트
- [ ] 계층 구조 재귀 테스트
- [ ] 권한 체크 테스트

---

## 📚 다음 단계 (Phase 3)

Phase 2가 완료되면 **Phase 3: 비즈니스 핵심 기능**으로 진행합니다.

**Phase 3 포함 기능:**
- 영업관리 (Sales Management)
- 견적서관리 (Quotation Management)
- 전자결재관리 (Approval Management)

---

**최종 업데이트:** 2025-11-21
**작성자:** Claude Code
**버전:** 1.0.0