kapital_bank/CLAUDE.md

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:

  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

# 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

  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 Azerbaijani 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 (Azerbaijani → 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