Files
sam-docs/features/card-vehicle/card-transactions.md
김보곤 a23e2560ac docs:카드/차량관리 개발문서 추가 (5개 메뉴)
- 법인카드관리: 카드 CRUD, 결제일 휴일조정, 사용금액 집계, 선불결제
- 카드사용내역: 바로빌 SOAP 연동, 분개, 거래숨김, 금액수정
- 차량목록: 법인/렌트/리스 차량 등록, 주행거리 자동계산
- 차량일지: 운행기록, 용도별 통계, 출발↔도착 교환
- 정비이력: 카테고리별 비용 관리, 주행거리 자동갱신

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 16:31:25 +09:00

312 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 카드사용내역
## 개요
카드사용내역은 바로빌 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 네비게이션 시 전체 페이지 리로드 필수