Commit Graph

62 Commits

Author SHA1 Message Date
Ali eb7bd51f1d feat(api): migrate BIRBank integration to new v2 portal API
The bank rewrote its B2B API. Auth (login/refresh) is unchanged; everything
else moved to /b2b/<service>/portal/v{N}/... with a new response shape
(HTTP status codes + direct JSON instead of the responseData/response.code
envelope). Migrated all flows and verified against the live API.

Import:
- accounts → /b2b/accounts/portal/v1, cards → /b2b/cards/portal/v1
- account statement → /b2b/account/portal/v3/statements (top-level statementList)
- card statement → /b2b/cards/portal/v1/statements (accountNo+panLast4, paginated)
- ISO date parsing for trnDt; robust card date parsing; pagination safety cap

Bank dictionary:
- sync_bank_codes seeds from /banks?iban= per account; Bank Code gains bank_id + bic_code
- beneficiary bank/branch id resolved live from IBAN at send time

Outbound payments (rewritten):
- send → national-currency/internal (Kapital) or /inland (other banks) with
  nested payer/payee, payee.bank.id, name, tin; response {id, processKey}
- status → GET /transfers/portal/v1/{id}, mapped from frontState
- cancel → PUT /transfers/portal/v1/{id}/reject (mandatory comment)
- Kapital Bank Payment reworked: transfer_no/transfer_id/process_key/front_state
- VÖEN sourced from party (Bank Account has none); required for inland
- AZN-only guard on currency and sender account

Client/UX:
- bank error details (errors[]) surfaced via extract_error_message
- cancel dialogs show real errors instead of "Unknown error"

