diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index e8d61edd853..4fd66c8cb28 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -2440,6 +2440,10 @@ class AccountMoveLine(models.Model):
currency_field='company_currency_id',
compute='_compute_balance',
help="Technical field holding the debit - credit in order to open meaningful graph views from reports")
+ cumulated_balance = fields.Monetary(string='Cumulated Balance', store=False,
+ currency_field='company_currency_id',
+ compute='_compute_cumulated_balance',
+ help="Cumulated balance depending on the domain and the order chosen in the view.")
amount_currency = fields.Monetary(string='Amount in Currency', store=True, copy=True,
help="The amount expressed in an optional other currency if it is a multi-currency entry.")
price_subtotal = fields.Monetary(string='Subtotal', store=True, readonly=True,
@@ -2999,6 +3003,39 @@ class AccountMoveLine(models.Model):
for line in self:
line.balance = line.debit - line.credit
+ @api.model
+ def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None):
+ def to_tuple(t):
+ return tuple(map(to_tuple, t)) if isinstance(t, (list, tuple)) else t
+ # Make an explicit order because we will need to reverse it
+ order = (order or self._order) + ', id'
+ # Add the domain and order by in order to compute the cumulated balance in _compute_cumulated_balance
+ return super(AccountMoveLine, self.with_context(domain_cumulated_balance=to_tuple(domain or []), order_cumulated_balance=order)).search_read(domain, fields, offset, limit, order)
+
+ @api.depends_context('order_cumulated_balance', 'domain_cumulated_balance')
+ def _compute_cumulated_balance(self):
+ if not self.env.context.get('order_cumulated_balance'):
+ # We do not come from search_read, so we are not in a list view, so it doesn't make any sense to compute the cumulated balance
+ self.cumulated_balance = 0
+ return
+
+ # get the where clause
+ query = self._where_calc(self.env.context.get('domain_cumulated_balance'))
+ order_string = ", ".join(self._generate_order_by_inner(self._table, self.env.context.get('order_cumulated_balance'), query, reverse_direction=True))
+ from_clause, where_clause, where_clause_params = query.get_sql()
+ sql = """
+ SELECT account_move_line.id, SUM(account_move_line.balance) OVER (
+ ORDER BY %(order_by)s
+ ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+ )
+ FROM %(from)s
+ WHERE %(where)s
+ """ % {'from': from_clause, 'where': where_clause, 'order_by': order_string}
+ self.env.cr.execute(sql, where_clause_params)
+ result = {r[0]: r[1] for r in self.env.cr.fetchall()}
+ for record in self:
+ record.cumulated_balance = result[record.id]
+
@api.depends('debit', 'credit', 'account_id', 'amount_currency', 'currency_id', 'matched_debit_ids', 'matched_credit_ids', 'matched_debit_ids.amount', 'matched_credit_ids.amount', 'move_id.state', 'company_id')
def _amount_residual(self):
""" Computes the residual amount of a move line from a reconcilable account in the company currency and the line's currency.
diff --git a/addons/account/views/account_move_views.xml b/addons/account/views/account_move_views.xml
index 0494b0fb8be..e9c2c128036 100644
--- a/addons/account/views/account_move_views.xml
+++ b/addons/account/views/account_move_views.xml
@@ -186,6 +186,7 @@
+
@@ -254,6 +255,10 @@
hide
1
+ show
+
+
+
@@ -266,6 +271,10 @@
hide
show
+ show
+
+
+