docs: Phase 1.1 카드 거래 대시보드 API 개발 완료
- 카드/가지급금 관리 섹션 계획 문서 추가 - 변경 이력 문서 추가 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
75
changes/20260122_card_transaction_dashboard_api.md
Normal file
75
changes/20260122_card_transaction_dashboard_api.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# 변경 내용 요약
|
||||
|
||||
**날짜:** 2026-01-22
|
||||
**작업자:** Claude Code
|
||||
**계획 문서:** docs/plans/card-management-section-plan.md
|
||||
**Phase:** 1.1 카드 거래 대시보드 API 개발
|
||||
|
||||
## 📋 변경 개요
|
||||
CEO 대시보드 카드/가지급금 관리 섹션(cm1)의 모달 팝업용 카드 거래 대시보드 API 엔드포인트 신규 추가.
|
||||
기존 summary API를 확장하여 월별 추이, 사용자별 비율, 최근 거래 목록을 포함한 상세 데이터 제공.
|
||||
|
||||
## 📁 수정된 파일
|
||||
- `api/app/Services/CardTransactionService.php` - dashboard() 메서드 및 헬퍼 메서드 추가
|
||||
- `api/app/Http/Controllers/Api/V1/CardTransactionController.php` - dashboard() 액션 추가
|
||||
- `api/routes/api.php` - /dashboard 라우트 등록
|
||||
- `api/app/Swagger/v1/CardTransactionApi.php` - 대시보드 스키마 및 엔드포인트 문서화
|
||||
|
||||
## 🔧 상세 변경 사항
|
||||
|
||||
### 1. CardTransactionService.php
|
||||
**신규 메서드:**
|
||||
- `dashboard()` - 대시보드 전체 데이터 반환
|
||||
- `getMonthTotal()` - 특정 기간 카드 사용액 합계 (private)
|
||||
- `getMonthlyTrend()` - 최근 N개월 월별 추이 (private)
|
||||
- `getUserRatio()` - 사용자별 카드 사용 비율 (private)
|
||||
- `getRecentTransactions()` - 최근 거래 목록 (private)
|
||||
|
||||
**응답 구조:**
|
||||
```php
|
||||
[
|
||||
'summary' => [
|
||||
'current_month_total' => float,
|
||||
'previous_month_total' => float,
|
||||
'change_rate' => float,
|
||||
'unprocessed_count' => int,
|
||||
],
|
||||
'monthly_trend' => [...],
|
||||
'user_ratio' => [...],
|
||||
'recent_transactions' => [...],
|
||||
]
|
||||
```
|
||||
|
||||
### 2. CardTransactionController.php
|
||||
**신규 액션:**
|
||||
```php
|
||||
public function dashboard(): JsonResponse
|
||||
```
|
||||
|
||||
### 3. api/routes/api.php
|
||||
**신규 라우트:**
|
||||
```php
|
||||
Route::get('/dashboard', [CardTransactionController::class, 'dashboard'])
|
||||
->name('v1.card-transactions.dashboard');
|
||||
```
|
||||
|
||||
### 4. CardTransactionApi.php (Swagger)
|
||||
**신규 스키마:**
|
||||
- `CardTransactionDashboard` - 대시보드 응답 전체 구조
|
||||
|
||||
**신규 엔드포인트:**
|
||||
- `GET /api/v1/card-transactions/dashboard`
|
||||
|
||||
## ✅ 테스트 체크리스트
|
||||
- [x] Pint 코드 스타일 검증 통과
|
||||
- [x] 라우트 등록 확인 (php artisan route:list)
|
||||
- [x] Swagger 문서 생성 완료
|
||||
- [ ] API 호출 테스트 (Swagger UI)
|
||||
- [ ] 프론트엔드 연동 테스트
|
||||
|
||||
## ⚠️ 배포 시 주의사항
|
||||
특이사항 없음 (DB 스키마 변경 없음)
|
||||
|
||||
## 🔗 관련 문서
|
||||
- 계획 문서: `docs/plans/card-management-section-plan.md`
|
||||
- 기존 API 문서: `api/app/Swagger/v1/CardTransactionApi.php`
|
||||
819
plans/card-management-section-plan.md
Normal file
819
plans/card-management-section-plan.md
Normal file
@@ -0,0 +1,819 @@
|
||||
# 카드/가지급금 관리 섹션 데이터 연동 계획
|
||||
|
||||
> **작성일**: 2026-01-22
|
||||
> **목적**: CEO 대시보드 카드/가지급금 관리 섹션의 4개 카드 데이터 연동 및 모달 팝업 내용 개발
|
||||
> **기준 문서**: `cardManagementConfigs.ts`, `LoanApi.php`, `CardTransactionApi.php`
|
||||
> **상태**: 🔄 진행중 (Serena ID: card-management-plan-state)
|
||||
|
||||
---
|
||||
|
||||
## 📍 현재 진행 상태
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **마지막 완료 작업** | Phase 1.1 카드 거래 대시보드 API 개발 완료 |
|
||||
| **다음 작업** | Phase 1.2 가지급금 대시보드 API 개발 |
|
||||
| **진행률** | 1/12 (8%) |
|
||||
| **마지막 업데이트** | 2026-01-22 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 배경
|
||||
CEO 대시보드의 카드/가지급금 관리 섹션은 4개의 카드로 구성되어 있으며, 현재 목업 데이터를 사용 중입니다.
|
||||
각 카드 클릭 시 표시되는 모달 팝업도 하드코딩된 목업 데이터를 사용하고 있어 실제 API 연동이 필요합니다.
|
||||
|
||||
**4개 카드 구성:**
|
||||
- **cm1**: 카드 (당월 카드 사용액)
|
||||
- **cm2**: 가지급금 (미정산 가지급금)
|
||||
- **cm3**: 법인세 예상 가중 (가지급금으로 인한 법인세 추가)
|
||||
- **cm4**: 대표자 종합세 예상 가중 (가지급금으로 인한 종합소득세 추가)
|
||||
|
||||
### 1.2 기준 원칙
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 🎯 핵심 원칙 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ - 기존 API 최대 활용, 신규 API 최소화 │
|
||||
│ - 대시보드 전용 엔드포인트는 /dashboard 하위에 구성 │
|
||||
│ - 모달 데이터는 lazy loading (모달 열릴 때 호출) │
|
||||
│ - 에러 시 graceful degradation (목업 데이터 fallback) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.3 변경 승인 정책
|
||||
|
||||
| 분류 | 예시 | 승인 |
|
||||
|------|------|------|
|
||||
| ✅ 즉시 가능 | API 응답 필드 추가, 프론트엔드 타입 추가 | 불필요 |
|
||||
| ⚠️ 컨펌 필요 | 신규 API 엔드포인트, 서비스 로직 변경 | **필수** |
|
||||
| 🔴 금지 | DB 스키마 변경, 기존 API 응답 형식 변경 | 별도 협의 |
|
||||
|
||||
### 1.4 준수 규칙
|
||||
- `docs/quickstart/quick-start.md` - 빠른 시작 가이드
|
||||
- `docs/standards/quality-checklist.md` - 품질 체크리스트
|
||||
- `api/CLAUDE.md` - SAM API Development Rules
|
||||
|
||||
---
|
||||
|
||||
## 2. 기존 API 현황 분석
|
||||
|
||||
### 2.1 CardTransaction API (카드 거래)
|
||||
|
||||
| 엔드포인트 | 설명 | 모달 활용 |
|
||||
|-----------|------|----------|
|
||||
| `GET /api/v1/card-transactions` | 카드 거래 목록 | cm1 테이블 |
|
||||
| `GET /api/v1/card-transactions/summary` | 전월/당월 요약 | cm1 summaryCards |
|
||||
| `GET /api/v1/card-transactions/{id}` | 상세 조회 | - |
|
||||
|
||||
**summary 응답 구조:**
|
||||
```json
|
||||
{
|
||||
"previous_month_total": 1500000,
|
||||
"current_month_total": 850000,
|
||||
"total_count": 45,
|
||||
"total_amount": 2350000
|
||||
}
|
||||
```
|
||||
|
||||
**🔴 부족한 데이터:**
|
||||
- 월별 추이 데이터 (barChart용)
|
||||
- 사용자별/카드별 비율 데이터 (pieChart용)
|
||||
|
||||
### 2.2 Loan API (가지급금)
|
||||
|
||||
| 엔드포인트 | 설명 | 모달 활용 |
|
||||
|-----------|------|----------|
|
||||
| `GET /api/v1/loans` | 가지급금 목록 | cm2 테이블 |
|
||||
| `GET /api/v1/loans/summary` | 가지급금 요약 | cm2 summaryCards |
|
||||
| `POST /api/v1/loans/calculate-interest` | 인정이자 계산 | cm2, cm3, cm4 |
|
||||
| `GET /api/v1/loans/interest-report/{year}` | 연간 리포트 | cm3, cm4 |
|
||||
|
||||
**summary 응답 구조:**
|
||||
```json
|
||||
{
|
||||
"total_count": 10,
|
||||
"outstanding_count": 5,
|
||||
"settled_count": 3,
|
||||
"partial_count": 2,
|
||||
"total_amount": 50000000,
|
||||
"total_settled": 30000000,
|
||||
"total_outstanding": 20000000
|
||||
}
|
||||
```
|
||||
|
||||
**calculate-interest 응답 구조:**
|
||||
```json
|
||||
{
|
||||
"year": 2026,
|
||||
"interest_rate": 4.6,
|
||||
"summary": {
|
||||
"total_balance": 50000000,
|
||||
"total_recognized_interest": 2300000,
|
||||
"total_corporate_tax": 437000,
|
||||
"total_income_tax": 805000,
|
||||
"total_local_tax": 80500,
|
||||
"total_tax": 1322500
|
||||
},
|
||||
"details": [...]
|
||||
}
|
||||
```
|
||||
|
||||
**🔴 부족한 데이터:**
|
||||
- 법인세 비교 (가지급금 없을 때 vs 있을 때)
|
||||
- 종합소득세 비교 (가지급금 없을 때 vs 있을 때)
|
||||
|
||||
---
|
||||
|
||||
## 3. 대상 범위
|
||||
|
||||
### 3.1 Phase 1: API 개발 (Backend)
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 1.1 | 카드 거래 대시보드 API 개발 | ✅ | 월별 추이, 사용자별 비율 |
|
||||
| 1.2 | 가지급금 대시보드 API 개발 | ⏳ | 대시보드 요약 + 목록 |
|
||||
| 1.3 | 세금 시뮬레이션 API 개발 | ⏳ | 법인세/종합소득세 비교 |
|
||||
|
||||
### 3.2 Phase 2: 프론트엔드 타입 및 API 연동
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 2.1 | API 타입 정의 추가 | ⏳ | `lib/api/dashboard/types.ts` |
|
||||
| 2.2 | API 엔드포인트 함수 추가 | ⏳ | `lib/api/dashboard/endpoints.ts` |
|
||||
| 2.3 | 모달 데이터 훅 생성 | ⏳ | `useCardManagementModals.ts` |
|
||||
|
||||
### 3.3 Phase 3: 모달 컴포넌트 연동
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 3.1 | cm1 카드 모달 데이터 연동 | ⏳ | 카드 사용 상세 |
|
||||
| 3.2 | cm2 가지급금 모달 데이터 연동 | ⏳ | 가지급금 상세 |
|
||||
| 3.3 | cm3 법인세 모달 데이터 연동 | ⏳ | 법인세 예상 가중 상세 |
|
||||
| 3.4 | cm4 종합소득세 모달 데이터 연동 | ⏳ | 대표자 종합소득세 상세 |
|
||||
|
||||
### 3.4 Phase 4: 카드 데이터 연동 및 테스트
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 4.1 | 4개 카드 데이터 연동 | ⏳ | 섹션 카드 표시 |
|
||||
| 4.2 | 에러 핸들링 및 fallback | ⏳ | graceful degradation |
|
||||
|
||||
---
|
||||
|
||||
## 4. 상세 작업 내용
|
||||
|
||||
### 4.1 Phase 1: API 개발
|
||||
|
||||
#### 1.1 카드 거래 대시보드 API
|
||||
|
||||
**파일**: `api/app/Http/Controllers/Api/V1/CardTransactionController.php`
|
||||
|
||||
**신규 엔드포인트:**
|
||||
```
|
||||
GET /api/v1/card-transactions/dashboard
|
||||
```
|
||||
|
||||
**응답 구조:**
|
||||
```typescript
|
||||
interface CardTransactionDashboardResponse {
|
||||
summary: {
|
||||
current_month_total: number; // 당월 카드 사용액
|
||||
previous_month_total: number; // 전월 카드 사용액
|
||||
change_rate: number; // 전월 대비 증감률 (%)
|
||||
unprocessed_count: number; // 미정리 건수
|
||||
};
|
||||
monthly_trend: Array<{ // 최근 6개월 추이
|
||||
month: string; // "2026-01"
|
||||
amount: number;
|
||||
}>;
|
||||
user_ratio: Array<{ // 사용자별 비율
|
||||
user_name: string;
|
||||
amount: number;
|
||||
percentage: number;
|
||||
}>;
|
||||
recent_transactions: Array<{ // 최근 거래 (10건)
|
||||
id: number;
|
||||
card_name: string;
|
||||
user_name: string;
|
||||
used_at: string;
|
||||
merchant_name: string;
|
||||
amount: number;
|
||||
usage_type: string | null; // 계정과목
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2 가지급금 대시보드 API
|
||||
|
||||
**파일**: `api/app/Http/Controllers/Api/V1/LoanController.php`
|
||||
|
||||
**신규 엔드포인트:**
|
||||
```
|
||||
GET /api/v1/loans/dashboard
|
||||
```
|
||||
|
||||
**응답 구조:**
|
||||
```typescript
|
||||
interface LoanDashboardResponse {
|
||||
summary: {
|
||||
total_outstanding: number; // 미정산 가지급금 총액
|
||||
recognized_interest: number; // 인정이자 (연 4.6%)
|
||||
outstanding_count: number; // 미정산 건수
|
||||
};
|
||||
loans: Array<{ // 가지급금 목록
|
||||
id: number;
|
||||
loan_date: string;
|
||||
user_name: string;
|
||||
category: string; // 카드/계좌
|
||||
amount: number;
|
||||
status: string;
|
||||
content: string;
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3 세금 시뮬레이션 API
|
||||
|
||||
**파일**: `api/app/Http/Controllers/Api/V1/LoanController.php`
|
||||
|
||||
**신규 엔드포인트:**
|
||||
```
|
||||
GET /api/v1/loans/tax-simulation?year={year}
|
||||
```
|
||||
|
||||
**응답 구조:**
|
||||
```typescript
|
||||
interface TaxSimulationResponse {
|
||||
year: number;
|
||||
loan_summary: {
|
||||
total_outstanding: number; // 가지급금 잔액
|
||||
recognized_interest: number; // 인정이자
|
||||
interest_rate: number; // 이자율 (4.6%)
|
||||
};
|
||||
corporate_tax: { // 법인세
|
||||
without_loan: { // 가지급금 없을 때
|
||||
taxable_income: number; // 과세표준
|
||||
tax_amount: number; // 법인세액
|
||||
};
|
||||
with_loan: { // 가지급금 있을 때
|
||||
taxable_income: number;
|
||||
tax_amount: number;
|
||||
};
|
||||
difference: number; // 차이 (가중액)
|
||||
rate_info: string; // 적용 세율 정보
|
||||
};
|
||||
income_tax: { // 종합소득세
|
||||
without_loan: {
|
||||
taxable_income: number;
|
||||
tax_rate: string;
|
||||
tax_amount: number;
|
||||
};
|
||||
with_loan: {
|
||||
taxable_income: number;
|
||||
tax_rate: string;
|
||||
tax_amount: number;
|
||||
};
|
||||
difference: number;
|
||||
breakdown: { // 세부 내역
|
||||
income_tax: number;
|
||||
local_tax: number;
|
||||
insurance: number; // 4대보험
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 Phase 2: 프론트엔드 타입 및 API 연동
|
||||
|
||||
#### 2.1 API 타입 정의
|
||||
|
||||
**파일**: `react/src/lib/api/dashboard/types.ts`
|
||||
|
||||
추가할 타입:
|
||||
- `CardTransactionDashboardApiResponse`
|
||||
- `LoanDashboardApiResponse`
|
||||
- `TaxSimulationApiResponse`
|
||||
|
||||
#### 2.2 API 엔드포인트 함수
|
||||
|
||||
**파일**: `react/src/lib/api/dashboard/endpoints.ts`
|
||||
|
||||
추가할 함수:
|
||||
- `fetchCardTransactionDashboard()`
|
||||
- `fetchLoanDashboard()`
|
||||
- `fetchTaxSimulation(year: number)`
|
||||
|
||||
#### 2.3 모달 데이터 훅
|
||||
|
||||
**파일**: `react/src/hooks/useCardManagementModals.ts`
|
||||
|
||||
```typescript
|
||||
interface UseCardManagementModalsReturn {
|
||||
cm1Data: CardTransactionDashboardData | null;
|
||||
cm2Data: LoanDashboardData | null;
|
||||
cm3Data: TaxSimulationData | null;
|
||||
cm4Data: TaxSimulationData | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
fetchModalData: (cardId: string) => Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Phase 3: 모달 컴포넌트 연동
|
||||
|
||||
**파일**: `react/src/components/business/CEODashboard/modalConfigs/cardManagementConfigs.ts`
|
||||
|
||||
현재 하드코딩된 데이터를 API 데이터로 대체:
|
||||
- `summaryCards`: API 응답에서 동적 생성
|
||||
- `barChart.data`: `monthly_trend` 데이터 매핑
|
||||
- `pieChart.data`: `user_ratio` 데이터 매핑
|
||||
- `table.data`: API 목록 데이터 매핑
|
||||
- `comparisonSection`: 세금 시뮬레이션 데이터 매핑
|
||||
|
||||
### 4.4 Phase 4: 카드 데이터 연동
|
||||
|
||||
**파일**: `react/src/lib/api/dashboard/transformers.ts`
|
||||
|
||||
`transformCardManagementResponse` 함수 수정:
|
||||
- cm1: `CardTransactionSummary` 활용 (기존)
|
||||
- cm2: `LoanSummary` 활용
|
||||
- cm3: `TaxSimulation.corporate_tax.difference` 활용
|
||||
- cm4: `TaxSimulation.income_tax.difference` 활용
|
||||
|
||||
---
|
||||
|
||||
## 5. 컨펌 대기 목록
|
||||
|
||||
| # | 항목 | 변경 내용 | 영향 범위 | 상태 |
|
||||
|---|------|----------|----------|------|
|
||||
| 1 | 카드 거래 대시보드 API | 신규 엔드포인트 추가 | API 프로젝트 | ⏳ |
|
||||
| 2 | 가지급금 대시보드 API | 신규 엔드포인트 추가 | API 프로젝트 | ⏳ |
|
||||
| 3 | 세금 시뮬레이션 API | 신규 엔드포인트 추가 | API 프로젝트 | ⏳ |
|
||||
|
||||
---
|
||||
|
||||
## 6. 변경 이력
|
||||
|
||||
| 날짜 | 항목 | 변경 내용 | 파일 | 승인 |
|
||||
|------|------|----------|------|------|
|
||||
| 2026-01-22 | - | 문서 초안 작성 | - | - |
|
||||
|
||||
---
|
||||
|
||||
## 7. 참고 문서
|
||||
|
||||
- **빠른 시작**: `docs/quickstart/quick-start.md`
|
||||
- **품질 체크리스트**: `docs/standards/quality-checklist.md`
|
||||
- **API 규칙**: `api/CLAUDE.md`
|
||||
- **Loan Swagger**: `api/app/Swagger/v1/LoanApi.php`
|
||||
- **CardTransaction Swagger**: `api/app/Swagger/v1/CardTransactionApi.php`
|
||||
- **모달 설정**: `react/src/components/business/CEODashboard/modalConfigs/cardManagementConfigs.ts`
|
||||
|
||||
---
|
||||
|
||||
## 8. 세션 및 메모리 관리 정책
|
||||
|
||||
### 8.1 세션 시작 시 (Load Strategy)
|
||||
```javascript
|
||||
read_memory("card-management-plan-state") // 1. 상태 파악
|
||||
read_memory("card-management-plan-snapshot") // 2. 사고 흐름 복구
|
||||
```
|
||||
|
||||
### 8.2 작업 중 관리 (Context Defense)
|
||||
| 컨텍스트 잔량 | Action | 내용 |
|
||||
|--------------|--------|---------|
|
||||
| **30% 이하** | 🛠 **Snapshot** | `write_memory("card-management-plan-snapshot", "코드변경+논의요약")` |
|
||||
| **20% 이하** | 🧹 **Context Purge** | `write_memory("card-management-plan-active-symbols", "주요 수정 파일/함수")` |
|
||||
| **10% 이하** | 🛑 **Stop & Save** | 최종 상태 저장 후 세션 교체 권고 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 검증 결과
|
||||
|
||||
> 작업 완료 후 이 섹션에 검증 결과 추가
|
||||
|
||||
### 9.1 테스트 케이스
|
||||
|
||||
| 입력값 | 예상 결과 | 실제 결과 | 상태 |
|
||||
|--------|----------|----------|------|
|
||||
| cm1 카드 클릭 | 카드 사용 상세 모달 표시 | - | ⏳ |
|
||||
| cm2 카드 클릭 | 가지급금 상세 모달 표시 | - | ⏳ |
|
||||
| cm3 카드 클릭 | 법인세 상세 모달 표시 | - | ⏳ |
|
||||
| cm4 카드 클릭 | 종합소득세 상세 모달 표시 | - | ⏳ |
|
||||
| API 실패 시 | fallback 데이터 표시 | - | ⏳ |
|
||||
|
||||
### 9.2 성공 기준 달성 현황
|
||||
|
||||
| 기준 | 달성 | 비고 |
|
||||
|------|------|------|
|
||||
| 4개 카드 실제 데이터 표시 | ⏳ | |
|
||||
| 모달 팝업 실제 데이터 표시 | ⏳ | |
|
||||
| 에러 시 graceful degradation | ⏳ | |
|
||||
|
||||
---
|
||||
|
||||
## 10. 기존 코드 스니펫 (자기완결성 보완)
|
||||
|
||||
> 새 세션에서 이 문서만 보고 즉시 작업 가능하도록 핵심 코드 스니펫 포함
|
||||
|
||||
### 10.1 데이터 흐름 다이어그램
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ CEO Dashboard 카드/가지급금 데이터 흐름 │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────────┐ ┌───────────────────┐ │
|
||||
│ │ Laravel API │ → │ Next.js Proxy │ → │ useCEODashboard │ │
|
||||
│ │ /api/v1/... │ │ /api/proxy/... │ │ Hook │ │
|
||||
│ └──────────────┘ └──────────────────┘ └─────────┬─────────┘ │
|
||||
│ │ │
|
||||
│ API Endpoints: ↓ │
|
||||
│ - card-transactions/summary ────────────────→ transformCardManagement │
|
||||
│ - loans/summary (신규 필요) Response() │
|
||||
│ - loans/tax-simulation (신규 필요) │ │
|
||||
│ ↓ │
|
||||
│ ┌─────────────────────────┐ │
|
||||
│ │ CardManagementData │ │
|
||||
│ │ ├─ cards: AmountCard[] │ │
|
||||
│ │ ├─ checkPoints[] │ │
|
||||
│ │ └─ warningBanner? │ │
|
||||
│ └───────────┬─────────────┘ │
|
||||
│ │ │
|
||||
│ ┌────────────────────────────────────────────────┤ │
|
||||
│ ↓ ↓ │
|
||||
│ ┌──────────────────┐ ┌───────────────────────────────┐ │
|
||||
│ │ CardManagement │ │ DetailModal │ │
|
||||
│ │ Section │ ──(카드 클릭)──→ │ ├─ getCardManagementModal │ │
|
||||
│ │ (4개 카드 표시) │ │ │ Config(cardId) │ │
|
||||
│ └──────────────────┘ │ └─ DetailModalConfig 사용 │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
│ │
|
||||
│ ⚠️ 현재 모달은 하드코딩 데이터 사용 → API 연동 필요 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 10.2 현재 transformCardManagementResponse 함수
|
||||
|
||||
**파일**: `react/src/lib/api/dashboard/transformers.ts` (486-524행)
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* CardTransaction 요약 API 응답 → CardManagementData 변환
|
||||
*
|
||||
* ⚠️ 현재 상태: cm1(카드)만 실제 데이터, cm2~cm4는 fallback 사용
|
||||
*/
|
||||
export function transformCardManagementResponse(
|
||||
summaryApi: CardTransactionApiResponse,
|
||||
fallbackData?: CardManagementData
|
||||
): CardManagementData {
|
||||
const changeRate = calculateChangeRate(
|
||||
summaryApi.current_month_total,
|
||||
summaryApi.previous_month_total
|
||||
);
|
||||
|
||||
return {
|
||||
warningBanner: fallbackData?.warningBanner,
|
||||
cards: [
|
||||
{
|
||||
id: 'cm1',
|
||||
label: '카드',
|
||||
amount: summaryApi.current_month_total,
|
||||
previousLabel: `전월 대비 ${changeRate > 0 ? '+' : ''}${changeRate.toFixed(1)}%`,
|
||||
},
|
||||
// ⚠️ cm2~cm4: 아직 API 미연동 → fallback 또는 기본값
|
||||
fallbackData?.cards[1] ?? {
|
||||
id: 'cm2',
|
||||
label: '가지급금',
|
||||
amount: 0,
|
||||
previousLabel: '미정리 0건',
|
||||
},
|
||||
fallbackData?.cards[2] ?? {
|
||||
id: 'cm3',
|
||||
label: '법인세 예상 가중',
|
||||
amount: 0,
|
||||
},
|
||||
fallbackData?.cards[3] ?? {
|
||||
id: 'cm4',
|
||||
label: '대표자 종합세 예상 가중',
|
||||
amount: 0,
|
||||
},
|
||||
],
|
||||
checkPoints: generateCardManagementCheckPoints(summaryApi),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 10.3 useCardManagement Hook
|
||||
|
||||
**파일**: `react/src/hooks/useCEODashboard.ts` (214-242행)
|
||||
|
||||
```typescript
|
||||
export function useCardManagement(fallbackData?: CardManagementData) {
|
||||
const [data, setData] = useState<CardManagementData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// 현재: card-transactions/summary만 호출
|
||||
const apiData = await fetchApi<CardTransactionApiResponse>(
|
||||
'card-transactions/summary'
|
||||
);
|
||||
const transformed = transformCardManagementResponse(apiData, fallbackData);
|
||||
setData(transformed);
|
||||
|
||||
} catch (err) {
|
||||
const errorMessage = err instanceof Error ? err.message : '데이터 로딩 실패';
|
||||
setError(errorMessage);
|
||||
console.error('CardManagement API Error:', err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [fallbackData]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [fetchData]);
|
||||
|
||||
return { data, loading, error, refetch: fetchData };
|
||||
}
|
||||
```
|
||||
|
||||
### 10.4 DetailModalConfig 타입 정의
|
||||
|
||||
**파일**: `react/src/components/business/CEODashboard/types.ts` (414-426행)
|
||||
|
||||
```typescript
|
||||
// 상세 모달 전체 설정 타입
|
||||
export interface DetailModalConfig {
|
||||
title: string;
|
||||
summaryCards: SummaryCardData[];
|
||||
barChart?: BarChartConfig;
|
||||
pieChart?: PieChartConfig;
|
||||
horizontalBarChart?: HorizontalBarChartConfig;
|
||||
comparisonSection?: ComparisonSectionConfig; // VS 비교 섹션
|
||||
referenceTable?: ReferenceTableConfig; // 참조 테이블
|
||||
referenceTables?: ReferenceTableConfig[]; // 다중 참조 테이블
|
||||
calculationCards?: CalculationCardsConfig;
|
||||
quarterlyTable?: QuarterlyTableConfig;
|
||||
table?: TableConfig;
|
||||
}
|
||||
```
|
||||
|
||||
### 10.5 모달 설정 구조 (cardManagementConfigs.ts)
|
||||
|
||||
**파일**: `react/src/components/business/CEODashboard/modalConfigs/cardManagementConfigs.ts`
|
||||
|
||||
```typescript
|
||||
// ⚠️ 현재: 모든 데이터가 하드코딩됨 → API 연동 필요
|
||||
|
||||
export function getCardManagementModalConfig(cardId: string): DetailModalConfig | null {
|
||||
const configs: Record<string, DetailModalConfig> = {
|
||||
// cm1: 카드 사용 상세
|
||||
cm1: {
|
||||
title: '카드 사용 상세',
|
||||
summaryCards: [
|
||||
{ label: '당월 카드 사용', value: 30123000, unit: '원' },
|
||||
{ label: '전월 대비', value: '+10.5%', isComparison: true, isPositive: true },
|
||||
{ label: '미정리 건수', value: '5건' },
|
||||
],
|
||||
barChart: {
|
||||
title: '월별 카드 사용 추이',
|
||||
data: [...], // 6개월 추이 데이터
|
||||
dataKey: 'value',
|
||||
xAxisKey: 'name',
|
||||
color: '#60A5FA',
|
||||
},
|
||||
pieChart: {
|
||||
title: '사용자별 카드 사용 비율',
|
||||
data: [...], // 사용자별 비율 데이터
|
||||
},
|
||||
table: {
|
||||
title: '카드 사용 내역',
|
||||
columns: [...],
|
||||
data: [...], // 최근 카드 사용 내역
|
||||
filters: [...],
|
||||
showTotal: true,
|
||||
},
|
||||
},
|
||||
|
||||
// cm2: 가지급금 상세
|
||||
cm2: {
|
||||
title: '가지급금 상세',
|
||||
summaryCards: [
|
||||
{ label: '가지급금', value: '4.5억원' },
|
||||
{ label: '인정이자 4.6%', value: 6000000, unit: '원' },
|
||||
{ label: '미정정', value: '10건' },
|
||||
],
|
||||
table: {
|
||||
title: '가지급금 관련 내역',
|
||||
columns: [...],
|
||||
data: [...],
|
||||
filters: [...],
|
||||
showTotal: true,
|
||||
},
|
||||
},
|
||||
|
||||
// cm3: 법인세 예상 가중 상세
|
||||
cm3: {
|
||||
title: '법인세 예상 가중 상세',
|
||||
summaryCards: [...],
|
||||
comparisonSection: {
|
||||
leftBox: {
|
||||
title: '없을때 법인세',
|
||||
items: [...],
|
||||
borderColor: 'orange',
|
||||
},
|
||||
rightBox: {
|
||||
title: '있을때 법인세',
|
||||
items: [...],
|
||||
borderColor: 'blue',
|
||||
},
|
||||
vsLabel: '법인세 예상 증가',
|
||||
vsValue: 3123000,
|
||||
},
|
||||
referenceTable: {
|
||||
title: '법인세 과세표준 (2024년 기준)',
|
||||
columns: [...],
|
||||
data: [...], // 법인세율 참조 테이블
|
||||
},
|
||||
},
|
||||
|
||||
// cm4: 대표자 종합소득세 예상 가중 상세
|
||||
cm4: {
|
||||
title: '대표자 종합소득세 예상 가중 상세',
|
||||
summaryCards: [...],
|
||||
comparisonSection: {
|
||||
leftBox: { title: '가지급금 인정이자가 반영된 종합소득세', ... },
|
||||
rightBox: { title: '가지급금 인정이자가 정리된 종합소득세', ... },
|
||||
vsLabel: '종합소득세 예상 절감',
|
||||
vsValue: 3123000,
|
||||
vsBreakdown: [ // 세부 항목
|
||||
{ label: '종합소득세', value: -2000000, unit: '원' },
|
||||
{ label: '지방소득세', value: -200000, unit: '원' },
|
||||
{ label: '4대 보험', value: -1000000, unit: '원' },
|
||||
],
|
||||
},
|
||||
referenceTable: {
|
||||
title: '종합소득세 과세표준 (2024년 기준)',
|
||||
columns: [...],
|
||||
data: [...], // 종합소득세율 참조 테이블
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return configs[cardId] || null;
|
||||
}
|
||||
```
|
||||
|
||||
### 10.6 API 응답 타입 (현재)
|
||||
|
||||
**파일**: `react/src/lib/api/dashboard/types.ts`
|
||||
|
||||
```typescript
|
||||
// CardTransaction API 응답 (현재 사용 중)
|
||||
export interface CardTransactionApiResponse {
|
||||
previous_month_total: number; // 전월 카드 사용액
|
||||
current_month_total: number; // 당월 카드 사용액
|
||||
total_count: number; // 총 건수
|
||||
total_amount: number; // 총 금액
|
||||
}
|
||||
```
|
||||
|
||||
### 10.7 CEODashboard에서 CardManagement 사용 방식
|
||||
|
||||
**파일**: `react/src/components/business/CEODashboard/CEODashboard.tsx` (301-307행)
|
||||
|
||||
```typescript
|
||||
// 1. useCEODashboard Hook에서 데이터 로드
|
||||
const apiData = useCEODashboard({
|
||||
cardManagementFallback: mockData.cardManagement, // fallback 데이터
|
||||
});
|
||||
|
||||
// 2. API 데이터와 mockData 병합
|
||||
const data = useMemo<CEODashboardData>(() => ({
|
||||
...mockData,
|
||||
cardManagement: apiData.cardManagement.data ?? mockData.cardManagement,
|
||||
}), [apiData]);
|
||||
|
||||
// 3. 카드 클릭 시 모달 표시
|
||||
const handleCardManagementCardClick = useCallback((cardId: string) => {
|
||||
const config = getCardManagementModalConfig(cardId); // 하드코딩 데이터
|
||||
if (config) {
|
||||
setDetailModalConfig(config);
|
||||
setIsDetailModalOpen(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 4. 섹션 렌더링
|
||||
{dashboardSettings.cardManagement && (
|
||||
<CardManagementSection
|
||||
data={data.cardManagement}
|
||||
onCardClick={handleCardManagementCardClick}
|
||||
/>
|
||||
)}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 구현 시 참고사항
|
||||
|
||||
### 11.1 신규 API 개발 시 주의점
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 🔴 필수 준수 사항 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 1. BelongsToTenant 트레잇 사용 (멀티테넌시) │
|
||||
│ 2. FormRequest로 입력 검증 │
|
||||
│ 3. Swagger 문서 작성 (LoanApi.php 참조) │
|
||||
│ 4. 에러 응답 시 success: false, message: '...' 형식 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 11.2 Loan 모델 세금 계산 상수
|
||||
|
||||
**파일**: `api/app/Models/Tenants/Loan.php`
|
||||
|
||||
```php
|
||||
// 세금 계산 상수 (2024년 기준)
|
||||
const CORPORATE_TAX_RATE = 0.19; // 법인세율 19%
|
||||
const INCOME_TAX_RATE = 0.35; // 종합소득세율 35%
|
||||
const LOCAL_TAX_RATE = 0.10; // 지방소득세율 10%
|
||||
const DEFAULT_INTEREST_RATE = 4.6; // 인정이자율 4.6%
|
||||
```
|
||||
|
||||
### 11.3 프론트엔드 파일 수정 순서
|
||||
|
||||
```
|
||||
1. react/src/lib/api/dashboard/types.ts
|
||||
└─ 신규 API 응답 타입 추가
|
||||
|
||||
2. react/src/lib/api/dashboard/transformers.ts
|
||||
└─ transformCardManagementResponse 수정
|
||||
|
||||
3. react/src/hooks/useCEODashboard.ts
|
||||
└─ useCardManagement 훅 수정 (다중 API 호출)
|
||||
|
||||
4. react/src/hooks/useCardManagementModals.ts (신규)
|
||||
└─ 모달용 데이터 훅 생성
|
||||
|
||||
5. react/src/components/business/CEODashboard/modalConfigs/cardManagementConfigs.ts
|
||||
└─ 하드코딩 → API 데이터 기반 동적 생성으로 변경
|
||||
|
||||
6. react/src/components/business/CEODashboard/CEODashboard.tsx
|
||||
└─ 모달 열기 시 API 호출 연동
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. 자기완결성 점검 결과
|
||||
|
||||
### 12.1 체크리스트 검증
|
||||
|
||||
| # | 검증 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 1 | 작업 목적이 명확한가? | ✅ | 4개 카드 + 모달 연동 |
|
||||
| 2 | 성공 기준이 정의되어 있는가? | ✅ | 섹션 9.2 참조 |
|
||||
| 3 | 작업 범위가 구체적인가? | ✅ | Phase 1~4 정의 |
|
||||
| 4 | 의존성이 명시되어 있는가? | ✅ | 기존 API 현황 분석 |
|
||||
| 5 | 참고 파일 경로가 정확한가? | ✅ | 섹션 7, 10 참조 |
|
||||
| 6 | 단계별 절차가 실행 가능한가? | ✅ | 섹션 4, 11 상세 작업 |
|
||||
| 7 | 검증 방법이 명시되어 있는가? | ✅ | 섹션 9.1 테스트 케이스 |
|
||||
| 8 | 모호한 표현이 없는가? | ✅ | API 응답 구조 명시 |
|
||||
| 9 | 기존 코드 스니펫이 포함되어 있는가? | ✅ | 섹션 10 참조 |
|
||||
| 10 | 데이터 흐름이 명시되어 있는가? | ✅ | 섹션 10.1 다이어그램 |
|
||||
|
||||
### 12.2 새 세션 시뮬레이션 테스트
|
||||
|
||||
| 질문 | 답변 가능 | 참조 섹션 |
|
||||
|------|:--------:|----------|
|
||||
| Q1. 이 작업의 목적은 무엇인가? | ✅ | 1.1 배경 |
|
||||
| Q2. 어디서부터 시작해야 하는가? | ✅ | 3.1 Phase 1 |
|
||||
| Q3. 어떤 파일을 수정해야 하는가? | ✅ | 4. 상세 작업, 11.3 순서 |
|
||||
| Q4. 작업 완료 확인 방법은? | ✅ | 9. 검증 결과 |
|
||||
| Q5. 막혔을 때 참고 문서는? | ✅ | 7. 참고 문서 |
|
||||
| Q6. 현재 코드 구조는 어떻게 되어 있는가? | ✅ | 10. 코드 스니펫 |
|
||||
| Q7. 데이터가 어떻게 흐르는가? | ✅ | 10.1 다이어그램 |
|
||||
|
||||
**결과**: 7/7 통과 → ✅ 자기완결성 확보
|
||||
|
||||
### 12.3 보완 이력
|
||||
|
||||
| 날짜 | 항목 | 원본 | 보완 내용 |
|
||||
|------|------|------|----------|
|
||||
| 2026-01-22 | 문서 초안 | - | 초기 계획 작성 |
|
||||
| 2026-01-22 | 코드 스니펫 | 누락 | 섹션 10 추가: transformers, hooks, types, configs |
|
||||
| 2026-01-22 | 데이터 흐름 | 누락 | 섹션 10.1 다이어그램 추가 |
|
||||
| 2026-01-22 | 구현 순서 | 모호함 | 섹션 11.3 파일 수정 순서 명시 |
|
||||
|
||||
---
|
||||
|
||||
*이 문서는 /plan 스킬로 생성되었습니다.*
|
||||
Reference in New Issue
Block a user