# 더미 데이터 시딩 계획

> **작성일**: 2025-12-23
> **목적**: React API 연동 테스트를 위한 더미 데이터 생성
> **참고 문서**: `react-mock-to-api-migration-plan.md`

---

## 1. 현황 분석

### 1.1 기존 데이터 현황

| 테이블 | 현재 개수 | 추가 목표 | 최종 목표 |
|--------|----------|----------|----------|
| tenants | 5 | - | 기존 활용 |
| users | 13 | - | 기존 활용 |
| clients | 4 (tenant 287) | +20 | 24개 |
| client_groups | 0 | +5 | 5개 |
| bank_accounts | 0 | +5 | 5개 |
| sales | 0 (tenant 287) | +80 | 80개 |
| purchases | 0 | +70 | 70개 |
| deposits | 0 | +60 | 60개 |
| withdrawals | 0 | +60 | 60개 |
| bills | 0 | +30 | 30개 |
| bill_installments | 0 | +15 | 15개 |
| **총계** | - | **~345개** | - |

### 1.2 대상 테넌트

**Target: ID 287 (프론트_테스트회사)**
- Code: `JTKKPNNG6D`
- 기존 거래처 4개 보유 (ID: 9, 10, 11, 12)
- 테스트 목적으로 적합

### 1.3 데이터 기간

**2025년 1월 ~ 12월 (1년간)**
- 월별 균등 분포
- 최근월(11~12월)은 draft 상태 포함

---

## 2. 테이블 의존성 분석

### 2.1 의존성 다이어그램

```
┌─────────────────────────────────────────────────────────────────┐
│  Level 0: 기반 데이터 (이미 존재)                                 │
├─────────────────────────────────────────────────────────────────┤
│  tenants (ID: 287) ──┬── users (ID: 1)                          │
│                      │                                          │
└──────────────────────┼──────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│  Level 1: 마스터 데이터 (5 + 5 = 10개)                           │
├─────────────────────────────────────────────────────────────────┤
│  ├── client_groups (5개) - 거래처 그룹                           │
│  └── bank_accounts (5개) - 은행 계좌                             │
└─────────────────────────────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│  Level 2: 거래처 데이터 (20개)                                   │
├─────────────────────────────────────────────────────────────────┤
│  clients (20개) ← client_group_id (optional)                    │
└─────────────────────────────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│  Level 3: 입출금/어음 데이터 (60 + 60 + 30 = 150개)              │
├─────────────────────────────────────────────────────────────────┤
│  ├── deposits (60개) ← client_id, bank_account_id               │
│  ├── withdrawals (60개) ← client_id, bank_account_id            │
│  └── bills (30개) ← client_id, bank_account_id                  │
│      └── bill_installments (15개) ← bill_id                     │
└─────────────────────────────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────┐
│  Level 4: 매출/매입 데이터 (80 + 70 = 150개)                     │
├─────────────────────────────────────────────────────────────────┤
│  ├── sales (80개) ← client_id, deposit_id (optional)            │
│  └── purchases (70개) ← client_id, withdrawal_id (optional)     │
└─────────────────────────────────────────────────────────────────┘
```

### 2.2 삽입 순서 및 수량

```
1. client_groups     (5개)   - 거래처 그룹
2. bank_accounts     (5개)   - 은행 계좌
3. clients           (20개)  - 거래처 (매출처/매입처)
4. deposits          (60개)  - 입금 (월 5건)
5. withdrawals       (60개)  - 출금 (월 5건)
6. bills             (30개)  - 어음 (수취 15건 + 발행 15건)
7. sales             (80개)  - 매출 (월 6~7건)
8. purchases         (70개)  - 매입 (월 5~6건)
────────────────────────────
총계                 ~345개
```

---

## 3. 더미 데이터 스키마

### 3.1 client_groups (거래처 그룹) - 5개

```php
[
    ['group_code' => 'VIP',    'group_name' => 'VIP 고객',      'price_rate' => 0.95],
    ['group_code' => 'GOLD',   'group_name' => '골드 고객',     'price_rate' => 0.97],
    ['group_code' => 'SILVER', 'group_name' => '실버 고객',     'price_rate' => 0.98],
    ['group_code' => 'NORMAL', 'group_name' => '일반 고객',     'price_rate' => 1.00],
    ['group_code' => 'NEW',    'group_name' => '신규 고객',     'price_rate' => 1.00],
]
```

### 3.2 bank_accounts (은행 계좌) - 5개

```php
[
    ['bank_code' => '004', 'bank_name' => 'KB국민은행',  'account_number' => '123-45-6789012',  'account_holder' => '프론트테스트', 'account_name' => '운영계좌', 'is_primary' => true],
    ['bank_code' => '088', 'bank_name' => '신한은행',    'account_number' => '110-123-456789',  'account_holder' => '프론트테스트', 'account_name' => '급여계좌', 'is_primary' => false],
    ['bank_code' => '020', 'bank_name' => '우리은행',    'account_number' => '1002-123-456789', 'account_holder' => '프론트테스트', 'account_name' => '예비계좌', 'is_primary' => false],
    ['bank_code' => '081', 'bank_name' => '하나은행',    'account_number' => '123-456789-12345','account_holder' => '프론트테스트', 'account_name' => '법인카드', 'is_primary' => false],
    ['bank_code' => '011', 'bank_name' => 'NH농협은행',  'account_number' => '351-1234-5678-12','account_holder' => '프론트테스트', 'account_name' => '비상금',   'is_primary' => false],
]
```

### 3.3 clients (거래처) - 20개

#### 매출처 (SALES) - 10개
| Code | 회사명 | 사업자번호 | 그룹 | 담당자 |
|------|--------|-----------|------|--------|
| S001 | 삼성전자 | 124-81-00998 | VIP | 김철수 |
| S002 | LG전자 | 107-86-14075 | VIP | 이영희 |
| S003 | SK하이닉스 | 204-81-17169 | GOLD | 박민수 |
| S004 | 현대자동차 | 101-81-05765 | GOLD | 정은지 |
| S005 | 네이버 | 220-81-62517 | GOLD | 최준호 |
| S006 | 카카오 | 120-87-65763 | SILVER | 강미래 |
| S007 | 쿠팡 | 120-88-00767 | SILVER | 임도현 |
| S008 | 토스 | 120-87-83139 | NORMAL | 윤서연 |
| S009 | 배달의민족 | 220-87-93847 | NORMAL | 한지민 |
| S010 | 당근마켓 | 815-87-01234 | NEW | 오태양 |

#### 매입처 (PURCHASE) - 7개
| Code | 회사명 | 사업자번호 | 그룹 | 담당자 |
|------|--------|-----------|------|--------|
| P001 | 한화솔루션 | 138-81-00610 | - | 김재원 |
| P002 | 포스코 | 506-81-08754 | - | 이현석 |
| P003 | 롯데케미칼 | 301-81-07123 | - | 박서준 |
| P004 | GS칼텍스 | 104-81-23858 | - | 정해인 |
| P005 | 대한항공 | 110-81-14794 | - | 송민호 |
| P006 | 현대제철 | 130-81-12345 | - | 강동원 |
| P007 | SK이노베이션 | 110-81-67890 | - | 유재석 |

#### 매출매입처 (BOTH) - 3개
| Code | 회사명 | 사업자번호 | 그룹 | 담당자 |
|------|--------|-----------|------|--------|
| B001 | 두산에너빌리티 | 124-81-08628 | GOLD | 조인성 |
| B002 | CJ대한통운 | 104-81-39849 | SILVER | 공유 |
| B003 | 삼성SDS | 124-81-34567 | VIP | 이정재 |

### 3.4 월별 데이터 분포

| 월 | 입금 | 출금 | 매출 | 매입 | 상태 |
|----|------|------|------|------|------|
| 1월 | 5건 | 5건 | 6건 | 5건 | confirmed/invoiced |
| 2월 | 5건 | 5건 | 6건 | 5건 | confirmed/invoiced |
| 3월 | 5건 | 5건 | 7건 | 6건 | confirmed/invoiced |
| 4월 | 5건 | 5건 | 6건 | 5건 | confirmed/invoiced |
| 5월 | 5건 | 5건 | 7건 | 6건 | confirmed/invoiced |
| 6월 | 5건 | 5건 | 6건 | 6건 | confirmed/invoiced |
| 7월 | 5건 | 5건 | 7건 | 6건 | confirmed/invoiced |
| 8월 | 5건 | 5건 | 6건 | 6건 | confirmed/invoiced |
| 9월 | 5건 | 5건 | 7건 | 6건 | confirmed/invoiced |
| 10월 | 5건 | 5건 | 7건 | 6건 | confirmed/invoiced |
| 11월 | 5건 | 5건 | 8건 | 7건 | confirmed + draft |
| 12월 | 5건 | 5건 | 7건 | 6건 | draft 위주 |
| **합계** | **60건** | **60건** | **80건** | **70건** | |

### 3.5 금액 범위 및 분포

```
┌─────────────────────────────────────────────────────────────────┐
│  금액 분포 (공급가액 기준)                                        │
├─────────────────────────────────────────────────────────────────┤
│  소액 (30%):    1,000,000 ~ 5,000,000원                         │
│  중액 (50%):    5,000,000 ~ 30,000,000원                        │
│  대액 (20%):   30,000,000 ~ 100,000,000원                       │
├─────────────────────────────────────────────────────────────────┤
│  세액: 공급가액 × 10%                                            │
│  합계: 공급가액 × 110%                                           │
└─────────────────────────────────────────────────────────────────┘
```

### 3.6 deposits (입금) - 60개 예시

```php
// 월별 5건씩, 총 60건
// 결제수단: transfer(70%), card(15%), cash(10%), check(5%)

$deposits = [
    // 1월
    ['date' => '2025-01-05', 'client' => '삼성전자',     'amount' => 55000000, 'method' => 'transfer'],
    ['date' => '2025-01-10', 'client' => 'LG전자',       'amount' => 28000000, 'method' => 'transfer'],
    ['date' => '2025-01-15', 'client' => '현대자동차',   'amount' => 42000000, 'method' => 'transfer'],
    ['date' => '2025-01-20', 'client' => '네이버',       'amount' => 15000000, 'method' => 'card'],
    ['date' => '2025-01-25', 'client' => '카카오',       'amount' => 8500000,  'method' => 'transfer'],

    // 2월
    ['date' => '2025-02-05', 'client' => 'SK하이닉스',   'amount' => 68000000, 'method' => 'transfer'],
    ['date' => '2025-02-10', 'client' => '쿠팡',         'amount' => 22000000, 'method' => 'transfer'],
    ['date' => '2025-02-15', 'client' => '토스',         'amount' => 9800000,  'method' => 'card'],
    ['date' => '2025-02-20', 'client' => '삼성SDS',      'amount' => 35000000, 'method' => 'transfer'],
    ['date' => '2025-02-25', 'client' => '두산에너빌리티','amount' => 48000000, 'method' => 'check'],

    // ... 3월 ~ 12월 (패턴 반복, Seeder에서 자동 생성)
];
```

### 3.7 withdrawals (출금) - 60개 예시

```php
// 월별 5건씩, 총 60건
$withdrawals = [
    // 1월
    ['date' => '2025-01-03', 'client' => '한화솔루션',   'amount' => 32000000, 'method' => 'transfer'],
    ['date' => '2025-01-08', 'client' => '포스코',       'amount' => 45000000, 'method' => 'transfer'],
    ['date' => '2025-01-15', 'client' => '롯데케미칼',   'amount' => 18000000, 'method' => 'transfer'],
    ['date' => '2025-01-22', 'client' => 'GS칼텍스',     'amount' => 12500000, 'method' => 'card'],
    ['date' => '2025-01-28', 'client' => '대한항공',     'amount' => 5800000,  'method' => 'transfer'],

    // 2월
    ['date' => '2025-02-05', 'client' => '현대제철',     'amount' => 52000000, 'method' => 'transfer'],
    ['date' => '2025-02-12', 'client' => 'SK이노베이션', 'amount' => 28000000, 'method' => 'transfer'],
    ['date' => '2025-02-18', 'client' => 'CJ대한통운',   'amount' => 8500000,  'method' => 'transfer'],
    ['date' => '2025-02-22', 'client' => '한화솔루션',   'amount' => 25000000, 'method' => 'check'],
    ['date' => '2025-02-28', 'client' => '포스코',       'amount' => 38000000, 'method' => 'transfer'],

    // ... 3월 ~ 12월 (패턴 반복)
];
```

### 3.8 sales (매출) - 80개 예시

```php
// 월별 6~7건, 총 80건
// 상태: 1~10월 invoiced/confirmed, 11~12월 draft 포함
$sales = [
    // 1월 (6건)
    ['number' => 'SAL-202501-0001', 'date' => '2025-01-05', 'client' => '삼성전자',     'supply' => 50000000, 'status' => 'invoiced'],
    ['number' => 'SAL-202501-0002', 'date' => '2025-01-08', 'client' => 'LG전자',       'supply' => 25454545, 'status' => 'invoiced'],
    ['number' => 'SAL-202501-0003', 'date' => '2025-01-12', 'client' => '현대자동차',   'supply' => 38181818, 'status' => 'invoiced'],
    ['number' => 'SAL-202501-0004', 'date' => '2025-01-18', 'client' => '네이버',       'supply' => 13636364, 'status' => 'confirmed'],
    ['number' => 'SAL-202501-0005', 'date' => '2025-01-22', 'client' => '카카오',       'supply' => 7727273,  'status' => 'confirmed'],
    ['number' => 'SAL-202501-0006', 'date' => '2025-01-28', 'client' => '삼성SDS',      'supply' => 31818182, 'status' => 'invoiced'],

    // ... 2월 ~ 10월 (invoiced/confirmed)

    // 11월 (8건 - draft 포함)
    ['number' => 'SAL-202511-0001', 'date' => '2025-11-03', 'client' => '삼성전자',     'supply' => 45000000, 'status' => 'invoiced'],
    ['number' => 'SAL-202511-0002', 'date' => '2025-11-06', 'client' => 'SK하이닉스',   'supply' => 62000000, 'status' => 'invoiced'],
    ['number' => 'SAL-202511-0003', 'date' => '2025-11-10', 'client' => '쿠팡',         'supply' => 18181818, 'status' => 'confirmed'],
    ['number' => 'SAL-202511-0004', 'date' => '2025-11-14', 'client' => '두산에너빌리티','supply' => 55000000, 'status' => 'confirmed'],
    ['number' => 'SAL-202511-0005', 'date' => '2025-11-18', 'client' => '당근마켓',     'supply' => 8909091,  'status' => 'confirmed'],
    ['number' => 'SAL-202511-0006', 'date' => '2025-11-22', 'client' => '토스',         'supply' => 12727273, 'status' => 'draft'],
    ['number' => 'SAL-202511-0007', 'date' => '2025-11-26', 'client' => '배달의민족',   'supply' => 15454545, 'status' => 'draft'],
    ['number' => 'SAL-202511-0008', 'date' => '2025-11-29', 'client' => 'LG전자',       'supply' => 28000000, 'status' => 'draft'],

    // 12월 (7건 - draft 위주)
    ['number' => 'SAL-202512-0001', 'date' => '2025-12-02', 'client' => '삼성전자',     'supply' => 48000000, 'status' => 'confirmed'],
    ['number' => 'SAL-202512-0002', 'date' => '2025-12-05', 'client' => '현대자동차',   'supply' => 35000000, 'status' => 'draft'],
    ['number' => 'SAL-202512-0003', 'date' => '2025-12-10', 'client' => '네이버',       'supply' => 22727273, 'status' => 'draft'],
    ['number' => 'SAL-202512-0004', 'date' => '2025-12-13', 'client' => '카카오',       'supply' => 16363636, 'status' => 'draft'],
    ['number' => 'SAL-202512-0005', 'date' => '2025-12-17', 'client' => '삼성SDS',      'supply' => 42000000, 'status' => 'draft'],
    ['number' => 'SAL-202512-0006', 'date' => '2025-12-20', 'client' => 'SK하이닉스',   'supply' => 58000000, 'status' => 'draft'],
    ['number' => 'SAL-202512-0007', 'date' => '2025-12-23', 'client' => '쿠팡',         'supply' => 20000000, 'status' => 'draft'],
];
```

### 3.9 purchases (매입) - 70개 예시

```php
// 월별 5~6건, 총 70건
$purchases = [
    // 1월 (5건)
    ['number' => 'PUR-202501-0001', 'date' => '2025-01-03', 'client' => '한화솔루션',   'supply' => 29090909, 'status' => 'confirmed'],
    ['number' => 'PUR-202501-0002', 'date' => '2025-01-10', 'client' => '포스코',       'supply' => 40909091, 'status' => 'confirmed'],
    ['number' => 'PUR-202501-0003', 'date' => '2025-01-15', 'client' => '롯데케미칼',   'supply' => 16363636, 'status' => 'confirmed'],
    ['number' => 'PUR-202501-0004', 'date' => '2025-01-22', 'client' => 'GS칼텍스',     'supply' => 11363636, 'status' => 'confirmed'],
    ['number' => 'PUR-202501-0005', 'date' => '2025-01-28', 'client' => '대한항공',     'supply' => 5272727,  'status' => 'confirmed'],

    // ... 2월 ~ 10월 (confirmed)

    // 11월 (7건 - draft 포함)
    ['number' => 'PUR-202511-0001', 'date' => '2025-11-03', 'client' => '현대제철',     'supply' => 48000000, 'status' => 'confirmed'],
    ['number' => 'PUR-202511-0002', 'date' => '2025-11-08', 'client' => 'SK이노베이션', 'supply' => 32000000, 'status' => 'confirmed'],
    ['number' => 'PUR-202511-0003', 'date' => '2025-11-12', 'client' => 'CJ대한통운',   'supply' => 9090909,  'status' => 'confirmed'],
    ['number' => 'PUR-202511-0004', 'date' => '2025-11-18', 'client' => '한화솔루션',   'supply' => 35000000, 'status' => 'confirmed'],
    ['number' => 'PUR-202511-0005', 'date' => '2025-11-22', 'client' => '포스코',       'supply' => 42000000, 'status' => 'draft'],
    ['number' => 'PUR-202511-0006', 'date' => '2025-11-26', 'client' => '롯데케미칼',   'supply' => 18181818, 'status' => 'draft'],
    ['number' => 'PUR-202511-0007', 'date' => '2025-11-29', 'client' => '두산에너빌리티','supply' => 55000000, 'status' => 'draft'],

    // 12월 (6건 - draft 위주)
    ['number' => 'PUR-202512-0001', 'date' => '2025-12-02', 'client' => 'GS칼텍스',     'supply' => 15454545, 'status' => 'confirmed'],
    ['number' => 'PUR-202512-0002', 'date' => '2025-12-06', 'client' => '대한항공',     'supply' => 7272727,  'status' => 'draft'],
    ['number' => 'PUR-202512-0003', 'date' => '2025-12-11', 'client' => '현대제철',     'supply' => 52000000, 'status' => 'draft'],
    ['number' => 'PUR-202512-0004', 'date' => '2025-12-15', 'client' => 'SK이노베이션', 'supply' => 28000000, 'status' => 'draft'],
    ['number' => 'PUR-202512-0005', 'date' => '2025-12-19', 'client' => '한화솔루션',   'supply' => 38000000, 'status' => 'draft'],
    ['number' => 'PUR-202512-0006', 'date' => '2025-12-23', 'client' => '포스코',       'supply' => 45000000, 'status' => 'draft'],
];
```

### 3.10 bills (어음) - 30개 예시