Security:
- Kapital Bank Login password: Data → encrypted Password field + migration patch

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 16:02:26 +00:00
Ali 14383c0e15 fix(import): guard realtime progress bar against late progress events
A 'progress' event arriving after 'complete' recreated an unmanaged
progress modal that nothing closed. Add an importFinished flag so the
progress handler no-ops after completion, and force-close the modal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 16:19:28 +00:00
Ali bdf32afa2d refactor(kapital-bank): move client JS into bundle; update settings, mappings, hooks, az locale
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 17:52:03 +00:00
Ali b004ff32f4 fix(create-accounts): set is_company_account=1 on auto-created Bank Accounts
Bank Accounts created via the "Create" buttons for both Kapital Bank
accounts and cards represent the company's own accounts at the bank —
not counterparty accounts. Without is_company_account=1 ERPNext treats
them as external and they don't appear in Bank Reconciliation Tool or
as selectable paid_from/paid_to in Payment Entry / Journal Entry.
2026-05-18 14:17:35 +00:00
Ali 5462c55cd3 refactor(kapital-bank): drop redundant Default Company field
System is single-company; Default Company on Kapital Bank Settings
duplicated what ERPNext already exposes via Global Defaults. Removed
the field and replaced all settings/doc.default_company reads with
erpnext.get_default_company() (used by Bank Account creation for
accounts/cards, Journal Entry / Payment Entry / Bank Transaction
creation during reconcile). Existing column on the singleton table is
left in place — Frappe just ignores it.
2026-05-18 13:42:34 +00:00
Ali c9032df3bf chore: use native Azərbaycan spelling in user-facing strings
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>
2026-05-14 10:56:54 +00:00
Ali 53d4eb1cc7 fix: symmetric Azeri translit + VOEN-first dedup
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>
2026-05-14 10:45:43 +00:00
Ali fd3f74d3ed feat: case-insensitive party matching, with per-row override
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>
2026-05-13 16:25:49 +00:00
Ali a6687da894 fix: filter cost_center in transaction_mappings to non-group nodes
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>
2026-05-13 10:44:27 +00:00
Ali 39c8733099 feat: resolve party at Create & Reconcile time from the mappings
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>
2026-05-12 13:01:33 +00:00
Ali e589dcdaf4 feat: fuzzy purpose matching in BRT Create & Reconcile
_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>
2026-05-12 12:22:47 +00:00
Ali bb49b5915a fix: clearing a mapping row's ERP/Bank Account link resets the registry record
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>
2026-05-12 11:38:08 +00:00
Ali d9d033bfe1 fix: create party without a group when none is configured
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>
2026-05-12 11:05:09 +00:00
Ali 853c01e3e9 feat: fall back to first leaf node when no group is configured + filter group fields
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>
2026-05-12 10:53:29 +00:00
Ali 8d66f2101d fix: reject group-node Customer/Supplier Group / Territory upfront
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>
2026-05-12 10:45:29 +00:00
Ali aae3dfacfb fix: clear validation message when default groups/company aren't set
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>
2026-05-12 10:31:40 +00:00
Ali cc7dfbeda8 chore: move BT-list Import button into shared "Import From..." group
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>
2026-05-08 16:24:03 +00:00
Ali 6fbec93fc9 new translations 2026-04-24 20:30:36 +00:00
Ali dd5ffc0bed feat: enrich card transaction descriptions and add duplicate warning
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>
2026-03-27 17:06:07 +04:00
Ali 677c1492e7 fix: use card's own currency for all card statement transactions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 23:17:59 +04:00
Ali e975cfbe26 fix: use amount instead of originalAmount for card statement imports
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 23:12:04 +04:00
Ali f87db8e6de fix: don't use mapping_currency as txn_currency in JE creation
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>
2026-03-26 21:37:21 +04:00
Ali d8cf942792 fix: use lcyAmount for cross-currency transactions on AZN accounts
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>
2026-03-26 19:44:16 +04:00
Ali b76cdd355e feat: add outbound payment flow via Kapital Bank API
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>
2026-03-26 19:44:05 +04:00
Ali 197257d044 fix: use bank_txn.kb_currency as fallback for txn_currency in JE creation
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>
2026-03-16 18:41:53 +04:00
Ali 97b57c8572 fix: rollback document if reconciliation fails in Documents & Reconcile mode
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>
2026-03-16 18:31:58 +04:00
Ali 87d4578927 fix: use mapping currency for JE creation in Documents & Reconcile mode
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>
2026-03-16 18:12:26 +04:00
Ali cbcd06c83b fix: use bt.currency fallback in _find_mapping_for_txn + fix txn_currency in JE creation
- _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>
2026-03-16 18:05:47 +04:00
Ali 57c8cb0925 fix: filter transaction mappings by currency + hide notes from list view
- 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>
2026-03-16 17:39:12 +04:00
Ali 3fbb02a7fc refactor: use existing expense_income_type field from jey_erp
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>
2026-03-16 16:32:16 +04:00
Ali 2f10fb4aa0 fix: skip mapping creation if document creation fails in Both mode
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>
2026-03-16 16:16:20 +04:00
Ali 3b44f5a694 feat: add kb_account_type custom field to Journal Entry
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>
2026-03-16 15:31:28 +04:00
Ali 62bc550186 fix: correct multi-currency amounts in Journal Entry creation
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>
2026-03-16 15:10:27 +04:00
Ali f063c5cd0c fix: swap debit/credit for Receive type Journal Entry
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>
2026-03-16 14:57:05 +04:00
Ali 3202f5e1ac fixed bug 2026-03-14 00:51:16 +04:00
Ali d17982c81a fixed bug 2026-03-13 22:06:27 +04:00
Ali 3e90e872a1 added currency to mappings 2026-03-13 21:28:17 +04:00
Ali 68c3d7d8a9 bug fix 2026-03-13 21:04:16 +04:00
Ali 5b47d06eec removed filter for multi currency 2026-03-13 20:21:30 +04:00
Ali 42e5c42ab3 removed filter for multi currency 2026-03-13 20:12:36 +04:00
Ali e54d13ae22 removed filter for multi currency 2026-03-13 20:09:07 +04:00
Ali c563f494c3 fixed bug with multicurrency 2026-03-13 18:26:43 +04:00
Ali fc34e5104b added mapping without party 2026-03-13 17:20:08 +04:00
Ali 7ced7d18a5 fixed documents & reconcile option 2026-03-12 15:01:04 +04:00
Ali 2f05dfe8d3 hide same operations 2026-03-11 21:24:23 +04:00
Ali c674fed28b bug fix 2026-03-11 19:36:51 +04:00
Ali 5f440c1b66 changed the way that check works in brt 2026-03-11 18:38:46 +04:00
Ali d20435b587 bug fix] 2026-03-11 17:08:44 +04:00
Ali 1c002a5e87 Added create & reconcile to brt 2026-03-11 15:00:39 +04:00
Ali bced451359 reconsiliation tool modified 2026-03-10 19:47:52 +04:00