Replaces "Azeri" / "Azerbaijani" with the native form "Azərbaycan" in
labels, descriptions, and Python comments. Field names / identifiers
are unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the same correctness fixes now in jey_erp.bank_integration:
- Party-name lookup at Create & Reconcile + fuzzy purpose matcher now apply
Azerbaijani transliteration when settings.consider_azeri_chars is on, with
per-row override via the new Azeri Translit Select on Customer/Supplier
Mappings (same pattern as case sensitivity).
- create_unmapped_customers / create_unmapped_suppliers now look up existing
parties by tax_id first, then by name; when found, the mapping row is
linked to the existing party instead of silently skipping it. Response
reports linked_count alongside created_count.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the same logic now in jey_erp.bank_integration. Party-name lookup at
Create & Reconcile gains a global 'Ignore Case in Party Matching' Check
(default ON) on Kapital Bank Settings, plus a 'Case Mode' Select on each
Customer / Supplier Mapping row that overrides the global per row.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A group Cost Center selected here would silently pass on save but fail at
PE/JE creation during reconciliation with "Cannot select a Group type Cost
Center". set_query on the child-table field hides group nodes from the
dropdown.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A Bank Transaction created before its counterparty was mapped carries no
party. When reconciling, look up the BT's bank_party_name in the
customer/supplier mappings — if that counterparty is mapped to an
ERPNext party, the txn gets it, so counterparty-based rules match and
the created PE/JE carries the party. Also: only attach a party to a
Payment Entry when one of the GL accounts is Receivable/Payable
(otherwise ERPNext rejects it).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
_find_mapping_for_txn now tries exact-substring purpose matches first
(unchanged), then falls back to a partial-ratio fuzzy match against
similarity_threshold_purpose — so a short/imprecise purpose keyword can
match somewhere inside a long statement description. Order: purpose+
counterparty (exact) > purpose-only (exact) > purpose+counterparty
(fuzzy) > purpose-only (fuzzy) > counterparty-only > fallback. Set the
threshold to 100 to keep the old substring-only behaviour. This makes
similarity_threshold_purpose meaningful in the BRT path (previously it
only affected the API-driven import).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The on_update reverse-sync only treated a row as "mapped" if its key
field was present, so clearing erp_customer / erp_supplier / bank_account
(without deleting the row) left the Kapital Bank Customer/Supplier/
Account/Card still marked Mapped. Now a row counts as mapped only when
both the key and the ERP/Bank Account link are set.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The first-leaf fallback meant customers always landed in "Individual"
even when no Customer Group was chosen. Customer/Supplier/Territory
aren't actually mandatory in ERPNext, so now: a configured value is
validated (exists + leaf) and used; nothing configured -> the party is
created with an empty customer_group / supplier_group / territory.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Creating customers/suppliers no longer requires a default Customer/
Supplier Group or Territory on Kapital Bank Settings — when none is set,
the first leaf (non-group) node of the tree is used. A configured value
is still validated (must exist and be a leaf), with a clear message.
Also: the default-group / default-territory Link fields (and the
matching mapping child-table fields) now filter to is_group=0 so a group
node can't be selected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Customer/Supplier require a leaf node for customer_group/supplier_group/
territory; selecting a group node makes ERPNext throw "Cannot select a
Group type ...". Creation now checks is_group during the upfront
validation and returns a clear message before touching any record.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Creating customers/suppliers/bank accounts from unmapped rows fell back
to "All Customer Groups" / "All Territories" / "All Supplier Groups",
which don't exist on localized sites, producing ERPNext's cryptic
"Could not find Customer Group: All Customer Groups". Creation now
validates upfront and returns a clear message ("Set a Default Customer
Group on Kapital Bank Settings ...") before touching any records — also
for Territory, Supplier Group, and Company/Bank when creating Bank
Accounts from account/card mappings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The "Import" button on the Bank Transaction list view moved from the
"Kapital Bank" group into the shared "Import From..." dropdown
(created by jey_erp), labelled "Load from Kapital Bank". Switched to a
defensive listview_settings assignment so jey_erp's existing onload
handler is preserved.
Removed client/bank_reconciliation_tool.js and its doctype_js hook —
the BRT extension (checkbox column, Create & Reconcile toolbar) lives
in jey_erp now and works with both Kapital Bank Settings and the new
Bank Integration mappings via a universal resolver. No behaviour change
for kb-mapped Bank Accounts: jey_erp's after_migrate links them to
Kapital Bank Settings via hidden Dynamic Link fields on Bank Account.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Build full description from operationName, fullRemark, shortRemark, and
description fields for card statement transactions. Show a warning banner
when card transactions are present since duplicate detection across card
and account statements is not possible due to different reference numbers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mapping_currency is a filter field (which transactions the rule matches),
not the denomination of the BT amount. Using it as txn_currency caused
700 AZN to be treated as 700 USD → 1190 AZN in the Journal Entry.
Now txn_currency comes from bank_txn.currency (= GL account currency),
which always matches the BT deposit/withdrawal amount.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: get_statement_transactions() used fcyAmount (foreign currency
amount) but tagged it with account_currency. For AZN-to-USD exchanges on
AZN accounts, this picked the USD amount (e.g. 400) but labelled it as
AZN, causing wrong BT amounts and cascading JE errors.
Fix: parse acCcy from API and use lcyAmount (always AZN per API docs)
when acCcy differs from account_currency. Also revert txn_currency
fallback in JE creation from kb_currency back to bank_txn.currency so
the amount and currency stay consistent throughout the pipeline.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Payment Request → bank API → status polling workflow:
- payment_api.py: send transfers, poll status, cancel, sync bank codes
- Kapital Bank Payment doctype for tracking transfer status
- Kapital Bank Bank Code doctype for transfer routing
- Client-side buttons on Payment Request and Payment Order
- PaymentRequest.before_submit override to survive wkhtmltopdf failures
- Custom fields on Bank Account (kb_bank_code) and Payment Request
- Improved HTTP error handling in BIRBankClient
- Updated CLAUDE.md with full architecture documentation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In "Both" mode, mapping_currency is empty and the frontend does not
pass currency in the txn dict, causing txn_currency to default to AZN.
Now falling back to bank_txn.kb_currency so the actual account currency
is always used regardless of which mode triggered the JE creation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously a JE/PE was left in the database even when reconcile_vouchers threw
an error. Now the whole transaction (document creation + failed reconciliation)
is rolled back so no orphaned document is created.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pass mapping_row.currency through the call chain so _create_journal_entry_for_brt
uses the mapping's currency (not the bank transaction document) as txn_currency.
This ensures correct exchange-rate calculation and proper multi-currency handling.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _find_mapping_for_txn: kb_currency could be empty on bank transactions not
imported through KB; fall back to standard currency field so USD-specific
mappings are not skipped when matching in Documents & Reconcile mode
- _create_journal_entry_for_brt: JS does not pass currency in txn dict;
fall back to bank_txn.currency so exchange-rate calculations are correct
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add currency field to purpose_rules tuple in _build_import_lookups
- Filter rules by txn currency in _match_purpose_rules (empty = match all)
- Remove in_list_view from notes field so currency column is visible in grid
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace custom kb_account_type field with the existing
expense_income_type field (label: Expense/Income) defined
in jey_erp. Remove the now-unnecessary ensure_journal_entry_custom_fields()
function from setup.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
In "Both" mode, mappings were saved before documents were created,
so a failed document still produced a mapping entry.
Now for "Both" mode: document is created first, and the mapping row
is added only on success. Settings are saved once after all transactions.
"Mappings Only" and "Documents & Reconcile" modes are unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a hidden, read-only 'KB Account Type' (Income/Expense) field
to Journal Entry via Custom Field, visible only in list view.
Populated automatically when a JE is created from a KB transaction:
- Pay (drcr=D) → Expense
- Receive (drcr=C) → Income
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace ad-hoc if/elif branches with a unified approach:
1. Read txn_currency from the transaction data
2. Convert amount → company currency via txn_rate
3. Derive each account's amount in its own currency
4. Recompute exact exchange rates from rounded amounts
to keep Frappe's debit == credit in company currency
Fixes the bug where a $40 debit was recorded as ~$25 debit
and 40 AZN credit due to dividing instead of multiplying
when the transaction currency matched the foreign account.
Applies to both bank_api.py (_import_one_transaction JE path)
and mapping.py (_create_journal_entry_for_brt).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
For Receive transactions, paid_to (bank account) should be debited
and paid_from (income/receivable account) should be credited.
The logic was inverted in both bank_api.py and mapping.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>