# 보유계좌관리 ## 개요 보유계좌관리는 회사의 은행계좌 정보를 중앙 집중식으로 관리하는 기능입니다. 계좌 등록/수정/삭제, 잔액 조회, 바로빌 연동 최신 잔액 업데이트를 지원합니다. - **라우트**: `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로 처리