# 영업파트너 고객관리

## 개요

영업파트너 고객관리는 영업파트너가 명함을 등록하여 영업권을 확보하고,
고객과의 계약 진행을 관리하는 기능입니다.
명함 등록, 영업권 유효기간(2개월), 사업자번호 중복 체크, 테넌트 전환을 지원합니다.

- **라우트**: `GET /sales/prospects`
- **미들웨어**: `auth`, `hq.member`
- **UI 기술**: Blade + HTMX + Tailwind CSS

## 파일 구조

```
mng/
├── app/Http/Controllers/Sales/
│   └── TenantProspectController.php      # 메인 컨트롤러 (12개 메서드)
├── app/Services/Sales/
│   └── TenantProspectService.php         # 비즈니스 로직 서비스
├── app/Models/Sales/
│   └── TenantProspect.php                # 가망고객 모델
└── resources/views/sales/prospects/
    ├── index.blade.php                   # 영업권 목록
    ├── create.blade.php                  # 명함 등록 폼
    ├── show.blade.php                    # 상세 페이지
    ├── edit.blade.php                    # 수정 폼
    └── partials/
        ├── show-modal.blade.php          # 상세 모달
        └── edit-modal.blade.php          # 수정 모달

api/
└── database/migrations/
    ├── 2026_01_27_221000_create_tenant_prospects_table.php
    └── 2026_01_28_090000_add_attachments_to_tenant_prospects_table.php
```

## 라우트

```php
// routes/web.php (sales prefix 그룹 내)

// Resource 라우트
GET    /prospects                        → index()    영업권 목록 (본인 기준)
GET    /prospects/create                 → create()   명함 등록 폼
POST   /prospects                        → store()    명함 등록 처리
GET    /prospects/{id}                   → show()     상세 페이지
GET    /prospects/{id}/edit              → edit()     수정 폼
PUT    /prospects/{id}                   → update()   수정 처리
DELETE /prospects/{id}                   → destroy()  삭제 (관리자)

// 추가 라우트
POST   /prospects/{id}/convert           → convert()             테넌트 전환
POST   /prospects/check-business-number  → checkBusinessNumber() 사업자번호 중복 체크
DELETE /prospects/{id}/attachment         → deleteAttachment()    첨부파일 삭제
GET    /prospects/{id}/modal-show        → modalShow()           상세 모달
GET    /prospects/{id}/modal-edit        → modalEdit()           수정 모달
```

## 컨트롤러

### TenantProspectController

| 메서드 | HTTP | 설명 |
|--------|------|------|
| `index()` | GET | 영업권 목록 (현재 사용자 기준) |
| `create()` | GET | 명함 등록 폼 |
| `store()` | POST | 명함 등록 (등록자 = 현재 사용자) |
| `show()` | GET | 상세 페이지 |
| `edit()` | GET | 수정 폼 |
| `update()` | PUT | 정보 수정 |
| `destroy()` | DELETE | 삭제 (관리자 전용) |
| `convert()` | POST | 영업권 → 테넌트 전환 |
| `checkBusinessNumber()` | POST | 사업자번호 중복 체크 (AJAX) |
| `modalShow()` | GET | 상세 모달 |
| `modalEdit()` | GET | 수정 모달 |
| `deleteAttachment()` | DELETE | 첨부 이미지 삭제 |

### TenantProspectService

| 메서드 | 설명 |
|--------|------|
| `register()` | 명함 등록 (영업권 확보), expires_at = 등록일 + 2개월 |
| `update()` | 정보 수정 + 파일 업로드 (명함/신분증/통장) |
| `convertToTenant()` | 영업권 → 테넌트 전환 (Tenant + user_tenants 생성) |
| `expireOldProspects()` | 만료 영업권 자동 처리 (배치) |
| `canRegister()` | 사업자번호 등록 가능 여부 확인 |
| `getProspects()` | 목록 조회 (검색, 상태, 파트너 필터) |
| `getStats()` | 통계 (total, active, expired, converted) |
| `uploadAttachment()` | 파일 업로드 (tenant disk) |
| `deleteAttachment()` | 파일 삭제 |

