# 보유계좌관리

## 개요

보유계좌관리는 회사의 은행계좌 정보를 중앙 집중식으로 관리하는 기능입니다.
계좌 등록/수정/삭제, 잔액 조회, 바로빌 연동 최신 잔액 업데이트를 지원합니다.

- **라우트**: `GET /finance/accounts`
- **라우트 이름**: `finance.accounts.index`
- **UI 기술**: Blade + HTMX

## 파일 구조

```
mng/
├── app/Http/Controllers/
│   ├── Finance/
│   │   └── BankAccountController.php           # 웹 컨트롤러
│   └── Api/Admin/
│       └── BankAccountController.php           # API 컨트롤러
├── app/Services/
│   └── BankAccountService.php                  # 비즈니스 로직
├── app/Models/Finance/
│   ├── BankAccount.php                         # 계좌 모델
│   └── BankTransaction.php                     # 거래내역 모델
└── resources/views/finance/accounts/
    ├── index.blade.php                         # 목록 페이지
    ├── create.blade.php                        # 등록 폼
    ├── edit.blade.php                          # 수정 폼
    ├── show.blade.php                          # 상세 (거래내역 포함)
    └── partials/
        └── table.blade.php                     # 테이블 partial (HTMX)
```

## 라우트

### 웹 라우트

```php
// routes/web.php (finance prefix 그룹 내)
Route::get('/accounts', [BankAccountController::class, 'index'])->name('accounts.index');
Route::get('/accounts/create', [..., 'create'])->name('accounts.create');
Route::get('/accounts/{id}', [..., 'show'])->name('accounts.show');
Route::get('/accounts/{id}/edit', [..., 'edit'])->name('accounts.edit');
```

### API 라우트

```php
// routes/api.php (admin/bank-accounts prefix)
GET    /all                     → 전체 계좌 (드롭다운용)
GET    /summary                 → 요약 통계
GET    /                        → 목록 (페이지네이션)
POST   /                        → 신규 등록
GET    /{id}                    → 상세 조회
PUT    /{id}                    → 수정
DELETE /{id}                    → 삭제 (Soft Delete)
POST   /{id}/restore            → 복원
DELETE /{id}/force              → 영구 삭제 (슈퍼관리자만)
POST   /{id}/toggle-active      → 활성/비활성 토글
GET    /{id}/transactions       → 거래내역 조회
POST   /bulk-delete             → 일괄 삭제
POST   /bulk-restore            → 일괄 복원
```

## 컨트롤러

### BankAccountController (웹)

| 메서드 | 설명 | 특이사항 |
|--------|------|---------|
| `index()` | 계좌 목록 | HTMX 감지 → HX-Redirect (JS 실행 보장) |
| `create()` | 등록 폼 | - |
| `show(id)` | 상세 + 거래내역 | 바로빌 거래 연동 |
| `edit(id)` | 수정 폼 | 404 에러 처리 |

## 서비스 클래스

### BankAccountService

| 메서드 | 설명 |
|--------|------|
| `getAccounts(filters, perPage)` | 목록 (페이지네이션) + 바로빌 최신 거래일 |
| `getAllAccounts()` | 모든 활성 계좌 (드롭다운용) |
| `getStatsByBank()` | 은행별 통계 |
| `getAccountById(id, withTrashed)` | 단일 조회 |
| `createAccount(data)` | 신규 등록 |
| `updateAccount(account, data)` | 수정 |
| `deleteAccount(account)` | Soft Delete |
| `restoreAccount(account)` | 복원 |
| `forceDeleteAccount(account)` | 영구 삭제 |
| `toggleActive(account)` | 활성/비활성 토글 |
| `getTransactions(accountId, filters, perPage)` | 계좌별 거래내역 |
| `getSummary()` | 전체 요약 (총 계좌 수, 총 잔액) |
| `bulkDelete(ids)` | 일괄 삭제 |
| `bulkRestore(ids)` | 일괄 복원 |

**바로빌 연동**: `getAccounts()` 실행 시 서브쿼리로 `barobill_bank_transactions` 테이블의 최신 거래 날짜/시간을 조회하여 계좌 데이터에 병합합니다.

```php
// 계좌번호 매칭: 하이픈 제거
REPLACE(account_number, '-', '') = barobill_bank_transactions.bank_account_num
```

## 모델

### BankAccount

**테이블**: `bank_accounts`

#### 주요 필드