```php
// 수취 어음 15건 + 발행 어음 15건, 총 30건
// bill_type: received(수취), issued(발행)
// status (수취): stored, maturityAlert, maturityResult, paymentComplete, dishonored
// status (발행): stored, maturityAlert, collectionRequest, collectionComplete, suing, dishonored

$bills = [
    // 수취 어음 (received) - 15건
    ['bill_number' => '202501000001', 'type' => 'received', 'client' => '삼성전자',     'amount' => 50000000, 'issue_date' => '2025-01-15', 'maturity_date' => '2025-04-15', 'status' => 'paymentComplete'],
    ['bill_number' => '202501000002', 'type' => 'received', 'client' => 'LG전자',       'amount' => 35000000, 'issue_date' => '2025-02-10', 'maturity_date' => '2025-05-10', 'status' => 'paymentComplete'],
    ['bill_number' => '202502000001', 'type' => 'received', 'client' => 'SK하이닉스',   'amount' => 80000000, 'issue_date' => '2025-02-20', 'maturity_date' => '2025-05-20', 'status' => 'paymentComplete'],
    ['bill_number' => '202503000001', 'type' => 'received', 'client' => '현대자동차',   'amount' => 45000000, 'issue_date' => '2025-03-05', 'maturity_date' => '2025-06-05', 'status' => 'maturityResult'],
    ['bill_number' => '202504000001', 'type' => 'received', 'client' => '네이버',       'amount' => 25000000, 'issue_date' => '2025-04-12', 'maturity_date' => '2025-07-12', 'status' => 'maturityResult'],
    ['bill_number' => '202505000001', 'type' => 'received', 'client' => '카카오',       'amount' => 18000000, 'issue_date' => '2025-05-08', 'maturity_date' => '2025-08-08', 'status' => 'stored'],
    ['bill_number' => '202506000001', 'type' => 'received', 'client' => '쿠팡',         'amount' => 32000000, 'issue_date' => '2025-06-15', 'maturity_date' => '2025-09-15', 'status' => 'stored'],
    ['bill_number' => '202507000001', 'type' => 'received', 'client' => '삼성SDS',      'amount' => 65000000, 'issue_date' => '2025-07-20', 'maturity_date' => '2025-10-20', 'status' => 'stored'],
    ['bill_number' => '202508000001', 'type' => 'received', 'client' => '토스',         'amount' => 15000000, 'issue_date' => '2025-08-10', 'maturity_date' => '2025-11-10', 'status' => 'stored'],
    ['bill_number' => '202509000001', 'type' => 'received', 'client' => '두산에너빌리티','amount' => 55000000, 'issue_date' => '2025-09-05', 'maturity_date' => '2025-12-05', 'status' => 'maturityAlert'],
    ['bill_number' => '202510000001', 'type' => 'received', 'client' => '삼성전자',     'amount' => 42000000, 'issue_date' => '2025-10-15', 'maturity_date' => '2026-01-15', 'status' => 'stored'],
    ['bill_number' => '202511000001', 'type' => 'received', 'client' => 'LG전자',       'amount' => 28000000, 'issue_date' => '2025-11-08', 'maturity_date' => '2026-02-08', 'status' => 'stored'],
    ['bill_number' => '202511000002', 'type' => 'received', 'client' => '네이버',       'amount' => 38000000, 'issue_date' => '2025-11-20', 'maturity_date' => '2026-02-20', 'status' => 'stored'],
    ['bill_number' => '202512000001', 'type' => 'received', 'client' => '현대자동차',   'amount' => 52000000, 'issue_date' => '2025-12-10', 'maturity_date' => '2026-03-10', 'status' => 'stored'],
    ['bill_number' => '202512000002', 'type' => 'received', 'client' => 'SK하이닉스',   'amount' => 70000000, 'issue_date' => '2025-12-18', 'maturity_date' => '2026-03-18', 'status' => 'stored'],

    // 발행 어음 (issued) - 15건
    ['bill_number' => '202501100001', 'type' => 'issued', 'client' => '한화솔루션',   'amount' => 40000000, 'issue_date' => '2025-01-20', 'maturity_date' => '2025-04-20', 'status' => 'collectionComplete'],
    ['bill_number' => '202502100001', 'type' => 'issued', 'client' => '포스코',       'amount' => 55000000, 'issue_date' => '2025-02-15', 'maturity_date' => '2025-05-15', 'status' => 'collectionComplete'],
    ['bill_number' => '202503100001', 'type' => 'issued', 'client' => '롯데케미칼',   'amount' => 30000000, 'issue_date' => '2025-03-10', 'maturity_date' => '2025-06-10', 'status' => 'collectionComplete'],
    ['bill_number' => '202504100001', 'type' => 'issued', 'client' => 'GS칼텍스',     'amount' => 22000000, 'issue_date' => '2025-04-18', 'maturity_date' => '2025-07-18', 'status' => 'collectionComplete'],
    ['bill_number' => '202505100001', 'type' => 'issued', 'client' => '대한항공',     'amount' => 18000000, 'issue_date' => '2025-05-12', 'maturity_date' => '2025-08-12', 'status' => 'collectionRequest'],
    ['bill_number' => '202506100001', 'type' => 'issued', 'client' => '현대제철',     'amount' => 48000000, 'issue_date' => '2025-06-20', 'maturity_date' => '2025-09-20', 'status' => 'collectionRequest'],
    ['bill_number' => '202507100001', 'type' => 'issued', 'client' => 'SK이노베이션', 'amount' => 35000000, 'issue_date' => '2025-07-15', 'maturity_date' => '2025-10-15', 'status' => 'stored'],
    ['bill_number' => '202508100001', 'type' => 'issued', 'client' => 'CJ대한통운',   'amount' => 25000000, 'issue_date' => '2025-08-22', 'maturity_date' => '2025-11-22', 'status' => 'stored'],
    ['bill_number' => '202509100001', 'type' => 'issued', 'client' => '두산에너빌리티','amount' => 60000000, 'issue_date' => '2025-09-10', 'maturity_date' => '2025-12-10', 'status' => 'maturityAlert'],
    ['bill_number' => '202510100001', 'type' => 'issued', 'client' => '한화솔루션',   'amount' => 45000000, 'issue_date' => '2025-10-08', 'maturity_date' => '2026-01-08', 'status' => 'stored'],
    ['bill_number' => '202511100001', 'type' => 'issued', 'client' => '포스코',       'amount' => 58000000, 'issue_date' => '2025-11-05', 'maturity_date' => '2026-02-05', 'status' => 'stored'],
    ['bill_number' => '202511100002', 'type' => 'issued', 'client' => '롯데케미칼',   'amount' => 32000000, 'issue_date' => '2025-11-18', 'maturity_date' => '2026-02-18', 'status' => 'stored'],
    ['bill_number' => '202512100001', 'type' => 'issued', 'client' => 'GS칼텍스',     'amount' => 28000000, 'issue_date' => '2025-12-05', 'maturity_date' => '2026-03-05', 'status' => 'stored'],
    ['bill_number' => '202512100002', 'type' => 'issued', 'client' => '현대제철',     'amount' => 42000000, 'issue_date' => '2025-12-15', 'maturity_date' => '2026-03-15', 'status' => 'stored'],
    ['bill_number' => '202512100003', 'type' => 'issued', 'client' => 'SK이노베이션', 'amount' => 38000000, 'issue_date' => '2025-12-22', 'maturity_date' => '2026-03-22', 'status' => 'stored'],
];

// 일부 어음에 차수 관리 내역 추가 (15건)
$billInstallments = [
    // 수취 어음 차수
    ['bill_number' => '202501000001', 'installments' => [
        ['date' => '2025-02-15', 'amount' => 25000000, 'note' => '1차 분할 입금'],
        ['date' => '2025-03-15', 'amount' => 25000000, 'note' => '2차 분할 입금'],
    ]],
    ['bill_number' => '202502000001', 'installments' => [
        ['date' => '2025-03-20', 'amount' => 40000000, 'note' => '1차 분할 입금'],
        ['date' => '2025-04-20', 'amount' => 40000000, 'note' => '2차 분할 입금'],
    ]],
    ['bill_number' => '202507000001', 'installments' => [
        ['date' => '2025-08-20', 'amount' => 30000000, 'note' => '1차 분할 입금'],
        ['date' => '2025-09-20', 'amount' => 35000000, 'note' => '2차 분할 입금'],
    ]],

    // 발행 어음 차수
    ['bill_number' => '202501100001', 'installments' => [
        ['date' => '2025-02-20', 'amount' => 20000000, 'note' => '1차 분할 지급'],
        ['date' => '2025-03-20', 'amount' => 20000000, 'note' => '2차 분할 지급'],
    ]],
    ['bill_number' => '202502100001', 'installments' => [
        ['date' => '2025-03-15', 'amount' => 27500000, 'note' => '1차 분할 지급'],
        ['date' => '2025-04-15', 'amount' => 27500000, 'note' => '2차 분할 지급'],
    ]],
    ['bill_number' => '202506100001', 'installments' => [
        ['date' => '2025-07-20', 'amount' => 24000000, 'note' => '1차 분할 지급'],
        ['date' => '2025-08-20', 'amount' => 24000000, 'note' => '2차 분할 지급'],
    ]],
];
```

---

## 4. Laravel Seeder 구현 전략

### 4.1 Seeder 파일 구조

```
database/seeders/
├── DummyDataSeeder.php          ← 메인 Seeder (순서 제어)
└── Dummy/
    ├── DummyClientGroupSeeder.php    ← 거래처 그룹 (5개)
    ├── DummyBankAccountSeeder.php    ← 은행 계좌 (5개)
    ├── DummyClientSeeder.php         ← 거래처 (20개)
    ├── DummyDepositSeeder.php        ← 입금 (60개)
    ├── DummyWithdrawalSeeder.php     ← 출금 (60개)
    ├── DummyBillSeeder.php           ← 어음 (30개) + 차수 (15개)
    ├── DummySaleSeeder.php           ← 매출 (80개)
    └── DummyPurchaseSeeder.php       ← 매입 (70개)
```

### 4.2 메인 Seeder

```php
<?php
// database/seeders/DummyDataSeeder.php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DummyDataSeeder extends Seeder
{
    // 대상 테넌트 ID
    public const TENANT_ID = 287;

    // 생성자 사용자 ID
    public const USER_ID = 1;

    public function run(): void
    {
        $this->command->info('🌱 더미 데이터 시딩 시작...');
        $this->command->info('   대상 테넌트: ID ' . self::TENANT_ID);

        $this->call([
            Dummy\DummyClientGroupSeeder::class,
            Dummy\DummyBankAccountSeeder::class,
            Dummy\DummyClientSeeder::class,
            Dummy\DummyDepositSeeder::class,
            Dummy\DummyWithdrawalSeeder::class,
            Dummy\DummyBillSeeder::class,
            Dummy\DummySaleSeeder::class,
            Dummy\DummyPurchaseSeeder::class,
        ]);

        $this->command->info('');
        $this->command->info('✅ 더미 데이터 시딩 완료!');
        $this->command->table(
            ['테이블', '생성 수량'],
            [
                ['client_groups', '5'],
                ['bank_accounts', '5'],
                ['clients', '20'],
                ['deposits', '60'],
                ['withdrawals', '60'],
                ['bills', '30'],
                ['bill_installments', '15'],
                ['sales', '80'],
                ['purchases', '70'],
                ['총계', '~345'],
            ]
        );
    }
}
```

### 4.3 실행 방법

```bash
# 더미 데이터 시딩
php artisan db:seed --class=DummyDataSeeder

# 특정 Seeder만 실행
php artisan db:seed --class=Database\\Seeders\\Dummy\\DummyClientSeeder
```

### 4.4 DB 스키마 상세 정의

#### 4.4.1 client_groups 테이블
```sql
CREATE TABLE client_groups (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tenant_id       BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',
    group_code      VARCHAR(30) NOT NULL COMMENT '그룹 코드',
    group_name      VARCHAR(100) NOT NULL COMMENT '그룹명',
    price_rate      DECIMAL(5,4) DEFAULT 1.0000 COMMENT '가격 배율',
    is_active       TINYINT DEFAULT 1 COMMENT '활성 여부',
    created_by      BIGINT UNSIGNED NULL COMMENT '생성자 ID',
    updated_by      BIGINT UNSIGNED NULL COMMENT '수정자 ID',
    deleted_by      BIGINT UNSIGNED NULL COMMENT '삭제자 ID',
    created_at      TIMESTAMP NULL,
    updated_at      TIMESTAMP NULL,
    deleted_at      TIMESTAMP NULL,

    UNIQUE INDEX uq_client_groups_tenant_code (tenant_id, group_code),
    FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
```

#### 4.4.2 bank_accounts 테이블
```sql
CREATE TABLE bank_accounts (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tenant_id       BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',
    bank_code       VARCHAR(10) NOT NULL COMMENT '은행 코드',
    bank_name       VARCHAR(50) NOT NULL COMMENT '은행명',
    account_number  VARCHAR(30) NOT NULL COMMENT '계좌번호',
    account_holder  VARCHAR(50) NOT NULL COMMENT '예금주',
    account_name    VARCHAR(100) NOT NULL COMMENT '계좌 별칭',
    status          VARCHAR(20) DEFAULT 'active' COMMENT '상태: active/inactive',
    assigned_user_id BIGINT UNSIGNED NULL COMMENT '담당자 ID',
    is_primary      BOOLEAN DEFAULT FALSE COMMENT '대표계좌 여부',
    created_by      BIGINT UNSIGNED NULL COMMENT '생성자 ID',
    updated_by      BIGINT UNSIGNED NULL COMMENT '수정자 ID',
    deleted_by      BIGINT UNSIGNED NULL COMMENT '삭제자 ID',
    created_at      TIMESTAMP NULL,
    updated_at      TIMESTAMP NULL,
    deleted_at      TIMESTAMP NULL
);
```

#### 4.4.3 clients 테이블 (주요 컬럼)
```sql
-- 핵심 필드만 기재 (전체 스키마는 마이그레이션 참조)
CREATE TABLE clients (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tenant_id       BIGINT UNSIGNED NOT NULL,
    client_group_id BIGINT UNSIGNED NULL COMMENT '그룹 ID (FK)',
    client_code     VARCHAR(20) NOT NULL COMMENT '거래처 코드',
    name            VARCHAR(100) NOT NULL COMMENT '거래처명',
    client_type     VARCHAR(20) NULL COMMENT 'SALES/PURCHASE/BOTH',
    contact_person  VARCHAR(50) NULL COMMENT '담당자명',
    phone           VARCHAR(20) NULL,
    mobile          VARCHAR(20) NULL,
    email           VARCHAR(100) NULL,
    address         TEXT NULL,
    business_no     VARCHAR(20) NULL COMMENT '사업자번호',
    business_type   VARCHAR(50) NULL COMMENT '업종',
    business_item   VARCHAR(100) NULL COMMENT '업태',
    is_active       BOOLEAN DEFAULT TRUE,
    created_at      TIMESTAMP NULL,
    updated_at      TIMESTAMP NULL,
    deleted_at      TIMESTAMP NULL
);
```

#### 4.4.4 deposits 테이블
```sql
CREATE TABLE deposits (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tenant_id       BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',
    deposit_date    DATE NOT NULL COMMENT '입금일',
    client_id       BIGINT UNSIGNED NULL COMMENT '거래처 ID',
    client_name     VARCHAR(100) NULL COMMENT '비회원 거래처명',
    bank_account_id BIGINT UNSIGNED NULL COMMENT '입금 계좌 ID',
    amount          DECIMAL(15,2) NOT NULL COMMENT '금액',
    payment_method  VARCHAR(20) NOT NULL COMMENT 'cash/transfer/card/check',
    account_code    VARCHAR(20) NULL COMMENT '계정과목',
    description     TEXT NULL COMMENT '적요',
    reference_type  VARCHAR(50) NULL COMMENT '참조 유형',
    reference_id    BIGINT UNSIGNED NULL COMMENT '참조 ID',
    created_by      BIGINT UNSIGNED NULL,
    updated_by      BIGINT UNSIGNED NULL,
    deleted_by      BIGINT UNSIGNED NULL,
    created_at      TIMESTAMP NULL,
    updated_at      TIMESTAMP NULL,
    deleted_at      TIMESTAMP NULL
);
```

#### 4.4.5 withdrawals 테이블
```sql
CREATE TABLE withdrawals (
    id                BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tenant_id         BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',
    withdrawal_date   DATE NOT NULL COMMENT '출금일',
    client_id         BIGINT UNSIGNED NULL COMMENT '거래처 ID',
    client_name       VARCHAR(100) NULL COMMENT '비회원 거래처명',
    bank_account_id   BIGINT UNSIGNED NULL COMMENT '출금 계좌 ID',
    amount            DECIMAL(15,2) NOT NULL COMMENT '금액',
    payment_method    VARCHAR(20) NOT NULL COMMENT 'cash/transfer/card/check',
    account_code      VARCHAR(20) NULL COMMENT '계정과목',
    description       TEXT NULL COMMENT '적요',
    reference_type    VARCHAR(50) NULL COMMENT '참조 유형',
    reference_id      BIGINT UNSIGNED NULL COMMENT '참조 ID',
    created_by        BIGINT UNSIGNED NULL,
    updated_by        BIGINT UNSIGNED NULL,
    deleted_by        BIGINT UNSIGNED NULL,
    created_at        TIMESTAMP NULL,
    updated_at        TIMESTAMP NULL,
    deleted_at        TIMESTAMP NULL
);
```

#### 4.4.6 sales 테이블
```sql
CREATE TABLE sales (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tenant_id       BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',
    sale_number     VARCHAR(30) NOT NULL COMMENT '매출번호',
    sale_date       DATE NOT NULL COMMENT '매출일자',
    client_id       BIGINT UNSIGNED NOT NULL COMMENT '거래처 ID',
    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 NULL COMMENT '적요',
    status          VARCHAR(20) DEFAULT 'draft' COMMENT 'draft/confirmed/invoiced',
    tax_invoice_id  BIGINT UNSIGNED NULL COMMENT '세금계산서 ID',
    deposit_id      BIGINT UNSIGNED NULL COMMENT '입금 연결 ID',
    created_by      BIGINT UNSIGNED NULL,
    updated_by      BIGINT UNSIGNED NULL,
    deleted_by      BIGINT UNSIGNED NULL,
    created_at      TIMESTAMP NULL,
    updated_at      TIMESTAMP NULL,
    deleted_at      TIMESTAMP NULL,

    UNIQUE INDEX uk_tenant_sale_number (tenant_id, sale_number)
);
```

#### 4.4.7 purchases 테이블
```sql
CREATE TABLE purchases (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    tenant_id       BIGINT UNSIGNED NOT NULL COMMENT '테넌트 ID',
    purchase_number VARCHAR(30) NOT NULL COMMENT '매입번호',
    purchase_date   DATE NOT NULL COMMENT '매입일자',
    client_id       BIGINT UNSIGNED NOT NULL COMMENT '거래처 ID',
    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 NULL COMMENT '적요',
    status          VARCHAR(20) DEFAULT 'draft' COMMENT 'draft/confirmed',
    withdrawal_id   BIGINT UNSIGNED NULL COMMENT '출금 연결 ID',
    created_by      BIGINT UNSIGNED NULL,
    updated_by      BIGINT UNSIGNED NULL,
    deleted_by      BIGINT UNSIGNED NULL,
    created_at      TIMESTAMP NULL,
    updated_at      TIMESTAMP NULL,
    deleted_at      TIMESTAMP NULL,

    UNIQUE INDEX uk_tenant_purchase_number (tenant_id, purchase_number)
);
```

### 4.5 모델 경로 및 네임스페이스

| 테이블 | 모델 클래스 | 네임스페이스 |
|--------|------------|-------------|
| client_groups | ClientGroup | `App\Models\Orders\ClientGroup` |
| bank_accounts | BankAccount | `App\Models\Tenants\BankAccount` |
| clients | Client | `App\Models\Orders\Client` |
| deposits | Deposit | `App\Models\Tenants\Deposit` |
| withdrawals | Withdrawal | `App\Models\Tenants\Withdrawal` |
| sales | Sale | `App\Models\Tenants\Sale` |
| purchases | Purchase | `App\Models\Tenants\Purchase` |

### 4.6 필수 상수값

#### 결제수단 (payment_method)
```php
// Deposit::PAYMENT_METHODS, Withdrawal::PAYMENT_METHODS
[
    'cash'     => '현금',
    'transfer' => '계좌이체',
    'card'     => '카드',
    'check'    => '수표',
]
```

