forked from Mapan/odoo17e
100 lines
4.2 KiB
Python
100 lines
4.2 KiB
Python
from math import copysign
|
|
|
|
from odoo import _
|
|
from odoo.tools.float_utils import float_is_zero
|
|
from .abstract import AbstractBuilder
|
|
|
|
|
|
class ComparisonBuilder(AbstractBuilder):
|
|
# OVERRIDES
|
|
def _get_params(self, period_ids: list, options: dict, line_id: str = None) -> dict:
|
|
chart_ids = self.env['consolidation.chart'].search([('period_ids', 'in', period_ids)]).ids
|
|
cols_amount = len(period_ids)
|
|
include_percentage = cols_amount == 2
|
|
params = super()._get_params(period_ids, options, line_id)
|
|
params.update({
|
|
'chart_ids': chart_ids,
|
|
'cols_amount': cols_amount,
|
|
'include_percentage': include_percentage,
|
|
})
|
|
return params
|
|
|
|
def _output_will_be_empty(self, period_ids: list, options: dict, line_id: str = None) -> bool:
|
|
return len(period_ids) == 0
|
|
|
|
def _compute_account_totals(self, account, **kwargs) -> list:
|
|
domain = [
|
|
('account_id', '=', account.id),
|
|
('period_id', 'in', kwargs.get('period_ids', []))
|
|
]
|
|
total_lines = self.env['consolidation.journal.line']._read_group(domain, ['period_id'], ['amount:sum'])
|
|
if len(total_lines) == 0:
|
|
return []
|
|
totals = []
|
|
total_dict = {period.id: total for period, total in total_lines}
|
|
# Need to keep the order of periods as nothing in DB can order them
|
|
for period_id in kwargs.get('period_ids', []):
|
|
totals.append(account.sign * total_dict.get(period_id, 0.0))
|
|
return totals
|
|
|
|
def _get_default_line_totals(self, options: dict, **kwargs) -> list:
|
|
return kwargs.get('cols_amount', len(kwargs.get('period_ids', []))) * [0.0]
|
|
|
|
def _format_account_line(self, account, parent_id, level: int, totals: list, options: dict, **kwargs) -> dict:
|
|
account_line = super()._format_account_line(account, parent_id, level, totals, options, **kwargs)
|
|
if kwargs.get('include_percentage', False) and totals and account_line:
|
|
account_line['columns'].append(self._build_percentage_column(*totals))
|
|
return account_line
|
|
|
|
def _build_section_line(self, section, level: int, options: dict, **kwargs):
|
|
section_totals, section_lines = super()._build_section_line(section, level, options, **kwargs)
|
|
if kwargs.get('include_percentage', False) and section_totals and section_lines:
|
|
section_lines[0]['columns'].append(self._build_percentage_column(*section_totals))
|
|
return section_totals, section_lines
|
|
|
|
def _build_total_line(self, totals: list, options: dict, **kwargs) -> dict:
|
|
total_line = super()._build_total_line(totals, options, **kwargs)
|
|
if kwargs.get('include_percentage', False) and total_line and totals:
|
|
total_line['columns'].append(self._build_percentage_column(*totals))
|
|
return total_line
|
|
|
|
@staticmethod
|
|
def _build_percentage_column(orig_value: float, now_value: float) -> dict:
|
|
"""
|
|
Build the percentage column based on the two given values
|
|
:param orig_value: the original value
|
|
:type orig_value: float
|
|
:param now_value: the value of now
|
|
:type now_value: float
|
|
:return: a formatted dict containing the percentage increase between the two given values and ready to be added
|
|
as a column inside a report line
|
|
:rtype: dict
|
|
"""
|
|
if not float_is_zero(orig_value, 6):
|
|
res = round((now_value - orig_value) / orig_value * 100, 1)
|
|
classes = ['number']
|
|
|
|
if float_is_zero(res, precision_rounding=0.1):
|
|
val = 0.0
|
|
elif (res > 0) == (orig_value > 0):
|
|
classes.append('color-green')
|
|
val = copysign(res, 1)
|
|
else:
|
|
classes.append('color-red')
|
|
val = copysign(res, -1)
|
|
return {
|
|
'name': ('%s%%' % val),
|
|
'no_format': val,
|
|
'figure_type': 'percentage',
|
|
'class': ' '.join(classes)
|
|
}
|
|
# res > 0
|
|
# orig > 0 :: GREEN
|
|
# orig < 0 :: RED
|
|
# res < 0
|
|
# orig < 0 :: GREEN
|
|
# orig > 0 :: RED
|
|
|
|
else:
|
|
return {'name': _('n/a'), 'figure_type': 'percentage'}
|