docs:고객/거래처/채권관리 개발문서 추가 (5개 메뉴)
- 거래처관리: vendor/freelancer 타입, OCR 명함인식 - 고객사관리: VIP/Gold/Silver/Bronze 등급, 업종별 관리 - 미수금관리: 부분/전액 수금, 연체 추적, API 서비스 - 미지급금관리: 부분/전액 지급, 세금계산서 추적 - 환불/해지관리: 승인 워크플로우, refund/cancel 타입 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
81
features/crm/README.md
Normal file
81
features/crm/README.md
Normal file
@@ -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` | 환불/해지 요청 (타입, 사유, 처리상태) |
|
||||||
135
features/crm/customers.md
Normal file
135
features/crm/customers.md
Normal file
@@ -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 스크립트 포함
|
||||||
150
features/crm/payables.md
Normal file
150
features/crm/payables.md
Normal file
@@ -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 스크립트 포함
|
||||||
179
features/crm/receivables.md
Normal file
179
features/crm/receivables.md
Normal file
@@ -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 스크립트 포함
|
||||||
166
features/crm/refunds.md
Normal file
166
features/crm/refunds.md
Normal file
@@ -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 스크립트 포함
|
||||||
150
features/crm/trading-partners.md
Normal file
150
features/crm/trading-partners.md
Normal file
@@ -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 스크립트 포함
|
||||||
Reference in New Issue
Block a user