- card-management-section-plan 수정 - monthly-expense-integration-plan 신규 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
718 lines
25 KiB
Markdown
718 lines
25 KiB
Markdown
# 당월 예상 지출내역 API 연동 계획
|
|
|
|
> **작성일**: 2026-01-22
|
|
> **목적**: CEO 대시보드의 당월 예상 지출내역 섹션 4개 카드 및 모달 API 연동
|
|
> **기준 문서**: `react/src/components/business/CEODashboard/`, `api/app/Services/ExpectedExpenseService.php`
|
|
> **상태**: 🔄 진행중 (Serena ID: monthly-expense-state)
|
|
|
|
---
|
|
|
|
## 📍 현재 진행 상태
|
|
|
|
| 항목 | 내용 |
|
|
|------|------|
|
|
| **마지막 완료 작업** | - |
|
|
| **다음 작업** | Phase 1.1 - 카드 요약 데이터 연동 상태 확인 |
|
|
| **진행률** | 0/8 (0%) |
|
|
| **마지막 업데이트** | 2026-01-22 |
|
|
|
|
---
|
|
|
|
## 1. 개요
|
|
|
|
### 1.1 배경
|
|
|
|
CEO 대시보드의 **당월 예상 지출내역** 섹션에 4개의 카드(매입, 카드, 발행어음, 총예상 지출 합계)가 있으며, 현재 카드 요약 데이터는 API 연동이 완료되어 있으나, 각 카드 클릭 시 표시되는 **모달의 상세 데이터는 목업(Mock) 데이터**를 사용하고 있음.
|
|
|
|
모달에는 다음 정보가 포함됨:
|
|
- **요약 카드**: 당월 금액, 전월 대비, 이용건 등
|
|
- **차트**: 월별 추이 바차트, 유형별/사용자별 파이차트, 거래처별 수평 바차트
|
|
- **테이블**: 일별 상세 내역 (필터, 정렬, 합계 포함)
|
|
|
|
### 1.2 기준 원칙
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ 🎯 핵심 원칙 │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ - Service-First 아키텍처 (비즈니스 로직은 Service에) │
|
|
│ - API 우선 개발 → Frontend 연동 │
|
|
│ - 기존 API 패턴 준수 (ExpectedExpenseService 확장) │
|
|
│ - Multi-tenancy 필수 (tenant_id 스코프) │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### 1.3 변경 승인 정책
|
|
|
|
| 분류 | 예시 | 승인 |
|
|
|------|------|------|
|
|
| ✅ 즉시 가능 | 기존 Service에 메서드 추가, 새 API 엔드포인트, React Hook 추가 | 불필요 |
|
|
| ⚠️ 컨펌 필요 | 테이블 스키마 변경, 기존 API 응답 구조 변경 | **필수** |
|
|
| 🔴 금지 | 기존 summary API 제거, 프로덕션 데이터 직접 수정 | 별도 협의 |
|
|
|
|
### 1.4 준수 규칙
|
|
- `docs/quickstart/quick-start.md` - 빠른 시작 가이드
|
|
- `docs/standards/quality-checklist.md` - 품질 체크리스트
|
|
- `api/CLAUDE.md` - SAM API Development Rules
|
|
- `docs/guides/swagger-guide.md` - Swagger 문서 작성 가이드
|
|
|
|
---
|
|
|
|
## 1.5 🔴 핵심 발견 사항: 데이터 소스 매핑
|
|
|
|
> **중요**: 4개 카드는 **서로 다른 테이블**에서 데이터를 가져와야 함!
|
|
|
|
| 카드 ID | 카드명 | 데이터 소스 테이블 | 비고 |
|
|
|---------|--------|-------------------|------|
|
|
| **me1** | 매입 | `purchases` | Purchase 모델 |
|
|
| **me2** | 카드 | `withdrawals` (payment_method='card') | Withdrawal 모델, CardTransactionService 참조 |
|
|
| **me3** | 발행어음 | `bills` (bill_type='issued') | Bill 모델 |
|
|
| **me4** | 지출예상 | `expected_expenses` (전체 집계) | ExpectedExpense 모델 |
|
|
|
|
### 1.5.1 ExpectedExpense 모델 (지출예상)
|
|
|
|
**파일**: `api/app/Models/Tenants/ExpectedExpense.php`
|
|
|
|
```php
|
|
// ⚠️ 주의: transaction_type에 'card', 'bill'이 없음!
|
|
public const TRANSACTION_TYPES = [
|
|
'purchase' => '매입',
|
|
'advance' => '선급금',
|
|
'suspense' => '가지급금',
|
|
'rent' => '임대료',
|
|
'salary' => '급여',
|
|
'insurance' => '보험료',
|
|
'tax' => '세금',
|
|
'utilities' => '공과금',
|
|
'other' => '기타',
|
|
];
|
|
|
|
public const PAYMENT_STATUSES = [
|
|
'pending' => '미지급',
|
|
'partial' => '부분지급',
|
|
'completed' => '지급완료',
|
|
];
|
|
|
|
// 주요 필드
|
|
protected $fillable = [
|
|
'vendor_id', 'transaction_type', 'description', 'amount',
|
|
'expected_payment_date', 'payment_status', 'paid_amount', // ...
|
|
];
|
|
```
|
|
|
|
### 1.5.2 Purchase 모델 (매입)
|
|
|
|
**파일**: `api/app/Models/Tenants/Purchase.php`
|
|
|
|
```php
|
|
public const PURCHASE_TYPES = [
|
|
'unset' => '미설정',
|
|
'raw_material' => '원재료매입',
|
|
'subsidiary_material' => '부재료매입',
|
|
'packaging_material' => '포장재매입',
|
|
'consumable' => '소모품',
|
|
'equipment' => '장비',
|
|
'service' => '용역',
|
|
'other' => '기타',
|
|
];
|
|
|
|
// 주요 필드: vendor_id, purchase_type, purchase_date, total_amount, status
|
|
// 관계: belongsTo(Vendor), hasMany(PurchaseItem)
|
|
```
|
|
|
|
### 1.5.3 Bill 모델 (발행어음)
|
|
|
|
**파일**: `api/app/Models/Tenants/Bill.php`
|
|
|
|
```php
|
|
public const BILL_TYPES = [
|
|
'received' => '수취',
|
|
'issued' => '발행', // ← me3 필터 조건
|
|
];
|
|
|
|
public const ISSUED_STATUSES = [
|
|
'stored' => '보관중',
|
|
'maturityAlert' => '만기입금(7일전)',
|
|
'matured' => '만기',
|
|
'defaulted' => '부도',
|
|
'partialPayment' => '분할입금',
|
|
'completed' => '입금완료',
|
|
];
|
|
|
|
// 주요 필드: bill_type, vendor_id, issue_date, maturity_date, amount, status
|
|
// 관계: belongsTo(Vendor), belongsTo(BankAccount)
|
|
```
|
|
|
|
### 1.5.4 Withdrawal 모델 (카드 사용)
|
|
|
|
**파일**: `api/app/Models/Tenants/Withdrawal.php`
|
|
|
|
```php
|
|
public const PAYMENT_METHODS = [
|
|
'cash' => '현금',
|
|
'transfer' => '계좌이체',
|
|
'card' => '카드', // ← me2 필터 조건
|
|
'check' => '수표',
|
|
];
|
|
|
|
// 주요 필드: bank_account_id, card_id, payment_method, withdrawal_date,
|
|
// amount, description, category, vendor_id
|
|
// 관계: belongsTo(Card), belongsTo(BankAccount), belongsTo(Vendor)
|
|
```
|
|
|
|
### 1.5.5 CardTransactionService (기존 서비스 참조)
|
|
|
|
**파일**: `api/app/Services/CardTransactionService.php`
|
|
|
|
```php
|
|
// summary() 메서드 - 카드 거래 조회 예시
|
|
public function summary(): array
|
|
{
|
|
$currentMonth = Withdrawal::where('payment_method', 'card')
|
|
->whereBetween('withdrawal_date', [$startOfMonth, $endOfMonth])
|
|
->sum('amount');
|
|
|
|
return [
|
|
'previous_month_total' => $previousMonth,
|
|
'current_month_total' => $currentMonth,
|
|
'total_count' => $count,
|
|
'total_amount' => $total,
|
|
];
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 1.6 DetailModal 컴포넌트 구조
|
|
|
|
**파일**: `react/src/components/business/CEODashboard/modals/DetailModal.tsx`
|
|
|
|
모달은 `DetailModalConfig` 타입의 설정 객체를 받아 렌더링:
|
|
|
|
```typescript
|
|
interface DetailModalConfig {
|
|
title: string;
|
|
subtitle?: string;
|
|
summaryCards?: SummaryCardData[]; // 상단 요약 카드들
|
|
barChart?: BarChartConfig; // 월별 추이 차트
|
|
pieChart?: PieChartConfig; // 파이 차트 (유형별)
|
|
horizontalBarChart?: HorizontalBarChartConfig; // 수평 바차트 (거래처별)
|
|
table?: TableConfig; // 상세 테이블 (필터, 정렬 포함)
|
|
}
|
|
|
|
// 렌더링 순서
|
|
<DetailModal config={config}>
|
|
1. SummaryCard[] (요약 카드들)
|
|
2. BarChartSection (월별 추이)
|
|
3. PieChartSection OR HorizontalBarChartSection (비율/현황)
|
|
4. TableSection (상세 내역 + 필터 + 정렬)
|
|
</DetailModal>
|
|
```
|
|
|
|
**데이터 흐름**:
|
|
```
|
|
카드 클릭 → handleMonthlyExpenseCardClick(cardId)
|
|
→ getMonthlyExpenseModalConfig(cardId) // 현재 하드코딩
|
|
→ setDetailModalConfig(config)
|
|
→ DetailModal 렌더링
|
|
```
|
|
|
|
---
|
|
|
|
## 2. 대상 범위
|
|
|
|
### 2.1 Phase 1: 현황 확인 및 카드 데이터 검증
|
|
|
|
| # | 작업 항목 | 상태 | 비고 |
|
|
|---|----------|:----:|------|
|
|
| 1.1 | 카드 요약 데이터 API 연동 상태 확인 | ⏳ | `useCEODashboard` → `useMonthlyExpense` |
|
|
| 1.2 | 현재 모달 목업 데이터 구조 분석 | ⏳ | `monthlyExpenseConfigs.ts` |
|
|
|
|
### 2.2 Phase 2: API 엔드포인트 개발
|
|
|
|
| # | 작업 항목 | 상태 | 비고 |
|
|
|---|----------|:----:|------|
|
|
| 2.1 | 매입(me1) 상세 API 개발 | ⏳ | 월별 추이, 유형별 비율, 일별 내역 |
|
|
| 2.2 | 카드(me2) 상세 API 개발 | ⏳ | 월별 추이, 사용자별 비율, 일별 내역 |
|
|
| 2.3 | 발행어음(me3) 상세 API 개발 | ⏳ | 월별 추이, 거래처별 현황, 일별 내역 |
|
|
| 2.4 | 지출예상(me4) 상세 API 개발 | ⏳ | 승인 내역서, 지출 합계, 계좌 잔액 |
|
|
|
|
### 2.3 Phase 3: Frontend 모달 연동
|
|
|
|
| # | 작업 항목 | 상태 | 비고 |
|
|
|---|----------|:----:|------|
|
|
| 3.1 | API 호출 Hook 추가 | ⏳ | `useCEODashboard.ts` 확장 |
|
|
| 3.2 | 모달 설정에서 API 데이터 연동 | ⏳ | `monthlyExpenseConfigs.ts` 수정 |
|
|
|
|
---
|
|
|
|
## 3. 작업 절차
|
|
|
|
### 3.1 단계별 절차
|
|
|
|
```
|
|
Step 1: 현황 확인 (Phase 1)
|
|
├── useCEODashboard.ts의 useMonthlyExpense 훅 동작 확인
|
|
├── transformMonthlyExpenseResponse 변환 로직 확인
|
|
└── monthlyExpenseConfigs.ts 목업 데이터 구조 분석
|
|
|
|
Step 2: API 설계 (Phase 2 준비)
|
|
├── 각 모달별 필요 데이터 정의
|
|
├── ExpectedExpenseService에 추가할 메서드 설계
|
|
└── Swagger 문서 작성
|
|
|
|
Step 3: API 개발 (Phase 2)
|
|
├── ExpectedExpenseService에 상세 조회 메서드 추가
|
|
├── ExpectedExpenseController에 라우트 추가
|
|
├── FormRequest 검증 클래스 생성
|
|
└── Swagger 문서 생성
|
|
|
|
Step 4: Frontend 연동 (Phase 3)
|
|
├── API 타입 정의 추가 (dashboard/types.ts)
|
|
├── API 호출 함수 추가 (useCEODashboard.ts)
|
|
├── Transformer 함수 추가 (transformers.ts)
|
|
└── monthlyExpenseConfigs.ts를 동적 데이터로 변경
|
|
```
|
|
|
|
### 3.2 모달별 데이터 구조 분석
|
|
|
|
#### me1 (매입 상세)
|
|
```typescript
|
|
{
|
|
summaryCards: [
|
|
{ label: '당월 매입', value: number, unit: '원' },
|
|
{ label: '전월 대비', value: string, isComparison: true }
|
|
],
|
|
barChart: { title: '월별 매입 추이', data: MonthlyData[] },
|
|
pieChart: { title: '자재 유형별 구매 비율', data: TypeRatioData[] },
|
|
table: {
|
|
title: '일별 매입 내역',
|
|
columns: ['no', 'date', 'vendor', 'amount', 'type'],
|
|
data: PurchaseItem[],
|
|
filters: ['type', 'sortOrder']
|
|
}
|
|
}
|
|
```
|
|
|
|
#### me2 (카드 상세)
|
|
```typescript
|
|
{
|
|
summaryCards: [
|
|
{ label: '당월 카드 사용', value: number, unit: '원' },
|
|
{ label: '전월 대비', value: string, isComparison: true },
|
|
{ label: '이용건', value: string }
|
|
],
|
|
barChart: { title: '월별 카드 사용 추이', data: MonthlyData[] },
|
|
pieChart: { title: '사용자별 카드 사용 비율', data: UserRatioData[] },
|
|
table: {
|
|
title: '일별 카드 사용 내역',
|
|
columns: ['no', 'cardName', 'user', 'date', 'store', 'amount', 'usageType'],
|
|
data: CardUsageItem[],
|
|
filters: ['user', 'sortOrder']
|
|
}
|
|
}
|
|
```
|
|
|
|
#### me3 (발행어음 상세)
|
|
```typescript
|
|
{
|
|
summaryCards: [
|
|
{ label: '당월 발행어음 사용', value: number, unit: '원' },
|
|
{ label: '전월 대비', value: string, isComparison: true }
|
|
],
|
|
barChart: { title: '월별 발행어음 추이', data: MonthlyData[] },
|
|
horizontalBarChart: { title: '당월 거래처별 발행어음', data: VendorData[] },
|
|
table: {
|
|
title: '일별 발행어음 내역',
|
|
columns: ['no', 'vendor', 'issueDate', 'dueDate', 'amount', 'status'],
|
|
data: BillItem[],
|
|
filters: ['vendor', 'status', 'sortOrder']
|
|
}
|
|
}
|
|
```
|
|
|
|
#### me4 (지출예상 상세)
|
|
```typescript
|
|
{
|
|
summaryCards: [
|
|
{ label: '당월 지출 예상', value: number, unit: '원' },
|
|
{ label: '전월 대비', value: string, isComparison: true },
|
|
{ label: '총 계좌 잔액', value: number, unit: '원' }
|
|
],
|
|
table: {
|
|
title: '당월 지출 승인 내역서',
|
|
columns: ['paymentDate', 'item', 'amount', 'vendor', 'account'],
|
|
data: ExpenseItem[],
|
|
filters: ['vendor', 'sortOrder'],
|
|
footerSummary: [
|
|
{ label: '지출 합계', value: number },
|
|
{ label: '계좌 잔액', value: number },
|
|
{ label: '최종 차액', value: number }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 4. 상세 작업 내용
|
|
|
|
> 각 Phase 진행 후 이 섹션에 상세 내용 추가
|
|
|
|
### 4.1 Phase 1: 현황 확인
|
|
|
|
#### 1.1 카드 요약 데이터 API 연동 상태
|
|
- **상태**: ⏳ 대기
|
|
- **확인 파일**:
|
|
- `react/src/hooks/useCEODashboard.ts` - `useMonthlyExpense()` 훅
|
|
- `react/src/lib/api/dashboard/transformers.ts` - `transformMonthlyExpenseResponse()`
|
|
- `api/app/Services/ExpectedExpenseService.php` - `summary()` 메서드
|
|
|
|
**현재 분석 결과**:
|
|
- ✅ 카드 요약 데이터는 이미 API 연동됨 (`/api/proxy/expected-expenses/summary`)
|
|
- ✅ `by_transaction_type`으로 purchase, card, bill 분류되어 반환
|
|
- ❌ 모달 상세 데이터는 `monthlyExpenseConfigs.ts`에서 하드코딩된 목업 사용
|
|
|
|
#### 1.2 현재 모달 목업 데이터 구조
|
|
- **상태**: ✅ 분석 완료
|
|
- **확인 파일**: `react/src/components/business/CEODashboard/modalConfigs/monthlyExpenseConfigs.ts`
|
|
|
|
**현재 분석 결과**:
|
|
- 각 카드 ID(me1~me4)별 `DetailModalConfig` 객체 정의
|
|
- 하드코딩된 데이터: summaryCards, barChart, pieChart, horizontalBarChart, table
|
|
- 테이블 필터와 정렬 옵션도 정적으로 정의됨
|
|
|
|
**목업 함수 시그니처** (API로 대체 필요):
|
|
```typescript
|
|
// monthlyExpenseConfigs.ts
|
|
export function getMonthlyExpenseModalConfig(cardId: string): DetailModalConfig | null {
|
|
switch (cardId) {
|
|
case 'me1': return getME1Config(); // 매입 - 하드코딩 목업
|
|
case 'me2': return getME2Config(); // 카드 - 하드코딩 목업
|
|
case 'me3': return getME3Config(); // 발행어음 - 하드코딩 목업
|
|
case 'me4': return getME4Config(); // 지출예상 - 하드코딩 목업
|
|
default: return null;
|
|
}
|
|
}
|
|
```
|
|
|
|
**목업 → API 전환 방식** (선택지):
|
|
1. **방식 A**: `getMonthlyExpenseModalConfig`를 async로 변경 → API 호출
|
|
2. **방식 B**: Modal 컴포넌트에서 `useEffect`로 API 호출 → config 동적 생성
|
|
3. **방식 C** (권장): 새 Hook `useMonthlyExpenseDetail(type)` 생성 → 데이터 반환 → config 생성
|
|
|
|
### 4.2 Phase 2: API 엔드포인트 개발
|
|
|
|
> **⚠️ 중요**: 각 API는 **서로 다른 테이블/서비스**에서 데이터를 조회함!
|
|
|
|
#### 2.1 매입(me1) 상세 API
|
|
|
|
- **상태**: ⏳ 대기
|
|
- **엔드포인트**: `GET /api/v1/purchases/dashboard-detail`
|
|
- **Service**: `PurchaseService` (신규 메서드 추가 또는 기존 확장)
|
|
- **Model**: `Purchase` (테이블: `purchases`)
|
|
- **필요 데이터**:
|
|
- 당월 매입 합계: `Purchase::whereBetween('purchase_date', [$start, $end])->sum('total_amount')`
|
|
- 전월 대비 변화율: 전월 합계 대비 증감률 계산
|
|
- 최근 7개월 월별 매입 추이: `groupBy(month)` 집계
|
|
- 자재 유형별 구매 비율: `groupBy('purchase_type')` → `raw_material`, `subsidiary_material` 등
|
|
- 일별 매입 내역: 개별 레코드 with `vendor` 관계
|
|
|
|
**API 응답 구조**:
|
|
```json
|
|
{
|
|
"summary": {
|
|
"current_month_total": 305000000,
|
|
"previous_month_total": 276000000,
|
|
"change_rate": 10.5,
|
|
"count": 45
|
|
},
|
|
"monthly_trend": [
|
|
{ "month": "2025-07", "amount": 250000000 },
|
|
{ "month": "2025-08", "amount": 280000000 }
|
|
],
|
|
"by_type": [
|
|
{ "type": "raw_material", "label": "원재료매입", "amount": 180000000, "ratio": 59.0 },
|
|
{ "type": "subsidiary_material", "label": "부재료매입", "amount": 80000000, "ratio": 26.2 }
|
|
],
|
|
"items": [
|
|
{
|
|
"id": 1,
|
|
"date": "2026-01-15",
|
|
"vendor_name": "대한철강",
|
|
"amount": 15000000,
|
|
"type": "raw_material",
|
|
"type_label": "원재료매입"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### 2.2 카드(me2) 상세 API
|
|
|
|
- **상태**: ⏳ 대기
|
|
- **엔드포인트**: `GET /api/v1/card-transactions/dashboard-detail`
|
|
- **Service**: `CardTransactionService` (기존 서비스 확장)
|
|
- **Model**: `Withdrawal` (테이블: `withdrawals`, 조건: `payment_method='card'`)
|
|
- **필요 데이터**:
|
|
- 당월 카드 사용 합계, 이용 건수: `where('payment_method', 'card')`
|
|
- 전월 대비 변화율
|
|
- 최근 7개월 월별 카드 사용 추이
|
|
- 사용자별 카드 사용 비율: `groupBy` → `card.assigned_user_id` 기준
|
|
- 일별 카드 사용 내역: with `card`, `card.assignedUser` 관계
|
|
|
|
**API 응답 구조**:
|
|
```json
|
|
{
|
|
"summary": {
|
|
"current_month_total": 30123000,
|
|
"previous_month_total": 27000000,
|
|
"change_rate": 11.6,
|
|
"count": 128
|
|
},
|
|
"monthly_trend": [
|
|
{ "month": "2025-07", "amount": 25000000 }
|
|
],
|
|
"by_user": [
|
|
{ "user_id": 1, "user_name": "김철수", "amount": 12000000, "ratio": 39.8 }
|
|
],
|
|
"items": [
|
|
{
|
|
"id": 1,
|
|
"card_name": "삼성카드 1234",
|
|
"user_name": "김철수",
|
|
"date": "2026-01-20",
|
|
"store": "GS25 강남점",
|
|
"amount": 35000,
|
|
"category": "복리후생비"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### 2.3 발행어음(me3) 상세 API
|
|
|
|
- **상태**: ⏳ 대기
|
|
- **엔드포인트**: `GET /api/v1/bills/dashboard-detail`
|
|
- **Service**: `BillService` (신규 메서드 추가)
|
|
- **Model**: `Bill` (테이블: `bills`, 조건: `bill_type='issued'`)
|
|
- **필요 데이터**:
|
|
- 당월 발행어음 합계: `where('bill_type', 'issued')`
|
|
- 전월 대비 변화율
|
|
- 최근 7개월 월별 발행어음 추이
|
|
- 거래처별 발행어음 현황: `groupBy('vendor_id')` with vendor 관계
|
|
- 일별 발행어음 내역: with `vendor` 관계
|
|
|
|
**API 응답 구조**:
|
|
```json
|
|
{
|
|
"summary": {
|
|
"current_month_total": 30123000,
|
|
"previous_month_total": 28000000,
|
|
"change_rate": 7.6,
|
|
"count": 15
|
|
},
|
|
"monthly_trend": [
|
|
{ "month": "2025-07", "amount": 26000000 }
|
|
],
|
|
"by_vendor": [
|
|
{ "vendor_id": 1, "vendor_name": "대한건설", "amount": 15000000, "ratio": 49.8 }
|
|
],
|
|
"items": [
|
|
{
|
|
"id": 1,
|
|
"vendor_name": "대한건설",
|
|
"issue_date": "2026-01-05",
|
|
"maturity_date": "2026-04-05",
|
|
"amount": 10000000,
|
|
"status": "stored",
|
|
"status_label": "보관중"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### 2.4 지출예상(me4) 상세 API
|
|
|
|
- **상태**: ⏳ 대기
|
|
- **엔드포인트**: `GET /api/v1/expected-expenses/dashboard-detail`
|
|
- **Service**: `ExpectedExpenseService` (기존 서비스 확장)
|
|
- **Model**: `ExpectedExpense` (테이블: `expected_expenses`)
|
|
- **추가 Model**: `BankAccount` (계좌 잔액 조회)
|
|
- **필요 데이터**:
|
|
- 당월 지출 예상 합계: `sum('amount')` where `expected_payment_date` in current month
|
|
- 전월 대비 변화율
|
|
- 총 계좌 잔액: `BankAccount::sum('balance')`
|
|
- 지출 승인 내역: 개별 레코드 with `vendor`, `bankAccount` 관계
|
|
- 푸터 요약: 지출 합계, 계좌 잔액, 최종 차액 계산
|
|
|
|
**API 응답 구조**:
|
|
```json
|
|
{
|
|
"summary": {
|
|
"current_month_total": 350000000,
|
|
"previous_month_total": 320000000,
|
|
"change_rate": 9.4,
|
|
"total_account_balance": 3050000000
|
|
},
|
|
"items": [
|
|
{
|
|
"id": 1,
|
|
"expected_payment_date": "2026-01-25",
|
|
"description": "원자재 대금",
|
|
"amount": 50000000,
|
|
"vendor_name": "대한철강",
|
|
"account_name": "기업은행 1234"
|
|
}
|
|
],
|
|
"footer": {
|
|
"expense_total": 350000000,
|
|
"account_balance": 3050000000,
|
|
"difference": 2700000000
|
|
}
|
|
}
|
|
|
|
### 4.3 Phase 3: Frontend 모달 연동
|
|
|
|
#### 3.1 API 호출 Hook 추가
|
|
- **상태**: ⏳ 대기
|
|
- **수정 파일**: `react/src/hooks/useCEODashboard.ts`
|
|
- **추가 내용**:
|
|
- `useMonthlyExpenseDetail(type: 'purchase' | 'card' | 'bill' | 'total')`
|
|
- 로딩, 에러, 데이터 상태 관리
|
|
|
|
#### 3.2 모달 설정 동적 데이터 연동
|
|
- **상태**: ⏳ 대기
|
|
- **수정 파일**: `react/src/components/business/CEODashboard/modalConfigs/monthlyExpenseConfigs.ts`
|
|
- **변경 내용**:
|
|
- 정적 함수 → 비동기 데이터 fetching 함수로 변경
|
|
- 또는 모달 컴포넌트에서 직접 API 호출하도록 변경
|
|
|
|
---
|
|
|
|
## 5. 컨펌 대기 목록
|
|
|
|
> API 내부 로직 변경 등 승인 필요 항목
|
|
|
|
| # | 항목 | 변경 내용 | 영향 범위 | 상태 |
|
|
|---|------|----------|----------|------|
|
|
| - | - | - | - | - |
|
|
|
|
---
|
|
|
|
## 6. 변경 이력
|
|
|
|
| 날짜 | 항목 | 변경 내용 | 파일 | 승인 |
|
|
|------|------|----------|------|------|
|
|
| 2026-01-22 | - | 문서 초안 작성 | - | - |
|
|
|
|
---
|
|
|
|
## 7. 참고 문서
|
|
|
|
- **빠른 시작**: `docs/quickstart/quick-start.md`
|
|
- **품질 체크리스트**: `docs/standards/quality-checklist.md`
|
|
- **API 규칙**: `api/CLAUDE.md` (SAM API Development Rules)
|
|
- **Swagger 가이드**: `docs/guides/swagger-guide.md`
|
|
- **대시보드 타입**: `react/src/lib/api/dashboard/types.ts`
|
|
|
|
---
|
|
|
|
## 8. 세션 및 메모리 관리 정책 (Serena Optimized)
|
|
|
|
### 8.1 세션 시작 시 (Load Strategy)
|
|
```javascript
|
|
// 순차적 로드
|
|
read_memory("monthly-expense-state") // 1. 상태 파악
|
|
read_memory("monthly-expense-snapshot") // 2. 사고 흐름 복구
|
|
read_memory("monthly-expense-active-symbols") // 3. 작업 대상 파악
|
|
```
|
|
|
|
### 8.2 작업 중 관리 (Context Defense)
|
|
| 컨텍스트 잔량 | Action | 내용 |
|
|
|--------------|--------|------|
|
|
| **30% 이하** | 🛠 **Snapshot** | `write_memory("monthly-expense-snapshot", "코드변경+논의요약")` |
|
|
| **20% 이하** | 🧹 **Context Purge** | `write_memory("monthly-expense-active-symbols", "주요 수정 파일/함수")` |
|
|
| **10% 이하** | 🛑 **Stop & Save** | 최종 상태 저장 후 세션 교체 권고 |
|
|
|
|
### 8.3 Serena 메모리 구조
|
|
- `monthly-expense-state`: { phase, progress, next_step, last_decision } (JSON 구조)
|
|
- `monthly-expense-snapshot`: 현재까지의 논의 및 코드 변경점 요약 (Text)
|
|
- `monthly-expense-rules`: 해당 작업에서 결정된 불변의 규칙들 (Text)
|
|
- `monthly-expense-active-symbols`: 현재 수정 중인 파일/심볼 리스트 (List)
|
|
|
|
---
|
|
|
|
## 9. 검증 결과
|
|
|
|
> 작업 완료 후 이 섹션에 검증 결과 추가
|
|
|
|
### 9.1 테스트 케이스
|
|
|
|
| 입력값 | 예상 결과 | 실제 결과 | 상태 |
|
|
|--------|----------|----------|------|
|
|
| me1 카드 클릭 | 매입 상세 모달 표시 (API 데이터) | | ⏳ |
|
|
| me2 카드 클릭 | 카드 상세 모달 표시 (API 데이터) | | ⏳ |
|
|
| me3 카드 클릭 | 발행어음 상세 모달 표시 (API 데이터) | | ⏳ |
|
|
| me4 카드 클릭 | 지출예상 상세 모달 표시 (API 데이터) | | ⏳ |
|
|
| 테이블 필터 적용 | 필터된 데이터 표시 | | ⏳ |
|
|
| 테이블 정렬 변경 | 정렬된 데이터 표시 | | ⏳ |
|
|
|
|
### 9.2 성공 기준 달성 현황
|
|
|
|
| 기준 | 달성 | 비고 |
|
|
|------|------|------|
|
|
| 4개 카드 요약 데이터 API 연동 | ✅ | 이미 연동됨 |
|
|
| 매입 상세 모달 API 연동 | ⏳ | |
|
|
| 카드 상세 모달 API 연동 | ⏳ | |
|
|
| 발행어음 상세 모달 API 연동 | ⏳ | |
|
|
| 지출예상 상세 모달 API 연동 | ⏳ | |
|
|
| 테이블 필터/정렬 동작 | ⏳ | |
|
|
|
|
---
|
|
|
|
## 10. 자기완결성 점검 결과
|
|
|
|
> 문서 생성 시 Phase 5.5에서 수행된 자기완결성 점검 결과
|
|
|
|
### 10.1 체크리스트 검증
|
|
|
|
| # | 검증 항목 | 상태 | 비고 |
|
|
|---|----------|:----:|------|
|
|
| 1 | 작업 목적이 명확한가? | ✅ | 4개 카드 및 모달 API 연동 |
|
|
| 2 | 성공 기준이 정의되어 있는가? | ✅ | 섹션 9.2 참조 |
|
|
| 3 | 작업 범위가 구체적인가? | ✅ | Phase별 작업 항목 명시 |
|
|
| 4 | 의존성이 명시되어 있는가? | ✅ | **1.5 데이터 소스 매핑** - 4개 모델 및 테이블 명시 |
|
|
| 5 | 참고 파일 경로가 정확한가? | ✅ | 모든 파일 경로 검증됨 |
|
|
| 6 | 단계별 절차가 실행 가능한가? | ✅ | Step 1~4 구체적, API 응답 구조 포함 |
|
|
| 7 | 검증 방법이 명시되어 있는가? | ✅ | 섹션 9.1 테스트 케이스 |
|
|
| 8 | 모호한 표현이 없는가? | ✅ | 구체적 데이터 구조 및 쿼리 힌트 명시 |
|
|
|
|
### 10.2 새 세션 시뮬레이션 테스트
|
|
|
|
| 질문 | 답변 가능 | 참조 섹션 |
|
|
|------|:--------:|----------|
|
|
| Q1. 이 작업의 목적은 무엇인가? | ✅ | 1.1 배경 |
|
|
| Q2. 어디서부터 시작해야 하는가? | ✅ | 3.1 단계별 절차 |
|
|
| Q3. 어떤 파일을 수정해야 하는가? | ✅ | 2. 대상 범위, 4. 상세 작업 내용 |
|
|
| Q4. 작업 완료 확인 방법은? | ✅ | 9. 검증 결과 |
|
|
| Q5. 막혔을 때 참고 문서는? | ✅ | 7. 참고 문서 |
|
|
| **Q6. 각 카드의 데이터 소스는?** | ✅ | **1.5 데이터 소스 매핑** |
|
|
| **Q7. API 응답 형식은?** | ✅ | **4.2 각 API별 응답 구조** |
|
|
| **Q8. 모델 필드는 무엇인가?** | ✅ | **1.5.1~1.5.4 모델 정의** |
|
|
|
|
**결과**: 8/8 통과 → ✅ 자기완결성 확보 (보완 후)
|
|
|
|
### 10.3 보완 이력
|
|
|
|
| 날짜 | 항목 | 원본 | 보완 내용 |
|
|
|------|------|------|----------|
|
|
| 2026-01-22 | - | - | 초기 검증 통과 (70-80%) |
|
|
| 2026-01-22 | 1.5 | 누락 | **데이터 소스 매핑** 추가 - 4개 카드별 테이블 명시 |
|
|
| 2026-01-22 | 1.5.1~1.5.5 | 누락 | **모델 정의** 추가 - 필드, 상수, 관계 명시 |
|
|
| 2026-01-22 | 1.6 | 누락 | **DetailModal 구조** 추가 - 컴포넌트 흐름 명시 |
|
|
| 2026-01-22 | 4.2 | 불완전 | **API 응답 구조** 추가 - JSON 예시 포함 |
|
|
| 2026-01-22 | 4.1 | 불완전 | **목업 전환 방식** 추가 - 3가지 선택지 명시 |
|
|
|
|
---
|
|
|
|
*이 문서는 /plan 스킬로 생성되었습니다.* |