# 카드사용내역

## 개요

카드사용내역은 바로빌 SOAP API를 통해 카드사 거래내역을 실시간 조회하고,
회계 분류(계정과목 지정), 분개(1거래→N계정과목), 거래 숨김, 금액 수정, 수동 거래 등록 등을 지원하는 기능입니다.

- **라우트**: `GET /finance/card-transactions` → 바로빌 EcardController로 리다이렉트
- **실제 페이지**: `GET /barobill/ecard`
- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링)

## 파일 구조

```
mng/
├── app/Http/Controllers/
│   ├── Barobill/
│   │   └── EcardController.php                    # 메인 컨트롤러 (바로빌 연동)
│   └── Finance/
│       └── CardTransactionController.php          # 수동 거래내역 컨트롤러
├── app/Models/Barobill/
│   ├── CardTransaction.php                        # 바로빌 카드거래 모델
│   ├── CardTransactionSplit.php                   # 거래 분개 모델
│   ├── CardTransactionHide.php                    # 거래 숨김 모델
│   └── CardTransactionAmountLog.php               # 금액 수정 이력 모델
├── app/Models/Finance/
│   └── CardTransaction.php                        # 수동 입력 거래 모델
└── resources/views/
    ├── barobill/ecard/
    │   └── index.blade.php                        # 바로빌 카드거래 React 페이지
    └── finance/
        └── card-transactions.blade.php            # 수동 거래내역 React 페이지

api/
└── database/migrations/
    ├── 2026_01_23_150000_create_barobill_card_transactions_table.php
    ├── 2026_01_23_160000_create_barobill_card_transaction_splits_table.php
    ├── 2026_02_05_100003_create_card_transactions_table.php
    ├── 2026_02_05_200100_create_barobill_card_transaction_amount_logs_table.php
    └── 2026_02_05_500000_create_barobill_card_transaction_hides_table.php
```

## 라우트

### 바로빌 카드거래 (메인)

```php
// routes/web.php (barobill/ecard prefix)
GET    /                    → index()              React 페이지 렌더링
GET    /cards               → cards()              등록된 카드 목록
GET    /transactions        → transactions()       거래내역 조회 (API+DB 병합)
GET    /account-codes       → accountCodes()       계정과목 목록
POST   /save                → save()               거래 저장 (회계 분류)
POST   /export              → exportExcel()        Excel 내보내기
GET    /splits              → splits()             분개 내역 조회
POST   /splits              → saveSplits()         분개 저장
DELETE /splits              → deleteSplits()       분개 삭제
POST   /manual              → storeManual()        수동 거래 등록
PUT    /manual/{id}         → updateManual()       수동 거래 수정
DELETE /manual/{id}         → destroyManual()      수동 거래 삭제
POST   /hide                → hideTransaction()    거래 숨김
POST   /restore             → restoreTransaction() 거래 숨김 해제
GET    /hidden              → hiddenTransactions()  숨긴 거래 목록
```

### 수동 거래내역 (보조)

```php
// routes/web.php (card-transactions prefix)
GET    /list                → index()              수동 거래 목록
POST   /store               → store()              수동 거래 등록
PUT    /{id}                → update()             수동 거래 수정
DELETE /{id}                → destroy()            수동 거래 삭제
```

## 컨트롤러

### EcardController (바로빌 카드거래)

| 메서드 | HTTP | 설명 |
|--------|------|------|
| `index()` | GET | React 페이지 렌더링 (HX-Redirect 적용) |
| `cards()` | GET | 바로빌 등록 카드 목록 (SOAP API) |
| `transactions()` | GET | **거래내역 조회** (API + DB 병합) |
| `accountCodes()` | GET | 계정과목 목록 |
| `save()` | POST | 거래 저장 (계정과목 지정) |
| `exportExcel()` | POST | Excel 내보내기 |
| `splits()` | GET | 분개 내역 조회 |
| `saveSplits()` | POST | 분개 저장 |
| `deleteSplits()` | DELETE | 분개 삭제 |
| `storeManual()` | POST | 수동 거래 등록 |
| `updateManual()` | PUT | 수동 거래 수정 |
| `destroyManual()` | DELETE | 수동 거래 삭제 |
| `hideTransaction()` | POST | 거래 숨김 처리 |
| `restoreTransaction()` | POST | 거래 숨김 해제 |
| `hiddenTransactions()` | GET | 숨긴 거래 목록 |

