Files
sam-docs/features/sales/prospects.md

190 lines
7.4 KiB
Markdown
Raw Permalink Normal View History

# 영업파트너 고객관리
## 개요
영업파트너 고객관리는 영업파트너가 명함을 등록하여 영업권을 확보하고,
고객과의 계약 진행을 관리하는 기능입니다.
명함 등록, 영업권 유효기간(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 실시간 검증
- 모달로 상세/수정 처리