Skip to content

feat(Bank Transaction): auto-book included bank fees (backport #346)#368

Draft
mergify[bot] wants to merge 5 commits into
version-16-hotfixfrom
mergify/bp/version-16-hotfix/pr-346
Draft

feat(Bank Transaction): auto-book included bank fees (backport #346)#368
mergify[bot] wants to merge 5 commits into
version-16-hotfixfrom
mergify/bp/version-16-hotfix/pr-346

Conversation

@mergify
Copy link
Copy Markdown
Contributor

@mergify mergify Bot commented May 20, 2026

Summary

Auto-book included bank fees on Bank Transaction submit (withdrawals) and at reconciliation time (deposits).

Withdrawals: On submit, a Journal Entry is created (Dr Bank Fees / Cr Bank) and allocated against the Bank Transaction, partially reconciling the fee portion.

Deposits: Fee booking is deferred to reconciliation, where the correct counter-account (e.g. receivable) is known. The reconciliation tool matches deposits using deposit + included_fee as the target amount, so the right vouchers are found. At reconciliation:

  • Single-currency: A Journal Entry settles both the fee and the invoice in one entry (Dr Bank, Dr Bank Fees / Cr Receivable)
  • Multi-currency: A Payment Entry is created with a deduction row for the fee. The system exchange rate determines exchange gain/loss separately from the fee.

Configuration

  • New Bank Fee Account field on Bank Account (Link to Expense account, same currency)
  • New Enable Automatic Journal Entries for Bank Fees checkbox in Banking Settings
  • All company Bank Accounts must have a fee account before the feature can be enabled

Depends on

Test plan

  • Submit withdrawal with included fee → fee JE created and allocated
  • Submit deposit with included fee → no fee JE created
  • Reconcile single-currency deposit with fee against Sales Invoice → JE with bank + fee rows, invoice fully cleared
  • Reconcile multi-currency deposit with fee against foreign invoice → PE with fee deduction, exchange gain/loss handled separately
  • Feature disabled → no fee JE on submit, no fee handling at reconciliation
  • Bank Account without fee account rejects save when feature is enabled
  • Currency mismatch between bank account and fee account is rejected
  • Cancel Bank Transaction → linked fee JEs are cancelled
  • Fee larger than withdrawal is rejected
    This is an automatic backport of pull request feat(Bank Transaction): auto-book included bank fees #346 done by Mergify.

Greptile Summary

This PR implements automatic bank-fee booking on Bank Transaction submit (withdrawals) and reconciliation (deposits), adding a bank_fee_account field to Bank Account and a global feature toggle in Banking Settings.

  • Withdrawals: a system-generated fee JE (Dr Bank Fees / Cr Bank) is created on submit and allocated against the BT, with create_je_automatic_rules correctly recalculating remaining_amount to account for the pre-allocated fee.
  • Deposits: fee booking is deferred to reconciliation; the matching query is expanded by included_fee so full-invoice vouchers are found; single-currency paths use a JE, multi-currency (company-currency bank) paths use a PE deduction row, and foreign-currency bank accounts raise CurrencyMismatchError.
  • Configuration guards: Bank Account validate blocks currency mismatch and missing fee accounts when the feature is enabled; Banking Settings validate blocks enabling the feature while any company bank account lacks a fee account.

Confidence Score: 4/5

The core withdrawal and deposit fee-booking paths are well-tested and logically sound; a previously-reported unresolved issue means the fee is silently dropped for manual-rate reconciliation of deposits.

The new accounting logic is well-covered by tests and the guard rails (currency checks, full-reconciliation enforcement, feature-flag gating) are solid. However, an open finding from the prior review — that make_pe_against_invoices is called without included_fee when manual_reconcile_amounts is provided — remains unaddressed. A deposit with an included fee reconciled via the manual-FX dialog will post the PE without the fee deduction, silently under-expensing to the fee account and leaving the ledger incorrect for any treasury team using statement-rate reconciliation.

banking/klarna_kosma_integration/doctype/bank_reconciliation_tool_beta/unpaid_vouchers.py — the manual-reconcile branch in get_payment_entries and the multi-party + foreign-currency-invoice edge case in make_jv_against_invoices.

Important Files Changed

Filename Overview
banking/overrides/bank_transaction.py New before_submit/create_je_bank_fees logic for withdrawal fee JEs; contains a dead-code branch (if credit > 0) that is unreachable but otherwise sound.
banking/klarna_kosma_integration/doctype/bank_reconciliation_tool_beta/unpaid_vouchers.py Core deposit-side fee reconciliation logic; single-currency JV and multi-currency PE paths are covered; reconcile_multi_party + included_fee against a foreign-currency invoice with a company-currency bank account will hit an internal JV currency error instead of a clear user message.
banking/klarna_kosma_integration/doctype/banking_settings/banking_settings.py Adds validation to block enabling the feature when any company bank account lacks a fee account; error message is missing the list of offending accounts, making remediation harder.
banking/overrides/bank_account.py New validate hook: enforces currency match between bank account and fee account, and blocks saving a company bank account without a fee account when the feature is enabled.
banking/klarna_kosma_integration/doctype/bank_reconciliation_tool_beta/bank_reconciliation_tool_beta.py matching_amount now includes deposit included_fee; JE exclusion logic replaced with more precise ExistsCriterion-based filter so auto-fee JEs reappear after unreconciliation.
banking/custom/bank_transaction.js Adds two headline banners on submitted BTs: one for zero-amount + fee transactions, one for foreign-currency deposits with fees.
banking/testing_utils.py Clean helpers for tests: set_automatic_bank_fee_entries, enriched create_bank_account/create_bank_transaction helpers; no conflict markers remain.

Sequence Diagram

sequenceDiagram
    participant BT as Bank Transaction
    participant BS as Banking Settings
    participant BA as Bank Account
    participant JE as Journal Entry
    participant PE as Payment Entry
    participant UV as unpaid_vouchers

    Note over BT: WITHDRAWAL FLOW
    BT->>BS: before_submit: check enable_automatic_journal_entries?
    BS-->>BT: "enabled=True"
    BT->>BA: get bank_fee_account
    BA-->>BT: fee_account
    BT->>JE: create_je_bank_fees (Dr BankFees / Cr Bank)
    JE-->>BT: fee_je_name + clearance_date set
    BT->>BT: append fee_je to payment_entries
    BT->>BT: recompute unallocated_amount

    Note over BT: DEPOSIT FLOW (deferred to reconciliation)
    BT->>UV: bulk_reconcile_vouchers → get_payment_entries
    UV->>UV: get_deposit_included_fee(bt)
    UV->>UV: validate_included_fee_reconciliation
    alt single-currency invoice
        UV->>JE: "make_jv_against_invoices(included_fee=fee)"
        Note right of JE: Dr Bank (deposit) + Dr BankFees (fee) / Cr Receivable (full)
    else multi-currency invoice (company-currency bank)
        UV->>PE: "make_pe_against_invoices(included_fee=fee)"
        Note right of PE: PE with fee deduction row
    else foreign-currency bank account
        UV-->>BT: CurrencyMismatchError
    end

    Note over BT: MATCHING QUERY
    BT->>UV: check_matching
    UV->>UV: "matching_amount = unallocated + get_deposit_included_fee"
    Note right of UV: Searches vouchers for deposit+fee amount

    Note over BT: CANCEL FLOW
    BT->>JE: on_cancel: cancel system-generated JEs with BT reference
Loading

Comments Outside Diff (1)

  1. banking/klarna_kosma_integration/doctype/bank_reconciliation_tool_beta/unpaid_vouchers.py, line 74-86 (link)

    P1 Included fee silently dropped during manual reconciliation

    When manual_reconcile_amounts is non-empty and included_fee > 0, the code falls into the else branch where make_pe_against_invoices is called without the included_fee argument (defaults to 0.0). validate_included_fee_reconciliation runs and passes without blocking this path, so the user receives no warning. The resulting Payment Entry settles the invoice but never records the bank-fee expense to the configured fee account, leaving the ledger incorrect for any manual-rate reconciliation on a deposit BT that carries a fee.

    Fix in Cursor

Fix All in Cursor

Reviews (2): Last reviewed commit: "style: format js file" | Re-trigger Greptile

* feat(Bank Transaction): auto-book included bank fees

Add bank fee account configuration and create fee Journal Entries on bank transaction submission so included fees are recognized immediately and reconciled correctly.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(Bank Transaction): make automatic fee booking optional

Guard included-fee Journal Entry creation behind a Banking Settings flag so existing sites without bank fee account setup continue to work until the feature is explicitly enabled.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(Banking Settings): bump modified timestamp for model sync

Update the DocType JSON modified timestamp so the controller change is picked up reliably during model sync.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(Bank Transaction): validate withdrawal against included fee

Reject withdrawal transactions where included fee exceeds withdrawal amount, while still allowing fee handling when deposit is not set.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: bump min required erp version

we depend on frappe/erpnext#52760

* fix: Cancel only fee JEs created by this feature

* fix: use bank date as clearance_date

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* test: cover disabled automatic bank fee entries

Ensure a Bank Transaction can be submitted without a bank fee account
when automatic bank fee journal entries are disabled, and assert that
no linked fee Journal Entry is created.

* fix(banking): enforce fee account setup for automatic bank fee entries

Prevent automatic bank fee journal entries from being enabled until every company Bank Account has a bank fee account, and reject company bank accounts without one while the feature is enabled.

* test: submitting a withdrawal with an included fee must create and reconcile the fee JE

* fix: keep deposit fee journal entries out of bank reconciliation

Create fee Journal Entries for deposit Bank Transactions with included fees, but do not add them to payment entries because the fee is already deducted before the bank credits the deposit. Semantically, a row in Bank Transaction would say "this JE is allocatable against the bank amount later", which is exactly what we don’t want for a deposit fee. Add regression coverage for included-fee deposit and withdrawal flows.

* fix: distinguish fee and custom journal entries in bank reconciliation

Keep cheque_no-linked custom journal entries hidden from matching while
excluding standard fee journal entries only for deposit transactions.

This lets unreconciled withdrawal fee journal entries be offered again.

* fix: preserve existing allocations for included bank fees

Recompute `allocated_amount` and `unallocated_amount` from `payment_entries` after appending the fee journal entry, so prior allocations are not lost. Add a regression test covering fee entry creation when an allocation already exists.

* refactor: centralize common testing utils

* fix: book fee on deposits during reconciliation

* fix: remove obsolete code and test

Since we no longer create fee JEs for deposits, there's nothing to exclude from matching. The test was validating behavior that no longer exists.

* test: update fee account names

This test now creates its own GL account (_Test Bank Fee Reco GL) instead of reusing self.gl_account, avoiding the "account already used by another bank account" error.

* fix: backfill party and reference on included-fee reconciliation JEs

* fix: respect feature-flag

* fix: require full reconciliation for included deposit fees

Prevent deposit-side included bank fees from being applied more than once by rejecting partial or follow-up voucher reconciliation for fee-bearing Bank Transactions.

* fix: round values before comparison

* fix(Bank Transaction): flag zero-amount included fees

Log unsupported zero-amount Bank Transactions with included fees and surface the issue in the form so users can review them manually.

* test: cancel Bank Transaction cancels linked fee Journal Entry

* fix: foreign currency-fee

* test: simplify test names

* refactor: test error types, not messages

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
(cherry picked from commit 3b3cf37)

# Conflicts:
#	banking/klarna_kosma_integration/doctype/bank_reconciliation_tool_beta/unpaid_vouchers.py
#	banking/overrides/bank_transaction.py
#	banking/testing_utils.py
#	pyproject.toml
@mergify mergify Bot added the conflicts label May 20, 2026
@mergify

This comment was marked as resolved.

@barredterra barredterra marked this pull request as draft May 20, 2026 23:39
Comment thread pyproject.toml Outdated
Comment thread banking/overrides/bank_transaction.py Outdated
Comment thread banking/testing_utils.py Outdated
@barredterra
Copy link
Copy Markdown
Member

@greptileai

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant