Files
sam-docs/features/finance/daily-fund-report.md

202 lines
5.8 KiB
Markdown
Raw Normal View History

# 일일자금일보
## 개요
일일자금일보는 기간별 계좌 입출금 현황을 조회하고 일별 보고서를 생성하는 기능입니다.
바로빌에서 수집된 은행 거래 데이터를 기반으로 날짜별, 계좌별 입출금 집계를 제공합니다.
- **라우트**: `GET /finance/daily-fund`
- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링)
## 파일 구조
```
mng/
├── app/Http/Controllers/Finance/
│ └── DailyFundController.php # 메인 컨트롤러 (6개 메서드)
├── app/Models/Finance/
│ ├── DailyFundTransaction.php # 수동 거래내역 모델
│ └── DailyFundMemo.php # 일별 메모 모델
├── app/Models/Barobill/
│ ├── BankTransaction.php # 바로빌 거래내역 모델
│ └── BankTransactionOverride.php # 거래 수정 이력
└── resources/views/finance/
└── daily-fund.blade.php # React 기반 UI
```
## 라우트
```php
// routes/web.php (finance prefix 그룹 내)
Route::get('/daily-fund', [DailyFundController::class, 'index'])->name('daily-fund');
// API 엔드포인트 (동일 컨트롤러)
Route::get('/daily-fund/period-report', [DailyFundController::class, 'periodReport']);
Route::post('/daily-fund', [DailyFundController::class, 'store']);
Route::put('/daily-fund/{id}', [DailyFundController::class, 'update']);
Route::delete('/daily-fund/{id}', [DailyFundController::class, 'destroy']);
Route::post('/daily-fund/memo', [DailyFundController::class, 'saveMemo']);
```
## 컨트롤러
### DailyFundController
| 메서드 | HTTP | 설명 |
|--------|------|------|
| `index()` | GET | 특정 날짜 거래내역 조회 |
| `store()` | POST | 거래내역 수동 등록 |
| `update()` | PUT | 거래내역 수정 |
| `destroy()` | DELETE | 거래내역 삭제 |
| `saveMemo()` | POST | 일별 메모 저장 |
| `periodReport()` | GET | **기간별 일일자금일보** (핵심) |
### periodReport() 핵심 로직
```
QueryString: start_date, end_date (YYYYMMDD)
BarobillBankTransaction 조회 (trans_date 범위)
BankTransactionOverride 병합 (수정된 적요/내용)
unique_key 기준 중복 제거
날짜별 그룹핑 + 계좌별 입출금 집계
JSON 응답
```
**응답 구조**:
```json
{
"dailyReports": [
{
"date": "20260211",
"dateFormatted": "2026년 2월 11일 수요일",
"accounts": [
{ "bankName": "우리은행", "accountNum": "1002-xxx", "deposit": 5000000, "withdraw": 1000000, "balance": 50000000 }
],
"deposits": [
{ "time": "0930", "bankName": "우리은행", "summary": "급여입금", "cast": "본사", "amount": 5000000, "balance": 50000000 }
],
"withdrawals": [ ... ],
"totalDeposit": 5000000,
"totalWithdraw": 1000000
}
]
}
```
## 뷰 구성 (React)
### daily-fund.blade.php
```
┌─ 기간 선택 컴포넌트 ────────────
│ 날짜 입력 (start_date ~ end_date)
│ 월별 단축키 (이번달, 지난달 등)
├─ 일별 보고서 반복 렌더링 ────────
│ ┌─ 날짜 헤더 ──────────
│ │ 2026년 2월 11일 수요일
│ │
│ ├─ 계좌별 요약 테이블 ──
│ │ 은행명 | 계좌번호 | 입금 | 출금 | 잔액
│ │
│ ├─ 입금 상세 내역 ─────
│ │ 시간 | 은행 | 적요 | 내용 | 금액 | 잔액
│ │
│ └─ 출금 상세 내역 ─────
│ 시간 | 은행 | 적요 | 내용 | 금액 | 잔액
└─ 인쇄 버튼
```
## 데이터 흐름
```
React Component (기간 선택)
↓ fetch GET /finance/daily-fund/period-report
DailyFundController::periodReport()
BarobillBankTransaction 조회
↓ (trans_date 범위 필터)
BankTransactionOverride 병합
↓ (수정된 적요/내용 덮어쓰기)
unique_key 기준 중복 제거
날짜별 + 계좌별 그룹핑
↓ (입금/출금 분류, 계좌별 집계)
JSON 응답
React 렌더링 (테이블, 통계)
```
## 데이터베이스 테이블
### barobill_bank_transactions (주 데이터)
| 컬럼 | 타입 | 설명 |
|------|------|------|
| `tenant_id` | bigint | 테넌트 ID |
| `bank_account_num` | string | 계좌번호 |
| `bank_name` | string | 은행명 |
| `trans_date` | string | 거래일 (YYYYMMDD) |
| `trans_time` | string | 거래시간 (HHMM) |
| `deposit` | decimal | 입금액 |
| `withdraw` | decimal | 출금액 |
| `balance` | decimal | 거래 후 잔액 |
| `summary` | string | 적요 |
| `cast` | string | 내용 |
### daily_fund_transactions (수동 입력)
| 컬럼 | 타입 | 설명 |
|------|------|------|
| `tenant_id` | bigint | 테넌트 ID |
| `transaction_date` | date | 거래일 |
| `type` | enum | income / expense |
| `amount` | decimal | 금액 |
| `description` | string | 설명 |
### daily_fund_memos
| 컬럼 | 타입 | 설명 |
|------|------|------|
| `tenant_id` | bigint | 테넌트 ID |
| `memo_date` | date | 메모 날짜 |
| `memo` | text | 메모 내용 |
| `author` | string | 작성자 |
## 핵심 로직
### 거래 중복 제거
```php
->unique(fn($tx) => $tx->unique_key)
// unique_key = bank_account_num|trans_dt|deposit|withdraw|balance
```
### 오버라이드 병합
```php
BankTransactionOverride::getByUniqueKeys($keys)
// → modified_summary, modified_cast로 원본 적요/내용 덮어쓰기
// → is_overridden 플래그 설정
```
### 일별 집계
```
거래 목록 → trans_date 기준 그룹핑
→ 각 날짜: 계좌별 분류
→ 입금 합계, 출금 합계 계산
→ 최종 잔액: DESC 정렬 첫 거래의 balance 값
```
## HTMX 호환성
- React 기반 페이지이므로 HX-Redirect 필요
- `@push('scripts')` 블록에 React/Babel 스크립트 포함