#### 매출 상태 (Sale::STATUSES)
```php
[
    'draft'     => '임시저장',
    'confirmed' => '확정',
    'invoiced'  => '세금계산서발행',
]
```

#### 매입 상태 (Purchase::STATUSES)
```php
[
    'draft'     => '임시저장',
    'confirmed' => '확정',
]
```

#### 거래처 유형 (client_type)
```php
// common_codes 테이블에서 관리
// group: 'client_type'
[
    'SALES'    => '매출처',
    'PURCHASE' => '매입처',
    'BOTH'     => '매출매입처',
]
```

### 4.7 완전한 Seeder 코드 구현

#### 4.7.1 DummyClientGroupSeeder.php
```php
<?php

namespace Database\Seeders\Dummy;

use App\Models\Orders\ClientGroup;
use Database\Seeders\DummyDataSeeder;
use Illuminate\Database\Seeder;

class DummyClientGroupSeeder extends Seeder
{
    public function run(): void
    {
        $tenantId = DummyDataSeeder::TENANT_ID;
        $userId = DummyDataSeeder::USER_ID;

        $groups = [
            ['group_code' => 'VIP',    'group_name' => 'VIP 고객',   'price_rate' => 0.95],
            ['group_code' => 'GOLD',   'group_name' => '골드 고객',  'price_rate' => 0.97],
            ['group_code' => 'SILVER', 'group_name' => '실버 고객',  'price_rate' => 0.98],
            ['group_code' => 'NORMAL', 'group_name' => '일반 고객',  'price_rate' => 1.00],
            ['group_code' => 'NEW',    'group_name' => '신규 고객',  'price_rate' => 1.00],
        ];

        foreach ($groups as $group) {
            ClientGroup::create([
                'tenant_id'  => $tenantId,
                'group_code' => $group['group_code'],
                'group_name' => $group['group_name'],
                'price_rate' => $group['price_rate'],
                'is_active'  => true,
                'created_by' => $userId,
            ]);
        }

        $this->command->info('   ✓ client_groups: ' . count($groups) . '건 생성');
    }
}
```

#### 4.7.2 DummyBankAccountSeeder.php
```php
<?php

namespace Database\Seeders\Dummy;

use App\Models\Tenants\BankAccount;
use Database\Seeders\DummyDataSeeder;
use Illuminate\Database\Seeder;

class DummyBankAccountSeeder extends Seeder
{
    public function run(): void
    {
        $tenantId = DummyDataSeeder::TENANT_ID;
        $userId = DummyDataSeeder::USER_ID;

        $accounts = [
            ['bank_code' => '004', 'bank_name' => 'KB국민은행', 'account_number' => '123-45-6789012',   'account_holder' => '프론트테스트', 'account_name' => '운영계좌', 'is_primary' => true],
            ['bank_code' => '088', 'bank_name' => '신한은행',   'account_number' => '110-123-456789',  'account_holder' => '프론트테스트', 'account_name' => '급여계좌', 'is_primary' => false],
            ['bank_code' => '020', 'bank_name' => '우리은행',   'account_number' => '1002-123-456789', 'account_holder' => '프론트테스트', 'account_name' => '예비계좌', 'is_primary' => false],
            ['bank_code' => '081', 'bank_name' => '하나은행',   'account_number' => '123-456789-12345','account_holder' => '프론트테스트', 'account_name' => '법인카드', 'is_primary' => false],
            ['bank_code' => '011', 'bank_name' => 'NH농협은행', 'account_number' => '351-1234-5678-12','account_holder' => '프론트테스트', 'account_name' => '비상금',   'is_primary' => false],
        ];

        foreach ($accounts as $account) {
            BankAccount::create([
                'tenant_id'      => $tenantId,
                'bank_code'      => $account['bank_code'],
                'bank_name'      => $account['bank_name'],
                'account_number' => $account['account_number'],
                'account_holder' => $account['account_holder'],
                'account_name'   => $account['account_name'],
                'status'         => 'active',
                'is_primary'     => $account['is_primary'],
                'created_by'     => $userId,
            ]);
        }

        $this->command->info('   ✓ bank_accounts: ' . count($accounts) . '건 생성');
    }
}
```

#### 4.7.3 DummyClientSeeder.php
```php
<?php

namespace Database\Seeders\Dummy;

use App\Models\Orders\Client;
use App\Models\Orders\ClientGroup;
use Database\Seeders\DummyDataSeeder;
use Illuminate\Database\Seeder;

class DummyClientSeeder extends Seeder
{
    public function run(): void
    {
        $tenantId = DummyDataSeeder::TENANT_ID;
        $userId = DummyDataSeeder::USER_ID;

        // 그룹 ID 조회
        $groups = ClientGroup::where('tenant_id', $tenantId)
            ->pluck('id', 'group_code')
            ->toArray();

        // 매출처 (SALES) - 10개
        $salesClients = [
            ['code' => 'S001', 'name' => '삼성전자',     'business_no' => '124-81-00998', 'group' => 'VIP',    'contact' => '김철수', 'phone' => '02-1234-5678', 'email' => 'kim@samsung.com'],
            ['code' => 'S002', 'name' => 'LG전자',       'business_no' => '107-86-14075', 'group' => 'VIP',    'contact' => '이영희', 'phone' => '02-2345-6789', 'email' => 'lee@lg.com'],
            ['code' => 'S003', 'name' => 'SK하이닉스',   'business_no' => '204-81-17169', 'group' => 'GOLD',   'contact' => '박민수', 'phone' => '031-123-4567', 'email' => 'park@skhynix.com'],
            ['code' => 'S004', 'name' => '현대자동차',   'business_no' => '101-81-05765', 'group' => 'GOLD',   'contact' => '정은지', 'phone' => '02-3456-7890', 'email' => 'jung@hyundai.com'],
            ['code' => 'S005', 'name' => '네이버',       'business_no' => '220-81-62517', 'group' => 'GOLD',   'contact' => '최준호', 'phone' => '031-234-5678', 'email' => 'choi@naver.com'],
            ['code' => 'S006', 'name' => '카카오',       'business_no' => '120-87-65763', 'group' => 'SILVER', 'contact' => '강미래', 'phone' => '02-4567-8901', 'email' => 'kang@kakao.com'],
            ['code' => 'S007', 'name' => '쿠팡',         'business_no' => '120-88-00767', 'group' => 'SILVER', 'contact' => '임도현', 'phone' => '02-5678-9012', 'email' => 'lim@coupang.com'],
            ['code' => 'S008', 'name' => '토스',         'business_no' => '120-87-83139', 'group' => 'NORMAL', 'contact' => '윤서연', 'phone' => '02-6789-0123', 'email' => 'yoon@toss.im'],
            ['code' => 'S009', 'name' => '배달의민족',   'business_no' => '220-87-93847', 'group' => 'NORMAL', 'contact' => '한지민', 'phone' => '02-7890-1234', 'email' => 'han@woowahan.com'],
            ['code' => 'S010', 'name' => '당근마켓',     'business_no' => '815-87-01234', 'group' => 'NEW',    'contact' => '오태양', 'phone' => '02-8901-2345', 'email' => 'oh@daangn.com'],
        ];

        // 매입처 (PURCHASE) - 7개
        $purchaseClients = [
            ['code' => 'P001', 'name' => '한화솔루션',   'business_no' => '138-81-00610', 'group' => null, 'contact' => '김재원', 'phone' => '02-1111-2222', 'email' => 'kim@hanwha.com'],
            ['code' => 'P002', 'name' => '포스코',       'business_no' => '506-81-08754', 'group' => null, 'contact' => '이현석', 'phone' => '054-111-2222', 'email' => 'lee@posco.com'],
            ['code' => 'P003', 'name' => '롯데케미칼',   'business_no' => '301-81-07123', 'group' => null, 'contact' => '박서준', 'phone' => '02-2222-3333', 'email' => 'park@lottechem.com'],
            ['code' => 'P004', 'name' => 'GS칼텍스',     'business_no' => '104-81-23858', 'group' => null, 'contact' => '정해인', 'phone' => '02-3333-4444', 'email' => 'jung@gscaltex.com'],
            ['code' => 'P005', 'name' => '대한항공',     'business_no' => '110-81-14794', 'group' => null, 'contact' => '송민호', 'phone' => '02-4444-5555', 'email' => 'song@koreanair.com'],
            ['code' => 'P006', 'name' => '현대제철',     'business_no' => '130-81-12345', 'group' => null, 'contact' => '강동원', 'phone' => '032-555-6666', 'email' => 'kang@hyundaisteel.com'],
            ['code' => 'P007', 'name' => 'SK이노베이션', 'business_no' => '110-81-67890', 'group' => null, 'contact' => '유재석', 'phone' => '02-6666-7777', 'email' => 'yoo@skinnovation.com'],
        ];

        // 매출매입처 (BOTH) - 3개
        $bothClients = [
            ['code' => 'B001', 'name' => '두산에너빌리티', 'business_no' => '124-81-08628', 'group' => 'GOLD',   'contact' => '조인성', 'phone' => '02-7777-8888', 'email' => 'cho@doosan.com'],
            ['code' => 'B002', 'name' => 'CJ대한통운',    'business_no' => '104-81-39849', 'group' => 'SILVER', 'contact' => '공유',   'phone' => '02-8888-9999', 'email' => 'gong@cjlogistics.com'],
            ['code' => 'B003', 'name' => '삼성SDS',       'business_no' => '124-81-34567', 'group' => 'VIP',    'contact' => '이정재', 'phone' => '02-9999-0000', 'email' => 'lee@samsungsds.com'],
        ];

        $count = 0;

        // 매출처 생성
        foreach ($salesClients as $client) {
            $this->createClient($client, 'SALES', $tenantId, $userId, $groups);
            $count++;
        }

        // 매입처 생성
        foreach ($purchaseClients as $client) {
            $this->createClient($client, 'PURCHASE', $tenantId, $userId, $groups);
            $count++;
        }

        // 매출매입처 생성
        foreach ($bothClients as $client) {
            $this->createClient($client, 'BOTH', $tenantId, $userId, $groups);
            $count++;
        }

        $this->command->info('   ✓ clients: ' . $count . '건 생성');
    }

    private function createClient(array $data, string $type, int $tenantId, int $userId, array $groups): void
    {
        Client::create([
            'tenant_id'       => $tenantId,
            'client_group_id' => $data['group'] ? ($groups[$data['group']] ?? null) : null,
            'client_code'     => $data['code'],
            'name'            => $data['name'],
            'client_type'     => $type,
            'contact_person'  => $data['contact'],
            'phone'           => $data['phone'],
            'email'           => $data['email'],
            'business_no'     => $data['business_no'],
            'business_type'   => '제조업',
            'business_item'   => '전자제품',
            'is_active'       => true,
        ]);
    }
}
```

#### 4.7.4 DummyDepositSeeder.php
```php
<?php

namespace Database\Seeders\Dummy;

use App\Models\Orders\Client;
use App\Models\Tenants\BankAccount;
use App\Models\Tenants\Deposit;
use Database\Seeders\DummyDataSeeder;
use Illuminate\Database\Seeder;

class DummyDepositSeeder extends Seeder
{
    public function run(): void
    {
        $tenantId = DummyDataSeeder::TENANT_ID;
        $userId = DummyDataSeeder::USER_ID;

        // 거래처 매핑 (SALES, BOTH만)
        $clients = Client::where('tenant_id', $tenantId)
            ->whereIn('client_type', ['SALES', 'BOTH'])
            ->get()
            ->keyBy('name');

        // 은행계좌 (대표계좌 우선)
        $bankAccounts = BankAccount::where('tenant_id', $tenantId)
            ->where('status', 'active')
            ->orderByDesc('is_primary')
            ->get();

        $primaryBankId = $bankAccounts->first()?->id;

        // 결제수단 분포: transfer(70%), card(15%), cash(10%), check(5%)
        $methods = array_merge(
            array_fill(0, 14, 'transfer'),
            array_fill(0, 3, 'card'),
            array_fill(0, 2, 'cash'),
            array_fill(0, 1, 'check')
        );

        // 거래처 순환 목록
        $clientNames = [
            '삼성전자', 'LG전자', 'SK하이닉스', '현대자동차', '네이버',
            '카카오', '쿠팡', '토스', '배달의민족', '당근마켓',
            '두산에너빌리티', 'CJ대한통운', '삼성SDS',
        ];

        // 금액 범위
        $amounts = [
            'small'  => [1000000, 5000000],     // 30%
            'medium' => [5000000, 30000000],    // 50%
            'large'  => [30000000, 100000000],  // 20%
        ];

        $count = 0;
        $year = 2025;

        // 월별 5건씩, 총 60건
        for ($month = 1; $month <= 12; $month++) {
            $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);

            for ($i = 0; $i < 5; $i++) {
                $day = rand(1, $daysInMonth);
                $clientName = $clientNames[($month * 5 + $i) % count($clientNames)];
                $client = $clients->get($clientName);

                // 금액 결정 (분포에 따라)
                $rand = rand(1, 100);
                if ($rand <= 30) {
                    $amount = rand($amounts['small'][0], $amounts['small'][1]);
                } elseif ($rand <= 80) {
                    $amount = rand($amounts['medium'][0], $amounts['medium'][1]);
                } else {
                    $amount = rand($amounts['large'][0], $amounts['large'][1]);
                }

                Deposit::create([
                    'tenant_id'       => $tenantId,
                    'deposit_date'    => sprintf('%04d-%02d-%02d', $year, $month, $day),
                    'client_id'       => $client?->id,
                    'client_name'     => $client ? null : $clientName,
                    'bank_account_id' => $primaryBankId,
                    'amount'          => $amount,
                    'payment_method'  => $methods[array_rand($methods)],
                    'description'     => $clientName . ' 입금',
                    'created_by'      => $userId,
                ]);

                $count++;
            }
        }

        $this->command->info('   ✓ deposits: ' . $count . '건 생성');
    }
}
```

#### 4.7.5 DummyWithdrawalSeeder.php
```php
<?php

namespace Database\Seeders\Dummy;

use App\Models\Orders\Client;
use App\Models\Tenants\BankAccount;
use App\Models\Tenants\Withdrawal;
use Database\Seeders\DummyDataSeeder;
use Illuminate\Database\Seeder;

class DummyWithdrawalSeeder extends Seeder
{
    public function run(): void
    {
        $tenantId = DummyDataSeeder::TENANT_ID;
        $userId = DummyDataSeeder::USER_ID;

        // 거래처 매핑 (PURCHASE, BOTH만)
        $clients = Client::where('tenant_id', $tenantId)
            ->whereIn('client_type', ['PURCHASE', 'BOTH'])
            ->get()
            ->keyBy('name');

        // 은행계좌
        $primaryBankId = BankAccount::where('tenant_id', $tenantId)
            ->where('is_primary', true)
            ->value('id');

        // 결제수단 분포
        $methods = array_merge(
            array_fill(0, 14, 'transfer'),
            array_fill(0, 3, 'card'),
            array_fill(0, 2, 'cash'),
            array_fill(0, 1, 'check')
        );

        // 매입처 순환 목록
        $clientNames = [
            '한화솔루션', '포스코', '롯데케미칼', 'GS칼텍스', '대한항공',
            '현대제철', 'SK이노베이션', 'CJ대한통운', '두산에너빌리티',
        ];

        $amounts = [
            'small'  => [1000000, 5000000],
            'medium' => [5000000, 30000000],
            'large'  => [30000000, 80000000],
        ];

        $count = 0;
        $year = 2025;

        for ($month = 1; $month <= 12; $month++) {
            $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);

            for ($i = 0; $i < 5; $i++) {
                $day = rand(1, $daysInMonth);
                $clientName = $clientNames[($month * 5 + $i) % count($clientNames)];
                $client = $clients->get($clientName);

                $rand = rand(1, 100);
                if ($rand <= 30) {
                    $amount = rand($amounts['small'][0], $amounts['small'][1]);
                } elseif ($rand <= 80) {
                    $amount = rand($amounts['medium'][0], $amounts['medium'][1]);
                } else {
                    $amount = rand($amounts['large'][0], $amounts['large'][1]);
                }

                Withdrawal::create([
                    'tenant_id'       => $tenantId,
                    'withdrawal_date' => sprintf('%04d-%02d-%02d', $year, $month, $day),
                    'client_id'       => $client?->id,
                    'client_name'     => $client ? null : $clientName,
                    'bank_account_id' => $primaryBankId,
                    'amount'          => $amount,
                    'payment_method'  => $methods[array_rand($methods)],
                    'description'     => $clientName . ' 지급',
                    'created_by'      => $userId,
                ]);

                $count++;
            }
        }

        $this->command->info('   ✓ withdrawals: ' . $count . '건 생성');
    }
}
```

#### 4.7.6 DummySaleSeeder.php
```php
<?php

namespace Database\Seeders\Dummy;

use App\Models\Orders\Client;
use App\Models\Tenants\Sale;
use Database\Seeders\DummyDataSeeder;
use Illuminate\Database\Seeder;

class DummySaleSeeder extends Seeder
{
    public function run(): void
    {
        $tenantId = DummyDataSeeder::TENANT_ID;
        $userId = DummyDataSeeder::USER_ID;

        // 거래처 매핑 (SALES, BOTH만)
        $clients = Client::where('tenant_id', $tenantId)
            ->whereIn('client_type', ['SALES', 'BOTH'])
            ->get()
            ->keyBy('name');

        $clientNames = [
            '삼성전자', 'LG전자', 'SK하이닉스', '현대자동차', '네이버',
            '카카오', '쿠팡', '토스', '배달의민족', '당근마켓',
            '두산에너빌리티', 'CJ대한통운', '삼성SDS',
        ];

        $amounts = [
            'small'  => [1000000, 5000000],
            'medium' => [5000000, 30000000],
            'large'  => [30000000, 100000000],
        ];

        // 월별 건수: 1~10월 6~7건, 11월 8건, 12월 7건 = 80건
        $monthlyCount = [6, 6, 7, 6, 7, 6, 7, 6, 7, 7, 8, 7];

        $count = 0;
        $year = 2025;

        for ($month = 1; $month <= 12; $month++) {
            $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
            $salesCount = $monthlyCount[$month - 1];

            for ($i = 0; $i < $salesCount; $i++) {
                $day = (int) (($i + 1) * $daysInMonth / ($salesCount + 1));
                $day = max(1, min($day, $daysInMonth));

                $clientName = $clientNames[($count) % count($clientNames)];
                $client = $clients->get($clientName);

                // 금액 결정
                $rand = rand(1, 100);
                if ($rand <= 30) {
                    $supply = rand($amounts['small'][0], $amounts['small'][1]);
                } elseif ($rand <= 80) {
                    $supply = rand($amounts['medium'][0], $amounts['medium'][1]);
                } else {
                    $supply = rand($amounts['large'][0], $amounts['large'][1]);
                }

                // 상태 결정: 1~10월 invoiced/confirmed, 11~12월 draft 포함
                if ($month <= 10) {
                    $status = rand(0, 1) ? 'invoiced' : 'confirmed';
                } elseif ($month == 11) {
                    $status = $i < 5 ? (rand(0, 1) ? 'invoiced' : 'confirmed') : 'draft';
                } else {
                    $status = $i < 1 ? 'confirmed' : 'draft';
                }

                $tax = round($supply * 0.1);
                $total = $supply + $tax;

                Sale::create([
                    'tenant_id'     => $tenantId,
                    'sale_number'   => sprintf('SAL-%04d%02d-%04d', $year, $month, $i + 1),
                    'sale_date'     => sprintf('%04d-%02d-%02d', $year, $month, $day),
                    'client_id'     => $client->id,
                    'supply_amount' => $supply,
                    'tax_amount'    => $tax,
                    'total_amount'  => $total,
                    'description'   => $clientName . ' 매출',
                    'status'        => $status,
                    'created_by'    => $userId,
                ]);

                $count++;
            }
        }

        $this->command->info('   ✓ sales: ' . $count . '건 생성');
    }
}
```

