fix: target actual bank.rec.widget (OWL) instead of legacy reconciliation widget — implement rest_debit/rest_credit fields + template extension

This commit is contained in:
Kristof Bernaert
2026-08-10 20:50:58 +02:00
parent 2a99ecbe5b
commit 277b38a0e9
7 changed files with 105 additions and 94 deletions
@@ -2,15 +2,15 @@
## Overview ## Overview
`dlv_account_reconciliation_rest_amount` extends the standard bank `dlv_account_reconciliation_rest_amount` extends the bank reconciliation
reconciliation screen (Accounting → Reconciliation) so the still-open widget (Accounting → Reconciliation, model `bank.rec.widget`) so the still
("rest") amount of a line is shown in parentheses next to its total. outstanding ("rest") amount of a partially matched line is shown in
parentheses next to its total.
On the reconciliation screen, when a proposed line (the bank movement itself, On the reconciliation screen, when an added invoice/bill (a `new_aml` line)
or an added invoice/bill) is only partially used to close the statement line, is only partially used to close the statement line, Odoo shows the full
Odoo shows the full amount struck through and the partial amount used above source amount struck through below the amount actually used — but not what
it — but not what remains unmatched on that line. This addon adds that remains unmatched on that line. This addon adds that missing number, e.g.:
missing number, e.g.:
``` ```
€ 1.899,97 € 1.899,97
@@ -22,19 +22,27 @@ outstanding, without having to search for it elsewhere.
## How it works ## How it works
- `static/src/js/reconciliation_rest_amount.js` patches - `models/bank_rec_widget_line.py` inherits `bank.rec.widget.line` and adds
`account.ReconciliationRenderer`'s `ManualLineRenderer.update()`. Before two computed `Monetary` fields, `rest_debit` and `rest_credit`
every render, it walks `state.reconciliation_proposition` and, for any line (`source_balance - balance`, split like the existing `debit`/`credit`
where `partial_amount` differs from `amount`, computes and formats the fields). Because `bank.rec.widget._compute_lines_widget` automatically
difference as `line.rest_amount_str`. serializes every field of `bank.rec.widget.line` to the front-end, these
- `static/src/xml/reconciliation_rest_amount.xml` inherits the shared two fields become available client-side as `line.rest_debit` /
`reconciliation.line.mv_line.amount` template (from `account_accountant`) `line.rest_credit` (each with `.display`, `.value`, `.is_zero`) with no
via xpath and prints `line.rest_amount_str` between parentheses, right extra plumbing needed.
after the existing amount. - `static/src/xml/reconciliation_rest_amount.xml` extends the OWL template
`account_accountant.bank_rec_widget_form_lines_widget`
(`t-inherit-mode="extension"`) and prints the rest amount in parentheses
next to the struck-through source amount, when it is non-zero.
Because both the bank movement (liquidity line) and any added invoice/bill ### Note on the bank movement itself
proposition are rendered through the same loop and template, this single
patch covers both cases. Earlier iterations of this addon assumed the bank movement (liquidity) line
could also show a "rest" amount, based on the legacy (pre-16.4) reconciliation
widget where that concept existed. In the `bank.rec.widget` model actually
used on this instance, the liquidity line always reflects the full statement
line amount — there is no partial/rest concept for it, so nothing is shown
there. See ROADMAP.md.
## Dependencies ## Dependencies
@@ -42,5 +50,6 @@ patch covers both cases.
## Installation ## Installation
Standard addon install/update. No configuration or data is added; the change Standard addon install/update (`-u dlv_account_reconciliation_rest_amount`).
is purely visual on the existing reconciliation widget. No configuration or data is added; the change is a new computed field plus a
purely visual template extension on the existing reconciliation widget.
@@ -0,0 +1 @@
from . import models
@@ -4,11 +4,10 @@
"summary": "Toon het restbedrag tussen haakjes op het afletterscherm " "summary": "Toon het restbedrag tussen haakjes op het afletterscherm "
"(bank reconciliatie)", "(bank reconciliatie)",
"description": """ "description": """
Voegt het restbedrag (verschil tussen het oorspronkelijke bedrag en het reeds Voegt het restbedrag (verschil tussen het volledige bronbedrag en het bedrag
afgeletterde/toegewezen bedrag) tussen haakjes toe aan het bank-afletterscherm, dat effectief wordt ingezet) tussen haakjes toe op het bank-afletterscherm
zowel bij de regel van het bankafschrift (liquidity-line) als bij de (bank.rec.widget), naast een gedeeltelijk gematchte afletteringsregel
voorgestelde afletteringsregels (bestaande boekingen) die niet volledig (bv. een factuur waarvan niet het volledige bedrag wordt gebruikt).
worden ingezet.
""", """,
"author": "bv Domus La Vila", "author": "bv Domus La Vila",
"website": "https://domuslavila.eu", "website": "https://domuslavila.eu",
@@ -19,7 +18,6 @@ worden ingezet.
"data": [], "data": [],
"assets": { "assets": {
"web.assets_backend": [ "web.assets_backend": [
"dlv_account_reconciliation_rest_amount/static/src/js/*.js",
"dlv_account_reconciliation_rest_amount/static/src/xml/*.xml", "dlv_account_reconciliation_rest_amount/static/src/xml/*.xml",
], ],
}, },
@@ -0,0 +1 @@
from . import bank_rec_widget_line
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models
class BankRecWidgetLine(models.Model):
_inherit = "bank.rec.widget.line"
# Restbedrag = het verschil tussen het volledige (bron)bedrag van de
# boeking en het bedrag dat effectief wordt ingezet om af te letteren.
# Enkel relevant wanneer de boeking niet volledig wordt gebruikt
# (zie display_stroked_balance / flag == 'new_aml').
#
# Elk veld op dit model wordt automatisch geserialiseerd naar de
# 'lines_widget' data (zie bank_rec_widget._compute_lines_widget), dus
# deze twee velden komen vanzelf beschikbaar in de front-end als
# line.rest_debit / line.rest_credit (met .display, .value, .is_zero).
rest_debit = fields.Monetary(
currency_field="company_currency_id",
compute="_compute_dlv_rest_amount",
)
rest_credit = fields.Monetary(
currency_field="company_currency_id",
compute="_compute_dlv_rest_amount",
)
@api.depends("balance", "source_balance")
def _compute_dlv_rest_amount(self):
for line in self:
rest = line.source_balance - line.balance
line.rest_debit = rest if rest > 0.0 else 0.0
line.rest_credit = -rest if rest < 0.0 else 0.0
@@ -1,55 +1,18 @@
odoo.define('dlv_account_reconciliation_rest_amount.reconciliation_renderer', function (require) {
"use strict";
/** /**
* Toont het restbedrag (het verschil tussen het volledige bedrag van een * DEPRECATED / unused on this Odoo instance.
* regel en het bedrag dat effectief wordt ingezet om af te letteren) tussen
* haakjes op het afletterscherm.
* *
* Dit geldt zowel voor de bankbeweging zelf (de liquidity-line) als voor een * This file used to patch the legacy `account.ReconciliationRenderer`
* toegevoegde boeking (bv. een aankoopfactuur) waarvan niet het volledige * widget (static/src/js/reconciliation/reconciliation_renderer.js in
* bedrag wordt gebruikt (line.partial_amount != line.amount). * account_accountant), which turned out not to be the widget actually used
*/ * on this server. The real reconciliation screen here is the newer OWL
* `bank.rec.widget` (see views/bank_rec_widget_views.xml and
var ReconciliationRenderer = require('account.ReconciliationRenderer'); * static/src/components/bank_reconciliation/ in account_accountant).
var field_utils = require('web.field_utils');
ReconciliationRenderer.ManualLineRenderer.include({
/**
* @override
*/
update: function (state) {
this._computeRestAmounts(state);
return this._super.apply(this, arguments);
},
/**
* Berekent, voor elke regel in de afletteringsvoorstellen die slechts
* gedeeltelijk wordt ingezet, het nog resterende (niet-afgeletterde)
* bedrag en formatteert dit als rest_amount_str.
* *
* @private * The rest-amount feature is now implemented server-side on
* @param {Object} state * models/bank_rec_widget_line.py (rest_debit / rest_credit fields) and
* rendered via static/src/xml/reconciliation_rest_amount.xml, which
* extends `account_accountant.bank_rec_widget_form_lines_widget`.
*
* Kept as an empty file (rather than deleted) because files in this
* workspace folder cannot be removed once written.
*/ */
_computeRestAmounts: function (state) {
var format_options = {currency_id: state.st_line.currency_id};
_.each(state.reconciliation_proposition, function (line) {
if (!line) {
return;
}
var hasPartialAmount = line.partial_amount && Math.abs(line.partial_amount) !== Math.abs(line.amount);
if (hasPartialAmount) {
var rest = Math.abs(line.amount) - Math.abs(line.partial_amount);
line.rest_amount = rest;
line.rest_amount_str = field_utils.format.monetary(rest, {}, format_options);
} else {
delete line.rest_amount;
delete line.rest_amount_str;
}
});
},
});
});
@@ -2,23 +2,31 @@
<templates xml:space="preserve"> <templates xml:space="preserve">
<!-- <!--
Voegt het restbedrag (line.rest_amount_str, berekend in Voegt het restbedrag (line.rest_debit / line.rest_credit, berekend in
reconciliation_rest_amount.js) tussen haakjes toe naast het bedrag models/bank_rec_widget_line.py) tussen haakjes toe naast het
van een afletteringsregel. Geldt zowel voor de bankbeweging doorgestreepte bronbedrag van een afletteringsregel die niet
(liquidity-line) als voor een toegevoegde boeking waarvan niet het volledig wordt ingezet (bv. een gedeeltelijk gematchte factuur).
volledige bedrag wordt ingezet.
Origineel template: reconciliation.line.mv_line.amount Origineel template: account_accountant.bank_rec_widget_form_lines_widget
(enterprise-sys/account_accountant/static/src/xml/account_reconciliation.xml) (enterprise-sys/account_accountant/static/src/components/bank_reconciliation/bank_rec_widget.xml)
Dit is een legacy widget-template (gerenderd via core.qweb.render, Dit is een echt OWL-template, dus we breiden het uit via
geen OWL), dus we breiden ze uit met de oude t-extend/t-jquery t-inherit-mode="extension" + <xpath>, zodat de patch automatisch
syntax in plaats van <xpath>. toegepast wordt zonder de JS-component te moeten aanpassen.
--> -->
<t t-extend="reconciliation.line.mv_line.amount"> <t t-name="dlv_account_reconciliation_rest_amount.bank_rec_widget_form_lines_widget"
<t t-jquery="span.line_amount:last" t-operation="after"> t-inherit="account_accountant.bank_rec_widget_form_lines_widget"
<span t-if="line.rest_amount_str" class="dlv_rest_amount text-muted" title="Nog te matchen"> (<t t-out="line.rest_amount_str"/>)</span> t-inherit-mode="extension"
</t> owl="1">
<xpath expr="(//td[@field='debit'])[2]" position="inside">
<span t-if="!line.rest_debit.is_zero" class="dlv_rest_amount text-muted ms-1" title="Nog te matchen"> (<t t-out="line.rest_debit.display"/>)</span>
</xpath>
<xpath expr="(//td[@field='credit'])[2]" position="inside">
<span t-if="!line.rest_credit.is_zero" class="dlv_rest_amount text-muted ms-1" title="Nog te matchen"> (<t t-out="line.rest_credit.display"/>)</span>
</xpath>
</t> </t>
</templates> </templates>