### CardTransactionController (수동 거래)

| 메서드 | HTTP | 설명 |
|--------|------|------|
| `index()` | GET | 수동 거래 목록 (필터, 통계 포함) |
| `store()` | POST | 거래 등록 |
| `update()` | PUT | 거래 수정 |
| `destroy()` | DELETE | 거래 삭제 (Soft Delete) |

## 바로빌 SOAP API 연동

### 사용 SOAP 메서드

| WSDL | 메서드 | 기능 |
|------|--------|------|
| CARD.asmx | `GetRegisteredCard` | 등록된 카드 목록 조회 |
| CARD.asmx | `GetPeriodCardLog` | 기간별 카드거래 내역 조회 |

### 테넌트별 서버 모드

```
BarobillMember.server_mode → 'test' 또는 'production'
→ BarobillConfig 재로드 → SOAP 클라이언트 재초기화
```

## 핵심 로직

### 거래내역 조회 흐름 (transactions)

```
React 컴포넌트 (카드/기간 선택)
    ↓
GET /barobill/ecard/transactions
    ↓
1. BarobillMember 조회 (바로빌 인증 정보)
    ↓
2. 테넌트별 서버 모드 적용 (test/production)
    ↓
3. SOAP 호출: GetPeriodCardLog (바로빌 API)
    ↓
4. DB 저장된 거래와 병합 (barobill_card_transactions)
    ↓
5. 숨긴 거래 표시 (barobill_card_transaction_hides)
    ↓
6. 분개 데이터 병합 (barobill_card_transaction_splits)
    ↓
7. 수동 거래 병합
    ↓
8. 정렬 + JSON 응답
```

### 거래 고유 키 (unique_key)

```php
// CardTransaction (Barobill) 모델
return implode('|', [
    $this->card_num,
    $this->use_dt,          // 사용일시
    $this->approval_num,
    $this->approval_amount,
]);
```

### 거래 금액 처리

```
approval_type = '1' → 승인 (+ 금액)
approval_type = '2' → 취소 (- 금액)

modified_supply_amount, modified_tax → 금액 수정 시 원본 대신 사용
```

### 분개 저장 흐름

```
React (분개 모달)
    ↓
POST /barobill/ecard/splits
{
    originalUniqueKey: "카드번호|사용일시|승인번호|금액",
    originalData: { cardNum, useDt, ... },
    splits: [
        { amount: 50000, accountCode: "1000", accountName: "당좌예금" },
        { amount: 50000, accountCode: "2000", accountName: "미수금" }
    ]
}
    ↓
기존 분개 삭제 → 새 분개 생성 × N
```

## 모델

### CardTransaction (Barobill)

**테이블**: `barobill_card_transactions`

| 필드 | 타입 | 설명 |
|------|------|------|
| `tenant_id` | bigint | 테넌트 ID |
| `card_num` | string | 카드번호 (하이픈 없음) |
| `card_company` / `card_company_name` | string | 카드사 코드/명 |
| `use_dt` | string | 사용일시 (YYYYMMDDHHMMSS) |
| `use_date` / `use_time` | string | 사용일/시간 분리 |
| `approval_num` | string | 승인번호 |
| `approval_type` | string | 1=승인, 2=취소 |
| `approval_amount` | decimal | 승인금액 |
| `tax` / `service_charge` | decimal | 세금/봉사료 |
| `merchant_name` / `merchant_biz_num` | string | 가맹점명/사업자번호 |
| `account_code` / `account_name` | string | 계정과목 코드/명 |
| `modified_supply_amount` / `modified_tax` | decimal | 수정 공급가/세액 |
| `is_manual` | boolean | 수동 입력 여부 |