#### 4.7.7 DummyPurchaseSeeder.php
```php
<?php

namespace Database\Seeders\Dummy;

use App\Models\Orders\Client;
use App\Models\Tenants\Purchase;
use Database\Seeders\DummyDataSeeder;
use Illuminate\Database\Seeder;

class DummyPurchaseSeeder extends Seeder
{
    public function run(): void
    {
        $tenantId = DummyDataSeeder::TENANT_ID;
        $userId = DummyDataSeeder::USER_ID;

        // 거래처 매핑 (PURCHASE, BOTH만)
        $clients = Client::where('tenant_id', $tenantId)
            ->whereIn('client_type', ['PURCHASE', 'BOTH'])
            ->get()
            ->keyBy('name');

        $clientNames = [
            '한화솔루션', '포스코', '롯데케미칼', 'GS칼텍스', '대한항공',
            '현대제철', 'SK이노베이션', 'CJ대한통운', '두산에너빌리티',
        ];

        $amounts = [
            'small'  => [1000000, 5000000],
            'medium' => [5000000, 30000000],
            'large'  => [30000000, 80000000],
        ];

        // 월별 건수: 1~10월 5~6건, 11월 7건, 12월 6건 = 70건
        $monthlyCount = [5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 7, 6];

        $count = 0;
        $year = 2025;

        for ($month = 1; $month <= 12; $month++) {
            $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
            $purchaseCount = $monthlyCount[$month - 1];

            for ($i = 0; $i < $purchaseCount; $i++) {
                $day = (int) (($i + 1) * $daysInMonth / ($purchaseCount + 1));
                $day = max(1, min($day, $daysInMonth));

                $clientName = $clientNames[($count) % count($clientNames)];
                $client = $clients->get($clientName);

                $rand = rand(1, 100);
                if ($rand <= 30) {
                    $supply = rand($amounts['small'][0], $amounts['small'][1]);
                } elseif ($rand <= 80) {
                    $supply = rand($amounts['medium'][0], $amounts['medium'][1]);
                } else {
                    $supply = rand($amounts['large'][0], $amounts['large'][1]);
                }

                // 상태 결정
                if ($month <= 10) {
                    $status = 'confirmed';
                } elseif ($month == 11) {
                    $status = $i < 4 ? 'confirmed' : 'draft';
                } else {
                    $status = $i < 1 ? 'confirmed' : 'draft';
                }

                $tax = round($supply * 0.1);
                $total = $supply + $tax;

                Purchase::create([
                    'tenant_id'       => $tenantId,
                    'purchase_number' => sprintf('PUR-%04d%02d-%04d', $year, $month, $i + 1),
                    'purchase_date'   => sprintf('%04d-%02d-%02d', $year, $month, $day),
                    'client_id'       => $client->id,
                    'supply_amount'   => $supply,
                    'tax_amount'      => $tax,
                    'total_amount'    => $total,
                    'description'     => $clientName . ' 매입',
                    'status'          => $status,
                    'created_by'      => $userId,
                ]);

                $count++;
            }
        }

        $this->command->info('   ✓ purchases: ' . $count . '건 생성');
    }
}
```

#### 4.7.8 DummyBillSeeder.php
```php
<?php

namespace Database\Seeders\Dummy;

use App\Models\Orders\Client;
use App\Models\Tenants\BankAccount;
use App\Models\Tenants\Bill;
use App\Models\Tenants\BillInstallment;
use Database\Seeders\DummyDataSeeder;
use Illuminate\Database\Seeder;

class DummyBillSeeder extends Seeder
{
    public function run(): void
    {
        $tenantId = DummyDataSeeder::TENANT_ID;
        $userId = DummyDataSeeder::USER_ID;

        // 거래처 매핑
        $clients = Client::where('tenant_id', $tenantId)->get()->keyBy('name');

        // 은행계좌 (대표계좌)
        $primaryBankId = BankAccount::where('tenant_id', $tenantId)
            ->where('is_primary', true)
            ->value('id');

        // 수취 어음 데이터 (received) - 15건
        $receivedBills = [
            ['bill_number' => '202501000001', 'client' => '삼성전자',      'amount' => 50000000, 'issue_date' => '2025-01-15', 'maturity_date' => '2025-04-15', 'status' => 'paymentComplete'],
            ['bill_number' => '202501000002', 'client' => 'LG전자',        'amount' => 35000000, 'issue_date' => '2025-02-10', 'maturity_date' => '2025-05-10', 'status' => 'paymentComplete'],
            ['bill_number' => '202502000001', 'client' => 'SK하이닉스',    'amount' => 80000000, 'issue_date' => '2025-02-20', 'maturity_date' => '2025-05-20', 'status' => 'paymentComplete'],
            ['bill_number' => '202503000001', 'client' => '현대자동차',    'amount' => 45000000, 'issue_date' => '2025-03-05', 'maturity_date' => '2025-06-05', 'status' => 'maturityResult'],
            ['bill_number' => '202504000001', 'client' => '네이버',        'amount' => 25000000, 'issue_date' => '2025-04-12', 'maturity_date' => '2025-07-12', 'status' => 'maturityResult'],
            ['bill_number' => '202505000001', 'client' => '카카오',        'amount' => 18000000, 'issue_date' => '2025-05-08', 'maturity_date' => '2025-08-08', 'status' => 'stored'],
            ['bill_number' => '202506000001', 'client' => '쿠팡',          'amount' => 32000000, 'issue_date' => '2025-06-15', 'maturity_date' => '2025-09-15', 'status' => 'stored'],
            ['bill_number' => '202507000001', 'client' => '삼성SDS',       'amount' => 65000000, 'issue_date' => '2025-07-20', 'maturity_date' => '2025-10-20', 'status' => 'stored'],
            ['bill_number' => '202508000001', 'client' => '토스',          'amount' => 15000000, 'issue_date' => '2025-08-10', 'maturity_date' => '2025-11-10', 'status' => 'stored'],
            ['bill_number' => '202509000001', 'client' => '두산에너빌리티', 'amount' => 55000000, 'issue_date' => '2025-09-05', 'maturity_date' => '2025-12-05', 'status' => 'maturityAlert'],
            ['bill_number' => '202510000001', 'client' => '삼성전자',      'amount' => 42000000, 'issue_date' => '2025-10-15', 'maturity_date' => '2026-01-15', 'status' => 'stored'],
            ['bill_number' => '202511000001', 'client' => 'LG전자',        'amount' => 28000000, 'issue_date' => '2025-11-08', 'maturity_date' => '2026-02-08', 'status' => 'stored'],
            ['bill_number' => '202511000002', 'client' => '네이버',        'amount' => 38000000, 'issue_date' => '2025-11-20', 'maturity_date' => '2026-02-20', 'status' => 'stored'],
            ['bill_number' => '202512000001', 'client' => '현대자동차',    'amount' => 52000000, 'issue_date' => '2025-12-10', 'maturity_date' => '2026-03-10', 'status' => 'stored'],
            ['bill_number' => '202512000002', 'client' => 'SK하이닉스',    'amount' => 70000000, 'issue_date' => '2025-12-18', 'maturity_date' => '2026-03-18', 'status' => 'stored'],
        ];

        // 발행 어음 데이터 (issued) - 15건
        $issuedBills = [
            ['bill_number' => '202501100001', 'client' => '한화솔루션',    'amount' => 40000000, 'issue_date' => '2025-01-20', 'maturity_date' => '2025-04-20', 'status' => 'collectionComplete'],
            ['bill_number' => '202502100001', 'client' => '포스코',        'amount' => 55000000, 'issue_date' => '2025-02-15', 'maturity_date' => '2025-05-15', 'status' => 'collectionComplete'],
            ['bill_number' => '202503100001', 'client' => '롯데케미칼',    'amount' => 30000000, 'issue_date' => '2025-03-10', 'maturity_date' => '2025-06-10', 'status' => 'collectionComplete'],
            ['bill_number' => '202504100001', 'client' => 'GS칼텍스',      'amount' => 22000000, 'issue_date' => '2025-04-18', 'maturity_date' => '2025-07-18', 'status' => 'collectionComplete'],
            ['bill_number' => '202505100001', 'client' => '대한항공',      'amount' => 18000000, 'issue_date' => '2025-05-12', 'maturity_date' => '2025-08-12', 'status' => 'collectionRequest'],
            ['bill_number' => '202506100001', 'client' => '현대제철',      'amount' => 48000000, 'issue_date' => '2025-06-20', 'maturity_date' => '2025-09-20', 'status' => 'collectionRequest'],
            ['bill_number' => '202507100001', 'client' => 'SK이노베이션',  'amount' => 35000000, 'issue_date' => '2025-07-15', 'maturity_date' => '2025-10-15', 'status' => 'stored'],
            ['bill_number' => '202508100001', 'client' => 'CJ대한통운',    'amount' => 25000000, 'issue_date' => '2025-08-22', 'maturity_date' => '2025-11-22', 'status' => 'stored'],
            ['bill_number' => '202509100001', 'client' => '두산에너빌리티', 'amount' => 60000000, 'issue_date' => '2025-09-10', 'maturity_date' => '2025-12-10', 'status' => 'maturityAlert'],
            ['bill_number' => '202510100001', 'client' => '한화솔루션',    'amount' => 45000000, 'issue_date' => '2025-10-08', 'maturity_date' => '2026-01-08', 'status' => 'stored'],
            ['bill_number' => '202511100001', 'client' => '포스코',        'amount' => 58000000, 'issue_date' => '2025-11-05', 'maturity_date' => '2026-02-05', 'status' => 'stored'],
            ['bill_number' => '202511100002', 'client' => '롯데케미칼',    'amount' => 32000000, 'issue_date' => '2025-11-18', 'maturity_date' => '2026-02-18', 'status' => 'stored'],
            ['bill_number' => '202512100001', 'client' => 'GS칼텍스',      'amount' => 28000000, 'issue_date' => '2025-12-05', 'maturity_date' => '2026-03-05', 'status' => 'stored'],
            ['bill_number' => '202512100002', 'client' => '현대제철',      'amount' => 42000000, 'issue_date' => '2025-12-15', 'maturity_date' => '2026-03-15', 'status' => 'stored'],
            ['bill_number' => '202512100003', 'client' => 'SK이노베이션',  'amount' => 38000000, 'issue_date' => '2025-12-22', 'maturity_date' => '2026-03-22', 'status' => 'stored'],
        ];

        // 차수 관리 데이터
        $installmentsData = [
            '202501000001' => [
                ['date' => '2025-02-15', 'amount' => 25000000, 'note' => '1차 분할 입금'],
                ['date' => '2025-03-15', 'amount' => 25000000, 'note' => '2차 분할 입금'],
            ],
            '202502000001' => [
                ['date' => '2025-03-20', 'amount' => 40000000, 'note' => '1차 분할 입금'],
                ['date' => '2025-04-20', 'amount' => 40000000, 'note' => '2차 분할 입금'],
            ],
            '202507000001' => [
                ['date' => '2025-08-20', 'amount' => 30000000, 'note' => '1차 분할 입금'],
                ['date' => '2025-09-20', 'amount' => 35000000, 'note' => '2차 분할 입금'],
            ],
            '202501100001' => [
                ['date' => '2025-02-20', 'amount' => 20000000, 'note' => '1차 분할 지급'],
                ['date' => '2025-03-20', 'amount' => 20000000, 'note' => '2차 분할 지급'],
            ],
            '202502100001' => [
                ['date' => '2025-03-15', 'amount' => 27500000, 'note' => '1차 분할 지급'],
                ['date' => '2025-04-15', 'amount' => 27500000, 'note' => '2차 분할 지급'],
            ],
            '202506100001' => [
                ['date' => '2025-07-20', 'amount' => 24000000, 'note' => '1차 분할 지급'],
                ['date' => '2025-08-20', 'amount' => 24000000, 'note' => '2차 분할 지급'],
            ],
        ];

        $billCount = 0;
        $installmentCount = 0;

        // 수취 어음 생성
        foreach ($receivedBills as $data) {
            $client = $clients->get($data['client']);
            $bill = Bill::create([
                'tenant_id'         => $tenantId,
                'bill_number'       => $data['bill_number'],
                'bill_type'         => 'received',
                'client_id'         => $client?->id,
                'client_name'       => $client ? null : $data['client'],
                'amount'            => $data['amount'],
                'issue_date'        => $data['issue_date'],
                'maturity_date'     => $data['maturity_date'],
                'status'            => $data['status'],
                'is_electronic'     => rand(0, 1) === 1,
                'bank_account_id'   => $primaryBankId,
                'installment_count' => isset($installmentsData[$data['bill_number']]) ? count($installmentsData[$data['bill_number']]) : 0,
                'created_by'        => $userId,
            ]);
            $billCount++;

            // 차수 관리 데이터 추가
            if (isset($installmentsData[$data['bill_number']])) {
                foreach ($installmentsData[$data['bill_number']] as $instData) {
                    BillInstallment::create([
                        'bill_id'          => $bill->id,
                        'installment_date' => $instData['date'],
                        'amount'           => $instData['amount'],
                        'note'             => $instData['note'],
                    ]);
                    $installmentCount++;
                }
            }
        }

        // 발행 어음 생성
        foreach ($issuedBills as $data) {
            $client = $clients->get($data['client']);
            $bill = Bill::create([
                'tenant_id'         => $tenantId,
                'bill_number'       => $data['bill_number'],
                'bill_type'         => 'issued',
                'client_id'         => $client?->id,
                'client_name'       => $client ? null : $data['client'],
                'amount'            => $data['amount'],
                'issue_date'        => $data['issue_date'],
                'maturity_date'     => $data['maturity_date'],
                'status'            => $data['status'],
                'is_electronic'     => rand(0, 1) === 1,
                'bank_account_id'   => $primaryBankId,
                'installment_count' => isset($installmentsData[$data['bill_number']]) ? count($installmentsData[$data['bill_number']]) : 0,
                'created_by'        => $userId,
            ]);
            $billCount++;

            // 차수 관리 데이터 추가
            if (isset($installmentsData[$data['bill_number']])) {
                foreach ($installmentsData[$data['bill_number']] as $instData) {
                    BillInstallment::create([
                        'bill_id'          => $bill->id,
                        'installment_date' => $instData['date'],
                        'amount'           => $instData['amount'],
                        'note'             => $instData['note'],
                    ]);
                    $installmentCount++;
                }
            }
        }

        $this->command->info('   ✓ bills: ' . $billCount . '건 생성');
        $this->command->info('   ✓ bill_installments: ' . $installmentCount . '건 생성');
    }
}
```

