145 lines
7.7 KiB
Markdown
145 lines
7.7 KiB
Markdown
# 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 <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`
|