diff --git a/features/crm/README.md b/features/crm/README.md new file mode 100644 index 0000000..8c0659c --- /dev/null +++ b/features/crm/README.md @@ -0,0 +1,81 @@ +# 고객/거래처/채권관리 기능 + +## 개요 + +SAM 프로젝트의 고객/거래처/채권관리 모듈은 거래처 및 고객사 정보 관리, 미수금/미지급금 채권·채무 추적, +환불/해지 요청 처리를 종합적으로 관리하는 시스템입니다. +OCR 기반 명함 인식, 부분 수금/지급 처리, 승인 워크플로우를 지원합니다. + +## 메뉴 구성 + +| 메뉴 | 경로 | 설명 | UI 기술 | +|------|------|------|---------| +| [거래처관리](./trading-partners.md) | `/finance/partners` | 거래처(업체/프리랜서) 등록 관리 | React 18 | +| [고객사관리](./customers.md) | `/finance/customers` | 고객사 정보 및 등급 관리 | React 18 | +| [미수금관리](./receivables.md) | `/finance/receivables` | 채권 현황 및 수금 처리 | React 18 | +| [미지급금관리](./payables.md) | `/finance/payables` | 채무 현황 및 지급 처리 | React 18 | +| [환불/해지관리](./refunds.md) | `/finance/refunds` | 환불/해지 요청 및 승인 처리 | React 18 | + +## 아키텍처 + +``` +┌───────────────────────────────────────────────────────────────┐ +│ 고객/거래처/채권관리 모듈 │ +├───────────┬───────────┬───────────┬───────────┬───────────────┤ +│ 거래처관리 │ 고객사관리 │ 미수금관리 │ 미지급금관리│ 환불/해지관리 │ +│(업체/프리) │(등급관리) │(채권추적) │(채무추적) │(요청/승인) │ +│ OCR인식 │ VIP~Brz │ 수금처리 │ 지급처리 │ 워크플로우 │ +└─────┬─────┴─────┬─────┴─────┬─────┴─────┬─────┴───────┬──────┘ + │ │ │ │ │ + ▼ ▼ ▼ ▼ ▼ +┌───────────────────────────────────────────────────────────────┐ +│ 데이터베이스 │ +│ trading_partners, customers, │ +│ receivables, payables, refunds │ +└───────────────────────────────────────────────────────────────┘ +``` + +## 주요 기술 스택 + +| 기술 | 용도 | +|------|------| +| Laravel 11 (PHP 8.3) | 백엔드 프레임워크 | +| React 18 + Babel | 클라이언트 렌더링 UI (전 페이지) | +| Tailwind CSS + Lucide | 스타일링 및 아이콘 | +| OCR (Claude Vision) | 명함 인식 (거래처관리) | +| MySQL 8.0 | 데이터 저장 | + +## 공통 패턴 + +### 멀티 테넌트 + +모든 테이블은 `tenant_id` 기반으로 데이터를 격리합니다. + +### 부분 수금/지급 + +미수금과 미지급금은 부분 처리를 지원합니다: +``` +수금/지급액 입력 → collected/paid_amount 누적 +→ 전액 수금/지급: collected/paid 상태로 변경 +→ 부분 수금/지급: partial 상태로 변경 +``` + +### 상태 관리 비교 + +| 기능 | 상태값 | +|------|--------| +| 거래처 | active / inactive | +| 고객사 | active / inactive | +| 미수금 | outstanding → partial → collected / overdue | +| 미지급금 | unpaid → partial → paid / overdue | +| 환불/해지 | pending → approved → completed / rejected | + +## 데이터베이스 테이블 요약 + +| 테이블 | 역할 | +|--------|------| +| `trading_partners` | 거래처 정보 (업체/프리랜서, 사업자번호, 계좌 등) | +| `customers` | 고객사 정보 (등급, 업종, 담당자 등) | +| `receivables` | 미수금 (고객별 인보이스, 수금액, 연체 추적) | +| `payables` | 미지급금 (업체별 인보이스, 지급액, 세금계산서) | +| `refunds` | 환불/해지 요청 (타입, 사유, 처리상태) | diff --git a/features/crm/customers.md b/features/crm/customers.md new file mode 100644 index 0000000..9752eea --- /dev/null +++ b/features/crm/customers.md @@ -0,0 +1,135 @@ +# 고객사관리 + +## 개요 + +고객사관리는 회사의 고객사 정보를 등급별로 관리하는 기능입니다. +고객사 CRUD, 등급 분류(VIP/Gold/Silver/Bronze), 업종별 관리, 담당자 정보를 지원합니다. + +- **라우트**: `GET /finance/customers` +- **라우트 이름**: `finance.customers` +- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링) + +## 파일 구조 + +``` +mng/ +├── app/Http/Controllers/Finance/ +│ └── CustomerController.php # 메인 컨트롤러 (4개 메서드) +├── app/Models/Finance/ +│ └── Customer.php # 고객사 모델 +└── resources/views/finance/ + └── customers.blade.php # React 기반 단일 페이지 + +api/ +└── database/migrations/ + └── 2026_02_04_230001_create_customers_table.php +``` + +## 라우트 + +```php +// routes/web.php (finance prefix 그룹 내) +GET /customers → 페이지 렌더링 (HX-Redirect) + +// API 라우트 (customers prefix) +GET /customers/list → index() 고객사 목록 (JSON) +POST /customers/store → store() 고객사 등록 +PUT /customers/{id} → update() 고객사 수정 +DELETE /customers/{id} → destroy() 고객사 삭제 +``` + +## 컨트롤러 + +### CustomerController + +| 메서드 | HTTP | 설명 | +|--------|------|------| +| `index()` | GET | 고객사 목록 (검색, 등급/상태 필터) | +| `store()` | POST | 고객사 등록 (name 필수) | +| `update()` | PUT | 고객사 수정 | +| `destroy()` | DELETE | 고객사 삭제 (Soft Delete) | + +### index() 응답 구조 + +```json +{ + "success": true, + "data": [...], + "stats": { + "total": 100, + "active": 85, + "vip": 10, + "inactive": 15 + } +} +``` + +## 모델 + +### Customer + +**테이블**: `customers` + +| 필드 | 타입 | 설명 | +|------|------|------| +| `tenant_id` | bigint | 테넌트 ID | +| `name` | string(100) | 고객사명 | +| `biz_no` | string(20) | 사업자번호 | +| `ceo` | string(50) | 대표자명 | +| `industry` | string(50) | 업종 | +| `grade` | string(20) | 등급 (기본: Silver) | +| `contact` | string(50) | 연락처 | +| `email` | string(100) | 이메일 | +| `address` | string(200) | 주소 | +| `manager` | string(50) | 담당자명 | +| `manager_phone` | string(20) | 담당자 연락처 | +| `status` | string(20) | active / inactive | +| `memo` | text | 메모 | + +- SoftDeletes 적용 +- Scope: `forTenant($tenantId)` + +#### 등급 (grade) + +| 등급 | 설명 | +|------|------| +| VIP | 최우수 고객 | +| Gold | 우수 고객 | +| Silver | 일반 고객 (기본값) | +| Bronze | 신규/소규모 고객 | + +#### 업종 목록 + +IT/소프트웨어, 제조업, 서비스업, 유통업, 금융업, 기타 + +## 뷰 구성 (React) + +### customers.blade.php + +``` +┌─ 페이지 헤더 ────────────────────── +│ 제목: "고객사관리" +│ [CSV 내보내기] [등록] 버튼 +│ +├─ 통계 카드 (4열) ────────────────── +│ 전체 | 활성 | VIP | 비활성 +│ +├─ 필터 영역 ──────────────────────── +│ 검색 (고객사명, 대표자, 담당자) | 등급 필터 | 상태 필터 +│ +├─ 고객사 목록 테이블 ─────────────── +│ 고객사명 | 사업자번호 | 대표자 | 업종 | 등급 | 연락처 | 이메일 | 담당자 | 상태 +│ └─ 등급: VIP(보라), Gold(노랑), Silver(회색), Bronze(갈색) 배지 +│ +├─ 등록/수정 모달 ─────────────────── +│ 고객사명, 사업자번호, 대표자명 +│ 업종, 등급, 연락처, 이메일, 주소 +│ 담당자, 담당자 연락처, 상태, 메모 +│ +└─ 비어있을 때: 안내 메시지 +``` + +## HTMX 호환성 + +- React 기반 페이지이므로 **HX-Redirect 필요** +- `@push('scripts')` 블록에 React/Babel 스크립트 포함 diff --git a/features/crm/payables.md b/features/crm/payables.md new file mode 100644 index 0000000..f305483 --- /dev/null +++ b/features/crm/payables.md @@ -0,0 +1,150 @@ +# 미지급금관리 + +## 개요 + +미지급금관리는 공급업체별 채무 현황을 추적하고 지급 처리를 관리하는 기능입니다. +인보이스별 미지급금 등록, 부분/전액 지급 처리, 세금계산서 발행 추적, 연체 관리를 지원합니다. + +- **라우트**: `GET /finance/payables` +- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링) + +## 파일 구조 + +``` +mng/ +├── app/Http/Controllers/Finance/ +│ └── PayableController.php # 메인 컨트롤러 (5개 메서드) +├── app/Models/Finance/ +│ └── Payable.php # 미지급금 모델 +└── resources/views/finance/ + └── payables.blade.php # React 기반 단일 페이지 + +api/ +└── database/migrations/ + ├── 2026_02_04_222513_create_payables_table.php + └── 2026_02_05_600000_add_tax_type_and_payable_fields.php +``` + +## 라우트 + +```php +// routes/web.php (finance prefix 그룹 내) +GET /payables → 페이지 렌더링 (HX-Redirect) +GET /payables/list → index() 목록 + 통계 (JSON) +POST /payables/store → store() 등록 +PUT /payables/{id} → update() 수정 +POST /payables/{id}/pay → pay() 지급 처리 +DELETE /payables/{id} → destroy() 삭제 +``` + +## 컨트롤러 + +### PayableController + +| 메서드 | HTTP | 설명 | +|--------|------|------| +| `index()` | GET | 미지급금 목록 (검색, 상태/카테고리 필터) | +| `store()` | POST | 미지급금 등록 | +| `update()` | PUT | 미지급금 수정 | +| `pay()` | POST | **지급 처리** (지급액 입력 → 상태 자동 변경) | +| `destroy()` | DELETE | 삭제 (Soft Delete) | + +### pay() 지급 처리 로직 + +``` +지급액 입력 + ↓ +paid_amount += 지급액 + ↓ +paid_amount >= amount ? + → YES: status = 'paid' (전액 지급) + → NO: status = 'partial' (부분 지급) +``` + +### index() 응답 구조 + +```json +{ + "success": true, + "data": [...], + "stats": { + "totalAmount": 30000000, + "paidAmount": 20000000, + "unpaidAmount": 10000000, + "overdueAmount": 3000000, + "count": 18 + } +} +``` + +## 모델 + +### Payable + +**테이블**: `payables` + +| 필드 | 타입 | 설명 | +|------|------|------| +| `tenant_id` | bigint | 테넌트 ID | +| `vendor_name` | string(100) | 공급업체명 | +| `invoice_no` | string(50) | 인보이스 번호 | +| `issue_date` | date | 발급일 | +| `due_date` | date | 만기일 | +| `category` | string(50) | 카테고리 | +| `amount` | bigint | 총액 | +| `paid_amount` | bigint | 지급액 | +| `status` | string | unpaid / partial / paid / overdue | +| `description` | string | 설명 | +| `memo` | text | 메모 | +| `tax_invoice_issued` | boolean | 세금계산서 발행 여부 | + +- SoftDeletes 적용 +- Scope: `forTenant($tenantId)` +- Index: `(tenant_id, status)`, `(tenant_id, due_date)` + +#### 상태 흐름 + +``` +unpaid (미지급) + ├── pay() (부분) → partial (부분 지급) + ├── pay() (전액) → paid (지급 완료) + └── (만기일 경과) → overdue (연체) +``` + +#### 카테고리 + +사무용품, 소프트웨어, 서비스, 시설, 장비, 외주, 기타 + +## 뷰 구성 (React) + +### payables.blade.php + +``` +┌─ 페이지 헤더 ────────────────────── +│ 제목: "미지급금관리" +│ [등록] 버튼 +│ +├─ 통계 카드 (5열) ────────────────── +│ 총액 | 지급액 | 미지급액 | 연체액 | 건수 +│ +├─ 필터 영역 ──────────────────────── +│ 검색 (공급업체명) | 상태 | 카테고리 +│ +├─ 미지급금 목록 테이블 ───────────── +│ 공급업체 | 인보이스 | 발급일 | 만기일 | 카테고리 | 금액 | 지급액 | 상태 | 세금계산서 | 작업 +│ └─ 상태: 미지급(노랑), 부분(파랑), 지급완료(초록), 연체(빨강) 배지 +│ └─ 세금계산서: 발행/미발행 표시 +│ └─ 작업: 지급처리, 수정, 삭제 +│ +├─ 등록/수정 모달 ─────────────────── +│ 공급업체명, 인보이스번호, 발급일, 만기일 +│ 카테고리, 금액, 설명, 세금계산서 발행 체크박스, 메모 +│ +└─ 지급 처리 모달 ─────────────────── + 현재 미지급액 표시, 지급액 입력 +``` + +## HTMX 호환성 + +- React 기반 페이지이므로 **HX-Redirect 필요** +- `@push('scripts')` 블록에 React/Babel 스크립트 포함 diff --git a/features/crm/receivables.md b/features/crm/receivables.md new file mode 100644 index 0000000..bbd5cb4 --- /dev/null +++ b/features/crm/receivables.md @@ -0,0 +1,179 @@ +# 미수금관리 + +## 개요 + +미수금관리는 고객별 채권 현황을 추적하고 수금 처리를 관리하는 기능입니다. +인보이스별 미수금 등록, 부분/전액 수금 처리, 연체 추적, 통계 기능을 제공합니다. + +- **라우트**: `GET /finance/receivables` +- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링) + +## 파일 구조 + +``` +mng/ +├── app/Http/Controllers/Finance/ +│ └── ReceivableController.php # MNG 컨트롤러 (5개 메서드) +├── app/Models/Finance/ +│ └── Receivable.php # 미수금 모델 +└── resources/views/finance/ + └── receivables.blade.php # React 기반 단일 페이지 + +api/ +├── app/Http/Controllers/Api/V1/ +│ └── ReceivablesController.php # API 컨트롤러 (월별 채권 현황) +├── app/Services/ +│ └── ReceivablesService.php # 비즈니스 로직 서비스 +└── database/migrations/ + └── 2026_02_04_222005_create_receivables_table.php +``` + +## 라우트 + +### MNG 라우트 + +```php +// routes/web.php (finance prefix 그룹 내) +GET /receivables → 페이지 렌더링 (HX-Redirect) +GET /receivables/list → index() 목록 + 통계 (JSON) +POST /receivables/store → store() 등록 +PUT /receivables/{id} → update() 수정 +POST /receivables/{id}/collect → collect() 수금 처리 +DELETE /receivables/{id} → destroy() 삭제 +``` + +### API 라우트 + +```php +// routes/api.php (v1/receivables prefix) +GET / → index() 거래처별 월별 채권 현황 +GET /summary → summary() 채권 요약 통계 +POST /update-overdue → updateOverdueStatus() 연체 상태 일괄 갱신 +POST /update-memos → updateMemos() 메모 일괄 수정 +``` + +## 컨트롤러 + +### ReceivableController (MNG) + +| 메서드 | HTTP | 설명 | +|--------|------|------| +| `index()` | GET | 미수금 목록 (검색, 상태/카테고리 필터) | +| `store()` | POST | 미수금 등록 | +| `update()` | PUT | 미수금 수정 | +| `collect()` | POST | **수금 처리** (수금액 입력 → 상태 자동 변경) | +| `destroy()` | DELETE | 삭제 (Soft Delete) | + +### collect() 수금 처리 로직 + +``` +수금액 입력 + ↓ +collected_amount += 수금액 + ↓ +collected_amount >= amount ? + → YES: status = 'collected' (전액 수금) + → NO: status = 'partial' (부분 수금) +``` + +### index() 응답 구조 + +```json +{ + "success": true, + "data": [...], + "stats": { + "totalAmount": 50000000, + "collectedAmount": 30000000, + "outstandingAmount": 20000000, + "overdueAmount": 5000000, + "count": 25 + } +} +``` + +## 서비스 클래스 (API) + +### ReceivablesService + +거래처별 월별 채권 현황을 제공하는 서비스: + +| 메서드 | 설명 | +|--------|------| +| `index(params)` | 거래처별 월별 매출/입금/어음/미수금 현황 | +| `summary(params)` | 채권 요약 통계 | +| `getCarryForwardBalance()` | 이월잔액 계산 | +| `getSalesByPeriods()` | 기간별 매출 조회 | +| `getDepositsByPeriods()` | 기간별 입금 조회 | +| `getBillsByPeriods()` | 기간별 어음 조회 | +| `calculateCumulativeReceivables()` | 누적 미수금 계산 | + +## 모델 + +### Receivable + +**테이블**: `receivables` + +| 필드 | 타입 | 설명 | +|------|------|------| +| `tenant_id` | bigint | 테넌트 ID | +| `customer_name` | string(100) | 고객명 | +| `invoice_no` | string(50) | 인보이스 번호 | +| `issue_date` | date | 발급일 | +| `due_date` | date | 만기일 | +| `category` | string(50) | 카테고리 | +| `amount` | bigint | 총액 | +| `collected_amount` | bigint | 수금액 | +| `status` | string | outstanding / partial / collected / overdue | +| `description` | string | 설명 | +| `memo` | text | 메모 | + +- SoftDeletes 적용 +- Scope: `forTenant($tenantId)` +- Index: `(tenant_id, status)`, `(tenant_id, due_date)` + +#### 상태 흐름 + +``` +outstanding (미수금) + ├── collect() (부분) → partial (부분 수금) + ├── collect() (전액) → collected (수금 완료) + └── (만기일 경과) → overdue (연체) +``` + +#### 카테고리 + +서비스, 상품, 컨설팅, 기타 + +## 뷰 구성 (React) + +### receivables.blade.php + +``` +┌─ 페이지 헤더 ────────────────────── +│ 제목: "미수금관리" +│ [등록] 버튼 +│ +├─ 통계 카드 (5열) ────────────────── +│ 총액 | 수금액 | 미수금액 | 연체액 | 건수 +│ +├─ 필터 영역 ──────────────────────── +│ 검색 (고객명, 인보이스번호) | 상태 | 카테고리 +│ +├─ 미수금 목록 테이블 ─────────────── +│ 고객명 | 인보이스 | 발급일 | 만기일 | 카테고리 | 금액 | 수금액 | 상태 | 작업 +│ └─ 상태: 미수금(노랑), 부분(파랑), 수금완료(초록), 연체(빨강) 배지 +│ └─ 작업: 수금처리, 수정, 삭제 +│ +├─ 등록/수정 모달 ─────────────────── +│ 고객명, 인보이스번호, 발급일, 만기일 +│ 카테고리, 금액, 설명, 메모 +│ +└─ 수금 처리 모달 ─────────────────── + 현재 미수금액 표시, 수금액 입력 +``` + +## HTMX 호환성 + +- React 기반 페이지이므로 **HX-Redirect 필요** +- `@push('scripts')` 블록에 React/Babel 스크립트 포함 diff --git a/features/crm/refunds.md b/features/crm/refunds.md new file mode 100644 index 0000000..7823603 --- /dev/null +++ b/features/crm/refunds.md @@ -0,0 +1,166 @@ +# 환불/해지관리 + +## 개요 + +환불/해지관리는 고객의 환불 또는 해지 요청을 접수하고 승인 프로세스를 관리하는 기능입니다. +요청 등록, 사유 분류, 승인/거절 워크플로우, 환불액 추적을 지원합니다. + +- **라우트**: `GET /finance/refunds` +- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링) + +## 파일 구조 + +``` +mng/ +├── app/Http/Controllers/Finance/ +│ └── RefundController.php # 메인 컨트롤러 (5개 메서드) +├── app/Models/Finance/ +│ └── Refund.php # 환불/해지 모델 +└── resources/views/finance/ + └── refunds.blade.php # React 기반 단일 페이지 + +api/ +└── database/migrations/ + └── 2026_02_04_223406_create_refunds_table.php +``` + +## 라우트 + +```php +// routes/web.php (finance prefix 그룹 내) +GET /refunds → 페이지 렌더링 (HX-Redirect) +GET /refunds/list → index() 목록 + 통계 (JSON) +POST /refunds/store → store() 요청 등록 +PUT /refunds/{id} → update() 요청 수정 +POST /refunds/{id}/process → process() 요청 처리 (승인/완료/거절) +DELETE /refunds/{id} → destroy() 삭제 +``` + +## 컨트롤러 + +### RefundController + +| 메서드 | HTTP | 설명 | +|--------|------|------| +| `index()` | GET | 목록 (검색, 상태/타입 필터) | +| `store()` | POST | 환불/해지 요청 등록 | +| `update()` | PUT | 요청 수정 | +| `process()` | POST | **요청 처리** (approved/completed/rejected) | +| `destroy()` | DELETE | 삭제 (Soft Delete) | + +### process() 처리 로직 + +``` +POST /refunds/{id}/process +{ + "action": "approved" | "completed" | "rejected", + "refundAmount": 500000, // (완료 시) 실제 환불액 + "note": "처리 비고" +} + ↓ +status 변경 + process_date 기록 +``` + +### index() 응답 구조 + +```json +{ + "success": true, + "data": [...], + "stats": { + "pendingCount": 5, + "completedCount": 20, + "rejectedCount": 3, + "totalRefundAmount": 15000000 + } +} +``` + +## 모델 + +### Refund + +**테이블**: `refunds` + +| 필드 | 타입 | 설명 | +|------|------|------| +| `tenant_id` | bigint | 테넌트 ID | +| `type` | string | **refund**(환불) / **cancel**(해지) | +| `customer_name` | string(100) | 고객명 | +| `request_date` | date | 요청일 | +| `product_name` | string(100) | 상품명 | +| `original_amount` | bigint | 원금액 | +| `refund_amount` | bigint | 환불금액 | +| `reason` | string(100) | 사유 | +| `status` | string | pending / approved / completed / rejected | +| `process_date` | date | 처리일 | +| `note` | text | 비고 | + +- SoftDeletes 적용 +- Scope: `forTenant($tenantId)` +- Index: `(tenant_id, status)`, `(tenant_id, type)` + +#### 요청 타입 + +| 타입 | 설명 | +|------|------| +| `refund` | 환불 (금액 반환) | +| `cancel` | 해지 (서비스 종료) | + +#### 상태 흐름 + +``` +pending (대기) + ├── process(approved) → approved (승인) + │ ↓ + │ process(completed) → completed (완료) + 환불액/처리일 기록 + │ + └── process(rejected) → rejected (거절) + 처리일 기록 +``` + +#### 사유 목록 + +| 사유 | 설명 | +|------|------| +| 서비스 불만족 | 서비스 품질 관련 | +| 결제 오류 | 잘못된 결제 | +| 사업 종료 | 고객 사업 종료 | +| 경쟁사 이전 | 타사 이전 | +| 중복 결제 | 이중 결제 | +| 기타 | 기타 사유 | + +## 뷰 구성 (React) + +### refunds.blade.php + +``` +┌─ 페이지 헤더 ────────────────────── +│ 제목: "환불/해지관리" +│ [등록] 버튼 +│ +├─ 통계 카드 (4열) ────────────────── +│ 대기 | 완료 | 거절 | 총 환불액 +│ +├─ 필터 영역 ──────────────────────── +│ 검색 (고객명, 상품명) | 상태 (전체/대기/승인/완료/거절) | 타입 (환불/해지) +│ +├─ 요청 목록 테이블 ───────────────── +│ 타입 | 고객명 | 요청일 | 상품명 | 원금 | 환불액 | 사유 | 상태 | 처리일 | 작업 +│ └─ 타입: 환불(빨강), 해지(주황) 배지 +│ └─ 상태: 대기(노랑), 승인(파랑), 완료(초록), 거절(빨강) 배지 +│ └─ 작업: 처리, 수정, 삭제 +│ +├─ 등록/수정 모달 ─────────────────── +│ 타입(환불/해지), 고객명, 요청일, 상품명 +│ 원금액, 환불금액, 사유(드롭다운), 비고 +│ +└─ 처리 모달 ──────────────────────── + 요청 정보 표시 + 액션 선택: 승인 | 완료 | 거절 + 환불액 (완료 시), 비고 +``` + +## HTMX 호환성 + +- React 기반 페이지이므로 **HX-Redirect 필요** +- `@push('scripts')` 블록에 React/Babel 스크립트 포함 diff --git a/features/crm/trading-partners.md b/features/crm/trading-partners.md new file mode 100644 index 0000000..4a7b806 --- /dev/null +++ b/features/crm/trading-partners.md @@ -0,0 +1,150 @@ +# 거래처관리 + +## 개요 + +거래처관리는 회사의 거래처(업체/프리랜서)를 등록하고 관리하는 기능입니다. +업종별 분류, 사업자번호/계좌 관리, OCR 명함 인식을 지원합니다. + +- **라우트**: `GET /finance/partners` +- **라우트 이름**: `finance.partners` +- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링) + +## 파일 구조 + +``` +mng/ +├── app/Http/Controllers/Finance/ +│ └── TradingPartnerController.php # 메인 컨트롤러 (5개 메서드) +├── app/Models/Finance/ +│ └── TradingPartner.php # 거래처 모델 +├── app/Services/ +│ └── TradingPartnerOcrService.php # OCR 명함 인식 서비스 +└── resources/views/finance/ + └── partners.blade.php # React 기반 단일 페이지 + +api/ +└── database/migrations/ + └── 2026_02_04_221050_create_trading_partners_table.php +``` + +## 라우트 + +```php +// routes/web.php (finance prefix 그룹 내) +GET /partners → 페이지 렌더링 (HX-Redirect) + +// API 라우트 (partners prefix) +GET /partners/list → index() 거래처 목록 (JSON) +POST /partners/store → store() 거래처 등록 +POST /partners/ocr → ocr() OCR 명함 인식 +PUT /partners/{id} → update() 거래처 수정 +DELETE /partners/{id} → destroy() 거래처 삭제 +``` + +## 컨트롤러 + +### TradingPartnerController + +| 메서드 | HTTP | 설명 | +|--------|------|------| +| `index()` | GET | 거래처 목록 (검색, 타입/카테고리/상태 필터) | +| `store()` | POST | 거래처 등록 (name, type, category 필수) | +| `update()` | PUT | 거래처 수정 | +| `ocr()` | POST | **OCR 명함 인식** (이미지 → 거래처 정보 추출) | +| `destroy()` | DELETE | 거래처 삭제 (Soft Delete) | + +### index() 응답 구조 + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "name": "ABC 솔루션", + "type": "vendor", + "category": "IT/소프트웨어", + "bizNo": "123-45-67890", + "bankAccount": "우리은행 1002-xxx-xxxxx", + "contact": "02-1234-5678", + "email": "info@abc.co.kr", + "manager": "김담당", + "managerPhone": "010-1234-5678", + "status": "active", + "memo": "" + } + ], + "stats": { + "total": 50, + "vendor": 35, + "freelancer": 15, + "active": 42 + } +} +``` + +## 모델 + +### TradingPartner + +**테이블**: `trading_partners` + +| 필드 | 타입 | 설명 | +|------|------|------| +| `tenant_id` | bigint | 테넌트 ID | +| `name` | string(100) | 거래처명 | +| `type` | string | **vendor**(업체) / **freelancer**(프리랜서) | +| `category` | string(50) | 업종 카테고리 | +| `biz_no` | string | 사업자번호 | +| `bank_account` | string | 계좌 정보 | +| `contact` | string | 연락처 | +| `email` | string | 이메일 | +| `manager` | string | 담당자명 | +| `manager_phone` | string | 담당자 연락처 | +| `status` | string | active / inactive | +| `memo` | text | 메모 | + +- SoftDeletes 적용 +- Scope: `active()`, `forTenant($tenantId)` + +## 뷰 구성 (React) + +### partners.blade.php + +``` +┌─ 페이지 헤더 ────────────────────── +│ 제목: "거래처관리" +│ [CSV 내보내기] [OCR 등록] [등록] 버튼 +│ +├─ 통계 카드 (4열) ────────────────── +│ 전체 | 업체 | 프리랜서 | 활성 +│ +├─ 필터 영역 ──────────────────────── +│ 검색 (거래처명, 담당자) | 타입 (업체/프리랜서) | 카테고리 | 상태 +│ +├─ 거래처 목록 테이블 ─────────────── +│ 거래처명 | 타입 | 카테고리 | 사업자번호 | 계좌 | 담당자 | 상태 | 작업 +│ └─ 타입: 업체(파랑), 프리랜서(보라) 배지 +│ +├─ 등록/수정 모달 ─────────────────── +│ 거래처명, 타입(업체/프리랜서), 카테고리 +│ 사업자번호, 계좌정보, 연락처, 이메일 +│ 담당자, 담당자 연락처, 상태, 메모 +│ +└─ OCR 모달 ───────────────────────── + 명함 이미지 업로드 → AI 인식 → 자동 필드 채우기 +``` + +## OCR 명함 인식 + +### TradingPartnerOcrService + +명함 이미지를 Claude Vision API로 분석하여 거래처 정보를 자동 추출합니다: +- 이미지(Base64) → Claude Vision API 호출 +- 회사명, 담당자명, 연락처, 이메일, 주소 등 추출 +- 추출 결과를 등록 폼에 자동 입력 + +## HTMX 호환성 + +- React 기반 페이지이므로 **HX-Redirect 필요** +- `@push('scripts')` 블록에 React/Babel 스크립트 포함