---

## 5. 데이터 검증

### 5.1 시딩 후 검증 쿼리

```sql
-- 테이블별 데이터 수 확인
SELECT 'client_groups' as tbl, COUNT(*) as cnt FROM client_groups WHERE tenant_id = 287
UNION ALL
SELECT 'bank_accounts', COUNT(*) FROM bank_accounts WHERE tenant_id = 287
UNION ALL
SELECT 'clients', COUNT(*) FROM clients WHERE tenant_id = 287
UNION ALL
SELECT 'deposits', COUNT(*) FROM deposits WHERE tenant_id = 287
UNION ALL
SELECT 'withdrawals', COUNT(*) FROM withdrawals WHERE tenant_id = 287
UNION ALL
SELECT 'bills', COUNT(*) FROM bills WHERE tenant_id = 287
UNION ALL
SELECT 'bill_installments', COUNT(*) FROM bill_installments WHERE bill_id IN (SELECT id FROM bills WHERE tenant_id = 287)
UNION ALL
SELECT 'sales', COUNT(*) FROM sales WHERE tenant_id = 287
UNION ALL
SELECT 'purchases', COUNT(*) FROM purchases WHERE tenant_id = 287;

-- 어음 현황 (수취/발행별)
SELECT bill_type, status, COUNT(*) as count, SUM(amount) as total_amount
FROM bills
WHERE tenant_id = 287
GROUP BY bill_type, status
ORDER BY bill_type, status;

-- 월별 매출 현황
SELECT DATE_FORMAT(sale_date, '%Y-%m') as month,
       COUNT(*) as count,
       SUM(total_amount) as total
FROM sales
WHERE tenant_id = 287
GROUP BY month
ORDER BY month;

-- 거래처별 매출/매입 합계
SELECT c.name,
       COALESCE(SUM(s.total_amount), 0) as total_sales,
       COALESCE(SUM(p.total_amount), 0) as total_purchases
FROM clients c
LEFT JOIN sales s ON c.id = s.client_id AND s.deleted_at IS NULL
LEFT JOIN purchases p ON c.id = p.client_id AND p.deleted_at IS NULL
WHERE c.tenant_id = 287
GROUP BY c.id, c.name
ORDER BY total_sales DESC;
```

### 5.2 예상 결과 요약

| 항목 | 예상 값 |
|------|---------|
| 총 거래처 | 24개 (기존 4 + 신규 20) |
| 총 매출건수 | 80건 |
| 총 매입건수 | 70건 |
| 총 입금건수 | 60건 |
| 총 출금건수 | 60건 |
| 총 어음건수 | 30건 (수취 15건 + 발행 15건) |
| 총 차수건수 | 12건 (6개 어음 × 2차) |
| 연간 매출액 | 약 25~30억원 |
| 연간 매입액 | 약 18~22억원 |
| 수취어음 총액 | 약 6.5억원 |
| 발행어음 총액 | 약 5.8억원 |

---

## 6. 변경 이력

| 날짜 | 내용 | 작성자 |
|------|------|--------|
| 2025-12-23 | 문서 초안 작성 | Claude |
| 2025-12-23 | 1년치 300개 데이터로 확장 | Claude |
| 2025-12-23 | DB 스키마 상세 정의 추가 (4.4) | Claude |
| 2025-12-23 | 모델 경로 및 네임스페이스 추가 (4.5) | Claude |
| 2025-12-23 | 필수 상수값 정의 추가 (4.6) | Claude |
| 2025-12-23 | 완전한 Seeder 코드 구현 추가 (4.7) | Claude |
| 2025-12-23 | 어음(bills) 더미 데이터 추가 (30건 + 차수 12건) | Claude |

---

## 7. 다음 단계

1. [x] Seeder 파일 구현 → 4.7 섹션에 완전한 코드 포함
2. [ ] Seeder 파일 생성 (코드 복사 후 파일 생성)
3. [ ] 시딩 실행 (`php artisan db:seed --class=DummyDataSeeder`)
4. [ ] 데이터 검증 (5.1 검증 쿼리 실행)
5. [ ] React 연동 테스트
6. [ ] 추가 데이터 필요시 확장

---

## 8. 빠른 시작 가이드

### 8.1 Seeder 파일 생성 순서

```bash
# 1. Dummy 디렉토리 생성
mkdir -p api/database/seeders/Dummy

# 2. 파일 생성 (4.2 ~ 4.7 코드 복사)
# - api/database/seeders/DummyDataSeeder.php
# - api/database/seeders/Dummy/DummyClientGroupSeeder.php
# - api/database/seeders/Dummy/DummyBankAccountSeeder.php
# - api/database/seeders/Dummy/DummyClientSeeder.php
# - api/database/seeders/Dummy/DummyDepositSeeder.php
# - api/database/seeders/Dummy/DummyWithdrawalSeeder.php
# - api/database/seeders/Dummy/DummySaleSeeder.php
# - api/database/seeders/Dummy/DummyPurchaseSeeder.php

# 3. 시딩 실행
cd api
php artisan db:seed --class=DummyDataSeeder

# 4. 검증
php artisan tinker
>>> \App\Models\Tenants\Sale::where('tenant_id', 287)->count()
# 결과: 80
```

### 8.2 주요 참조 정보

| 항목 | 값 |
|------|-----|
| **대상 테넌트 ID** | 287 |
| **생성자 사용자 ID** | 1 |
| **데이터 기간** | 2025년 1월 ~ 12월 |
| **총 레코드 수** | ~300개 |

### 8.3 관련 문서

- [React Mock to API Migration Plan](./react-mock-to-api-migration-plan.md) - API 마이그레이션 계획
- [API Rules](../reference/api-rules.md) - API 개발 규칙