# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Kapital Bank is a Frappe app integrating BIRBank B2B API with ERPNext. It handles three workflows: 1. **Import**: Bank statement transactions → Payment Entries / Bank Transactions with fuzzy matching 2. **Mapping**: Purpose-based GL account routing with multi-currency Journal Entry creation 3. **Payments**: Outbound transfers via Payment Request → bank API → status polling ## Development Commands ```bash # Start development server (from bench directory) bench start # Install/reinstall the app bench install-app kapital_bank # Run migrations after doctype changes bench migrate # Run tests bench --site run-tests --app kapital_bank # Run a single test bench --site run-tests --app kapital_bank --module kapital_bank.kapital_bank.doctype.kapital_bank_settings.test_kapital_bank_settings # Linting and formatting (from app directory) pre-commit run --all-files pre-commit run ruff --all-files # Python only pre-commit run eslint --all-files # JavaScript only ``` ## Code Style - **Python**: Ruff linter/formatter — tabs, double quotes, line-length 110, target Python 3.10 - **JavaScript**: ESLint + Prettier — tabs, indent size 4 - **Indentation**: Tabs everywhere (spaces only in JSON, indent size 1) - **Ruff ignores**: B017, E101/402/501/741, W191, UP030/031/032, F401/403/405 ## Architecture ### Core Modules | File | Purpose | |---|---| | `kapital_bank/auth.py` | JWT auth: login, token refresh, scheduled renewal (cron every 4 min) | | `kapital_bank/api.py` | `BIRBankClient` — HTTP wrapper with auto token refresh on 401 | | `kapital_bank/bank_api.py` | Registry loading, fuzzy matching, transaction import (largest module) | | `kapital_bank/payment_api.py` | Outbound transfer execution, status polling, cancellation | | `kapital_bank/mapping.py` | Purpose-based GL mapping + multi-currency Journal Entry creation | | `kapital_bank/setup.py` | Custom field injection on Bank Transaction, Bank Account, Payment Request | | `kapital_bank/overrides/payment_request.py` | Wraps `before_submit()` to survive wkhtmltopdf failures during email send | | `kapital_bank/hooks.py` | Frappe hooks: doctype_js, scheduler_events, doc_events | ### Client-Side Modules | File | Purpose | |---|---| | `client/bank_transaction.js` | Bank Transaction import UI: date/source selection, realtime progress, error CSV export | | `client/payment_entry.js` | Payment Entry import UI (mirrors bank_transaction.js functionality) | | `client/bank_reconciliation_tool.js` | Adds checkbox selection + "Create & Reconcile" bulk action to BRT | | `client/mapping.js` | Shared module: purpose search/preview table for mapping workflows | | `client/payment_order.js` | "Send to Kapital Bank" / "Check Status" / "Cancel" buttons on Payment Order | | `client/payment_request.js` | Same transfer buttons + KB status indicator on Payment Request | | `client/kapital_bank_bank_code.js` | "Sync Bank Codes" button on Bank Code list view | ### Data Flow 1. **Auth**: Credentials in `Kapital Bank Login` → JWT tokens stored as encrypted Password fields → auto-refresh on 401, cron renewal every 4 min 2. **Registry**: API data fetched into local doctypes (Account, Card, Customer, Supplier) 3. **Mapping**: Settings child tables link bank entities to ERPNext records (Bank Account, Customer, Supplier, GL Account) 4. **Import**: Statement transactions → fuzzy match party/purpose → create Payment Entry or Bank Transaction + tracking record 5. **Purpose mapping**: Bank Transactions → match purpose/counterparty → create Transaction Mapping → optionally create Journal Entry + auto-reconcile 6. **Outbound payments**: Payment Request → `send_payment_request()` → Kapital Bank Payment (status tracking) → `poll_pending_payments()` cron → auto-create Payment Entry on success 7. **Cleanup**: Doc events on Payment Entry, Journal Entry, Bank Transaction (on_trash/on_cancel) auto-delete associated KB Transaction records ### Outbound Payment Flow ``` Payment Request (Outward, submitted) → send_payment_request() validates: KB Account mapping, beneficiary IBAN + Bank Code, party name latinization → POST /v2/internal-transfer → creates Kapital Bank Payment (status: "Sent") → poll_pending_payments() cron (every 30 min) → GET /internal-transfer/status → Success: auto-creates Payment Entry via PR.create_payment_entry() → Rejected: logs error, PR stays "Initiated" → Cancel: DELETE /internal-transfer (blocked if pending KB Payments exist) ``` ### Purpose Mapping Modes `mapping.py` supports three modes via `create_purpose_mappings()`: - **Mappings Only**: Creates Transaction Mapping rows (purpose→GL account) without documents - **Documents & Reconcile**: Creates Journal Entries with exchange rates + auto-reconciles Bank Transactions - **Both**: Creates mappings AND documents Priority-based matching in `_find_mapping_for_txn()`: purpose+party > purpose-only > party-only > fallback ### Matching Algorithm Three-tier party matching with configurable similarity thresholds: 1. Exact VÖEN (tax ID) match 2. Name similarity via `SequenceMatcher` (defaults: customer 90%, supplier 80%, purpose 70%) 3. Optional Azərbaycan character normalization (Ə→E, ə→e, etc.) ### DocTypes - **Single doctypes**: `Kapital Bank Login` (credentials), `Kapital Bank Settings` (central config hub with mapping child tables) - **Registry doctypes**: Account, Card, Customer, Supplier — local copies of bank data - **Child tables**: Account Mapping, Card Mapping, Customer Mapping, Supplier Mapping, Transaction Mapping - **Tracking**: `Kapital Bank Transaction` — tracks imported Payment Entries/Journal Entries/Bank Transactions by reference_no for deduplication - **Payment tracking**: `Kapital Bank Payment` — tracks outbound transfer status (Sent → Confirm Wait → Success/Rejected/Cancelled) - **Routing**: `Kapital Bank Bank Code` — 6-char bank codes for transfer routing (synced from API) - **Purpose master**: `Kapital Bank Purpose` — unique purpose keywords with direction (Incoming/Outgoing/Both), status (New/Mapped) - **Utility**: `Kapital Bank API Test` — manual API testing ### Custom Fields Injected on ERPNext Doctypes - **Bank Transaction**: `kb_currency` (Link to Currency) — for multi-currency matching - **Bank Account**: `kb_bank_code` (Link to Kapital Bank Bank Code) — required for outbound transfers - **Payment Request**: `kb_account` (Link to KB Account) + `kb_beneficiary_bank_account` (Link to Bank Account with IBAN) ### Key Patterns - All `@frappe.whitelist()` functions use `ignore_permissions=True` for system-level operations - Bulk imports run as background jobs via `frappe.enqueue()` with 10-min timeout - Progress published via `frappe.publish_realtime()` over Socket.IO (`kb_bt_import_progress`, `kb_bt_import_complete`) - Sensitive data (tokens, passwords) stored in Password-type fields (encrypted in DB) - Error logging via `frappe.log_error()` with `_mask()` hiding account numbers (7+ digits → `first3***last3`) - Party names latinized via `_latinize()` for bank transfers (Azərbaycan → ASCII) - Card statements limited to 90-day range; cross-account transfers deduplicated by reference_no ### Scheduler Events - **Every 4 min**: `auth.renew_token` — JWT token renewal - **Every 30 min**: `payment_api.poll_pending_payments` — check status of outbound transfers ## API Documentation BIRBank B2B API documentation PDFs are in `birbank_docs/`. The base URL is `https://my.birbank.business/api/b2b`. Key endpoints: `/accounts`, `/statements/{id}/transactions`, `/card-statements/{id}/transactions`, `/v2/internal-transfer`, `/internal-transfer/status`, `/bank-codes`