Files
enterprise-addons/account_accountant/models/analytic_mixin.py
T

70 lines
2.8 KiB
Python

from odoo import api, models
from odoo.fields import Domain
class AnalyticMixin(models.AbstractModel):
_inherit = 'analytic.mixin'
@api.model
def _read_group_for_accrual(self, domain, groupby=(), aggregates=(), having=(), offset=0, limit=None, order=None) -> list[tuple]:
""" This method is called instead of usual `_read_group` to compute the
sum of non-storedcomputed fields. It's used in the accrual views,
by `purchase.order.line` and `sale.order.line` models.
"""
aggregates_to_skip, fields_to_patch = self._get_aggregates_to_skip_and_fields_to_patch()
fields_index = {}
for field in fields_to_patch:
field_aggregate = f'{field}:sum'
if field_aggregate in aggregates:
fields_index[field] = aggregates.index(field_aggregate)
if not fields_index.keys():
return super()._read_group(domain, groupby, aggregates, having, offset, limit, order)
aggregates_2_0 = tuple(a for a in aggregates if a not in aggregates_to_skip)
res = super()._read_group(domain, groupby, aggregates_2_0, having, offset, limit, order)
# Make the aggregate sum "manually".
# Pre-fetch all matching records once outside the loop to avoid re-evaluating
# expensive search methods on every group iteration.
field_name = groupby[0]
date_granularity = ''
if ':' in field_name:
# Support of group by date fields.
field_name, date_granularity = field_name.split(':')
all_records = self.env[self._name].search_fetch(
domain=Domain.AND([domain, self._get_accrual_domain()]),
field_names=[field_name],
)
if date_granularity:
records_by_group = dict(
all_records._read_group(
domain=[('id', 'in', all_records.ids)],
groupby=groupby,
aggregates=['id:recordset'],
)
)
else:
records_by_group = all_records.grouped(field_name)
patched_res = []
for group in res:
records = records_by_group.get(group[0], all_records.browse())
new_tuple = list(group)
for field, index in fields_index.items():
sum_qty_received = sum(rec[field] for rec in records)
new_tuple.insert(index + 1, sum_qty_received)
patched_res.append(tuple(new_tuple))
return patched_res
@api.model
def _get_accrual_domain(self):
return [('product_id', '!=', False)]
@api.model
def _get_aggregates_to_skip_and_fields_to_patch(self):
return (
['qty_invoiced_at_date:sum', 'amount_to_invoice_at_date:sum'],
['qty_invoiced_at_date', 'amount_to_invoice_at_date']
)