## 모델

### TenantProspect

**테이블**: `tenant_prospects`

| 필드 | 타입 | 설명 |
|------|------|------|
| `business_number` | string(20) | 사업자번호 (중복 체크 키) |
| `company_name` | string(100) | 회사명 |
| `ceo_name` | string(50) | 대표자명 |
| `contact_phone` | string(20) | 연락처 |
| `contact_email` | string(100) | 이메일 |
| `address` | string(500) | 주소 |
| `registered_by` | bigint (FK) | 등록한 영업파트너 ID |
| `business_card_path` | string(500) | 명함 이미지 경로 |
| `id_card_path` | string(500) | 신분증 이미지 경로 |
| `bankbook_path` | string(500) | 통장 이미지 경로 |
| `status` | string(20) | active / expired / converted / completed |
| `registered_at` | timestamp | 등록일 |
| `expires_at` | timestamp | 만료일 (등록일 + 2개월) |
| `cooldown_ends_at` | timestamp | 재등록 가능일 (만료일 + 1개월) |
| `tenant_id` | bigint (FK, nullable) | 전환된 테넌트 ID |
| `converted_at` | timestamp | 전환일 |
| `converted_by` | bigint (FK) | 전환 처리자 ID |
| `memo` | text | 메모 |

- SoftDeletes 적용

#### 상태 흐름

```
명함 등록 → active (영업권 유효, 2개월)
              │
              ├── convert() → converted (테넌트 전환 완료)
              │                  └→ completed (영업 완료)
              │
              └── (2개월 경과) → expired (만료)
                                  └→ (1개월 쿨다운 후 재등록 가능)
```

#### 영업권 규칙

| 규칙 | 설명 |
|------|------|
| 유효기간 | 등록일로부터 2개월 |
| 쿨다운 | 만료 후 1개월간 재등록 불가 |
| 중복 체크 | 동일 사업자번호 중복 등록 방지 |
| 전환 | 영업권 → Tenant + user_tenants 자동 생성 |

#### 주요 속성/메서드

| 메서드 | 설명 |
|--------|------|
| `isActive()` | 영업권 유효 여부 |
| `isExpired()` | 만료 여부 |
| `isConverted()` | 테넌트 전환 완료 여부 |
| `canReRegister()` | 재등록 가능 여부 |
| `getStatusLabelAttribute()` | 상태 라벨 (영업중/완료/계약완료/대기중/만료) |
| `getStatusColorAttribute()` | Tailwind CSS 색상 |
| `getRemainingDaysAttribute()` | 남은 일수 |

## 뷰 구성

```
┌─ 페이지 헤더 ──────────────────────
│  제목: "고객관리 (영업권)"
│  [명함 등록] 버튼
│
├─ 통계 카드 ────────────────────────
│  전체 | 영업중 | 만료 | 전환완료
│
├─ 필터 영역 ────────────────────────
│  검색 (회사명, 사업자번호) | 상태 필터
│
├─ 영업권 목록 테이블 ──────────────
│  회사명 | 사업자번호 | 대표자 | 연락처 | 상태 | 남은일수 | 작업
│  └─ 상태: 영업중(초록), 만료(빨강), 전환(파랑), 완료(회색) 배지
│  └─ 작업: 상세, 수정, 전환, 삭제
│
├─ 등록 폼 ─────────────────────────
│  사업자번호 (중복 체크), 회사명, 대표자명
│  연락처, 이메일, 주소
│  명함 이미지 업로드
│  신분증, 통장사본 (선택)
│
└─ 상세 모달 ───────────────────────
   회사 정보 + 첨부파일 미리보기
   영업권 상태 + 남은 기간
   [테넌트 전환] 버튼
```

## HTMX 호환성

- Blade + HTMX 기반으로 **HX-Redirect 불필요**
- 사업자번호 중복 체크: AJAX 실시간 검증
- 모달로 상세/수정 처리
