149 lines
4.1 KiB
Markdown
149 lines
4.1 KiB
Markdown
|
|
# 컨설팅비용정산
|
|||
|
|
|
|||
|
|
## 개요
|
|||
|
|
|
|||
|
|
컨설팅비용정산은 컨설턴트별 상담수수료를 기록하고 관리하는 기능입니다.
|
|||
|
|
상담 시간과 시급 기반의 정산액 계산, 지급 상태 관리, 통계 기능을 제공합니다.
|
|||
|
|
|
|||
|
|
- **라우트**: `GET /finance/consulting-fee`
|
|||
|
|
- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링)
|
|||
|
|
|
|||
|
|
## 파일 구조
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
mng/
|
|||
|
|
├── app/Http/Controllers/Finance/
|
|||
|
|
│ └── ConsultingFeeController.php # 메인 컨트롤러 (4개 메서드)
|
|||
|
|
├── app/Models/Finance/
|
|||
|
|
│ └── ConsultingFee.php # 상담수수료 모델
|
|||
|
|
└── resources/views/finance/
|
|||
|
|
└── consulting-fee.blade.php # React 기반 단일 페이지
|
|||
|
|
|
|||
|
|
api/
|
|||
|
|
└── database/migrations/
|
|||
|
|
└── 2026_02_04_230006_create_consulting_fees_table.php
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 라우트
|
|||
|
|
|
|||
|
|
```php
|
|||
|
|
// routes/web.php (finance prefix 그룹 내)
|
|||
|
|
GET /consulting-fee → Blade 페이지 렌더링 (HX-Redirect)
|
|||
|
|
|
|||
|
|
// API 라우트 (consulting-fees prefix)
|
|||
|
|
GET /consulting-fees/list → index() 목록 + 통계 (JSON)
|
|||
|
|
POST /consulting-fees/store → store() 등록
|
|||
|
|
PUT /consulting-fees/{id} → update() 수정
|
|||
|
|
DELETE /consulting-fees/{id} → destroy() 삭제
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 컨트롤러
|
|||
|
|
|
|||
|
|
### ConsultingFeeController
|
|||
|
|
|
|||
|
|
| 메서드 | HTTP | 설명 |
|
|||
|
|
|--------|------|------|
|
|||
|
|
| `index()` | GET | 목록 + 통계 (검색, 상태 필터) |
|
|||
|
|
| `store()` | POST | 상담수수료 등록 |
|
|||
|
|
| `update()` | PUT | 수정 |
|
|||
|
|
| `destroy()` | DELETE | 삭제 (Soft Delete) |
|
|||
|
|
|
|||
|
|
### index() 응답 구조
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"data": [
|
|||
|
|
{
|
|||
|
|
"id": 1,
|
|||
|
|
"date": "2026-02-10",
|
|||
|
|
"consultant": "김컨설턴트",
|
|||
|
|
"customer": "A사",
|
|||
|
|
"service": "기술 컨설팅",
|
|||
|
|
"hours": 4,
|
|||
|
|
"hourlyRate": 150000,
|
|||
|
|
"amount": 600000,
|
|||
|
|
"status": "pending",
|
|||
|
|
"memo": ""
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"stats": {
|
|||
|
|
"totalAmount": 3500000,
|
|||
|
|
"paidAmount": 2000000,
|
|||
|
|
"pendingAmount": 1500000,
|
|||
|
|
"totalHours": 28
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 핵심 로직
|
|||
|
|
|
|||
|
|
### 정산액 계산
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
정산액(amount) = 상담시간(hours) × 시급(hourly_rate)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 상태 관리
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
pending (대기) → paid (지급완료)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 모델
|
|||
|
|
|
|||
|
|
### ConsultingFee
|
|||
|
|
|
|||
|
|
**테이블**: `consulting_fees`
|
|||
|
|
|
|||
|
|
| 필드 | 타입 | 설명 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| `tenant_id` | bigint | 테넌트 ID |
|
|||
|
|
| `date` | date | 상담일 |
|
|||
|
|
| `consultant` | string(50) | 컨설턴트명 |
|
|||
|
|
| `customer` | string(100) | 고객사명 |
|
|||
|
|
| `service` | string(50) | 서비스 유형 (기본: '기술 컨설팅') |
|
|||
|
|
| `hours` | int | 상담 시간 |
|
|||
|
|
| `hourly_rate` | int | 시급 |
|
|||
|
|
| `amount` | bigint | 정산액 |
|
|||
|
|
| `status` | string(20) | pending / paid |
|
|||
|
|
| `memo` | text | 메모 |
|
|||
|
|
|
|||
|
|
- SoftDeletes 적용
|
|||
|
|
- Scope: `forTenant($tenantId)`
|
|||
|
|
|
|||
|
|
## 뷰 구성 (React)
|
|||
|
|
|
|||
|
|
### consulting-fee.blade.php
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─ 페이지 헤더 ──────────────────────
|
|||
|
|
│ 제목: "컨설팅비용정산"
|
|||
|
|
│ [CSV 내보내기] [등록] 버튼
|
|||
|
|
│
|
|||
|
|
├─ 통계 카드 (4열) ──────────────────
|
|||
|
|
│ 총 상담시간 | 총 정산액 | 지급완료 | 미지급
|
|||
|
|
│
|
|||
|
|
├─ 필터 영역 ────────────────────────
|
|||
|
|
│ 검색 (컨설턴트/고객사) | 컨설턴트 필터 | 상태 필터
|
|||
|
|
│ 기간 선택 (시작일 ~ 종료일)
|
|||
|
|
│
|
|||
|
|
├─ 정산 목록 테이블 ─────────────────
|
|||
|
|
│ 날짜 | 컨설턴트 | 고객사 | 서비스 | 시간 | 시급 | 정산액 | 상태 | 작업
|
|||
|
|
│ └─ 상태: 대기(노랑), 지급완료(초록) 배지
|
|||
|
|
│ └─ 작업: 수정/삭제 버튼
|
|||
|
|
│
|
|||
|
|
├─ 등록/수정 모달 ───────────────────
|
|||
|
|
│ 상담일, 컨설턴트, 고객사, 서비스 유형
|
|||
|
|
│ 상담시간, 시급, 정산액 (자동 계산)
|
|||
|
|
│ 상태, 메모
|
|||
|
|
│ [삭제] [취소] [등록/저장]
|
|||
|
|
│
|
|||
|
|
└─ 비어있을 때: 안내 메시지
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## HTMX 호환성
|
|||
|
|
|
|||
|
|
- React 기반 페이지이므로 **HX-Redirect 필요**
|
|||
|
|
- `@push('scripts')` 블록에 React/Babel 스크립트 포함
|