7.7 KiB
7.7 KiB
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:
- Import: Bank statement transactions → Payment Entries / Bank Transactions with fuzzy matching
- Mapping: Purpose-based GL account routing with multi-currency Journal Entry creation
- Payments: Outbound transfers via Payment Request → bank API → status polling
Development Commands
# 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 <site-name> run-tests --app kapital_bank
# Run a single test
bench --site <site-name> 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
- Auth: Credentials in
Kapital Bank Login→ JWT tokens stored as encrypted Password fields → auto-refresh on 401, cron renewal every 4 min - Registry: API data fetched into local doctypes (Account, Card, Customer, Supplier)
- Mapping: Settings child tables link bank entities to ERPNext records (Bank Account, Customer, Supplier, GL Account)
- Import: Statement transactions → fuzzy match party/purpose → create Payment Entry or Bank Transaction + tracking record
- Purpose mapping: Bank Transactions → match purpose/counterparty → create Transaction Mapping → optionally create Journal Entry + auto-reconcile
- Outbound payments: Payment Request →
send_payment_request()→ Kapital Bank Payment (status tracking) →poll_pending_payments()cron → auto-create Payment Entry on success - 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:
- Exact VÖEN (tax ID) match
- Name similarity via
SequenceMatcher(defaults: customer 90%, supplier 80%, purpose 70%) - 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 useignore_permissions=Truefor 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