| 필드 | 타입 | 설명 |
|------|------|------|
| `tenant_id` | bigint | 테넌트 ID |
| `bank_code` | string | 은행 코드 (000=한국은행, 020=우리은행 등) |
| `bank_name` | string | 은행명 |
| `account_number` | string | 계좌번호 (하이픈 포함) |
| `account_holder` | string | 예금주명 |
| `account_name` | string | 계좌 별칭 |
| `account_type` | string | 예금종류 (보통예금, 정기예금, 적금) |
| `balance` | decimal(15,2) | 현재 잔액 |
| `currency` | string | 통화 (KRW) |
| `opened_at` | date | 개설일자 |
| `last_transaction_at` | datetime | 최종 거래일시 |
| `branch_name` | string | 지점명 |
| `memo` | text | 메모 |
| `status` | string | active / inactive |
| `is_primary` | boolean | 대표계좌 여부 |
| `sort_order` | int | 정렬 순서 |

#### Traits

- `BelongsToTenant` - 테넌트 기반 자동 필터링
- `SoftDeletes` - Soft Delete 지원

#### 주요 Scope

```php
->active()       // status = 'active'
->primary()      // is_primary = true
->byBank($name)  // 은행별 필터
->byType($type)  // 예금종류별 필터
->ordered()      // sort_order 정렬
```

#### 주요 Accessor

```php
$account->formatted_balance       // "1억 2,345만원" 형식
$account->masked_account_number   // "110-***-5678"
```

## 뷰 구성

### index.blade.php

```
┌─ 페이지 헤더 ──────────────────────
│  제목: "보유계좌관리"
│  버튼: "계좌 등록" (파란색)
│
├─ 요약 카드 (3열) ─────────────────
│  총 계좌 수 | 총 잔액 | 은행 수
│
├─ 테이블 컨테이너 ─────────────────
│  ├─ 헤더: 검색, 상태 필터
│  └─ HTMX 로드 영역 (#accounts-table)
│     └─ GET /admin/bank-accounts/
│
├─ partials/table.blade.php ────────
│  컬럼: 은행 | 계좌번호 | 예금종류 | 잔액 | 개설일자 | 최종처리일시 | 작업
│  ├─ 활성 항목: 수정/삭제 버튼
│  └─ 삭제된 항목: 복원/영구삭제 (opacity-50 bg-red-50)
│
└─ JavaScript: refreshAccountBalances()
   └─ GET /barobill/eaccount/latest-balances
   └─ DOM에서 잔액 실시간 업데이트
```

### 테이블 Partial 특징

| 컬럼 | 특이사항 |
|------|---------|
| 은행 | `show/{id}` 링크 |
| 예금종류 | 컬러 배지 (보통예금=파랑, 정기=보라, 적금=초록) |
| 잔액 | `data-account-number` 속성으로 동적 업데이트 |
| 최종처리일시 | 바로빌 거래일 또는 로컬 데이터 |
| 작업 | HTMX 기반 토글/삭제/복원 |

## 데이터 흐름

```
사용자 (브라우저)
    ↓
BankAccountController::index()
    ↓
BankAccountService::getSummary()
    ↓ (bank_accounts: 총 계좌 수, 총 잔액)
View: finance/accounts/index
    ├─ 요약 카드 표시
    ├─ HTMX 테이블 로드
    │   ↓
    │   Api\Admin\BankAccountController
    │   ↓
    │   BankAccountService::getAccounts()
    │   │   ↓
    │   │   bank_accounts + 바로빌 최신 거래일 서브쿼리
    │   └─ JSON/HTML 반환
    │
    └─ refreshAccountBalances()
        ↓
        EaccountController::latestBalances()
        ↓
        barobill_bank_transactions (최신 잔액)
        ↓
        DOM 업데이트
```

## 데이터베이스 스키마

### bank_accounts

**마이그레이션**: `api/database/migrations/2025_12_17_120001_create_bank_accounts_table.php`

```sql
CREATE TABLE bank_accounts (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    tenant_id BIGINT NOT NULL,
    bank_code VARCHAR(10),
    bank_name VARCHAR(50),
    account_number VARCHAR(50),
    account_holder VARCHAR(100),
    account_name VARCHAR(100),
    account_type VARCHAR(20),
    balance DECIMAL(15,2) DEFAULT 0,
    currency VARCHAR(3) DEFAULT 'KRW',
    opened_at DATE,
    last_transaction_at DATETIME,
    branch_name VARCHAR(100),
    memo TEXT,
    status VARCHAR(20) DEFAULT 'active',
    is_primary BOOLEAN DEFAULT FALSE,
    sort_order INT DEFAULT 0,
    created_by BIGINT, updated_by BIGINT, deleted_by BIGINT,
    created_at TIMESTAMP, updated_at TIMESTAMP, deleted_at TIMESTAMP
);
```

## HTMX 호환성

- Blade + HTMX 기반 (HX-Redirect 사용 - JavaScript 있음)
- 테이블은 HTMX partial로 동적 로드
- 토글/삭제/복원 액션은 HTMX로 처리