- **Unique Index**: `[tenant_id, card_num, use_dt, approval_num, approval_amount]`

### CardTransactionSplit

**테이블**: `barobill_card_transaction_splits`

| 필드 | 타입 | 설명 |
|------|------|------|
| `original_unique_key` | string(200) | 원본 거래 고유 키 |
| `split_amount` | decimal | 분개 금액 |
| `split_supply_amount` / `split_tax` | decimal | 공급가/세액 |
| `account_code` / `account_name` | string | 계정과목 |
| `deduction_type` / `evidence_name` | string | 공제구분/증빙명 |
| `sort_order` | int | 정렬 순서 |

### CardTransactionHide

**테이블**: `barobill_card_transaction_hides`

| 필드 | 타입 | 설명 |
|------|------|------|
| `original_unique_key` | string | 거래 고유 키 |
| `card_num` / `use_date` / `approval_num` | string | 원본 거래 정보 |
| `original_amount` / `merchant_name` | string | 원본 금액/가맹점 |
| `hidden_by` | bigint | 숨김 처리 사용자 |

### CardTransactionAmountLog

**테이블**: `barobill_card_transaction_amount_logs`

| 필드 | 타입 | 설명 |
|------|------|------|
| `card_transaction_id` | bigint | 카드거래 FK |
| `before_supply_amount` / `before_tax` | decimal | 수정 전 금액 |
| `after_supply_amount` / `after_tax` | decimal | 수정 후 금액 |
| `modified_by` / `modified_by_name` | string | 수정자 |
| `ip_address` | string | 수정 IP |

### CardTransaction (Finance - 수동)

**테이블**: `card_transactions`

| 필드 | 타입 | 설명 |
|------|------|------|
| `tenant_id` | bigint | 테넌트 ID |
| `card_id` | bigint | 법인카드 FK |
| `transaction_date` | date | 거래일 |
| `time` | string | 거래시간 (HH:MM) |
| `merchant` | string(200) | 가맹점명 |
| `category` | string | 카테고리 |
| `amount` | bigint | 금액 |
| `approval_no` | string | 승인번호 |
| `status` | enum | approved / cancelled |

## 뷰 구성 (React)

### card-transactions.blade.php (수동 거래)

```
┌─ 페이지 헤더 ──────────────────────
│  Excel 내보내기 | 거래 추가 버튼
│
├─ 통계 카드 (4열) ──────────────────
│  조회 건수 | 총 사용금액 | 승인 금액 | 취소 금액
│
├─ 카테고리 사용현황 (수평 바) ──────
│  식비 | 교통비 | 접대비 | ... (금액 순 정렬)
│
├─ 필터 영역 ────────────────────────
│  검색 | 카드 선택 | 카테고리 | 기간 | 상태(전체/승인/취소)
│
├─ 거래 목록 (날짜별 그룹) ──────────
│  날짜 헤더 (건수, 소계)
│  ├─ 가맹점명 + 카테고리 아이콘
│  ├─ 시간, 카드명, 카테고리라벨
│  ├─ 금액 (승인=빨강, 취소=파랑)
│  └─ 수정/삭제 버튼
│
└─ 등록/수정 모달
   카드, 날짜, 시간, 가맹점명, 카테고리
   금액, 승인번호, 상태, 메모
```

### 카테고리 목록

| 카테고리 | 아이콘 | 색상 |
|---------|--------|------|
| 식비 | Utensils | amber |
| 교통비 | Car | blue |
| 운영비 | Settings | gray |
| 마케팅비 | Megaphone | purple |
| 사무용품 | Paperclip | teal |
| 도서/교육 | BookOpen | indigo |
| 접대비 | Wine | rose |
| 장비구매 | Monitor | cyan |
| 기타 | MoreHorizontal | gray |

## HTMX 호환성

- React 기반 페이지이므로 **HX-Redirect 필요**
- `@push('scripts')` 블록에 React/Babel 스크립트 포함
- HTMX 네비게이션 시 전체 페이지 리로드 필수
