|
@ -462,32 +462,16 @@ class MisReport(models.Model): |
|
|
date_from, date_to, |
|
|
date_from, date_to, |
|
|
target_move, |
|
|
target_move, |
|
|
company, |
|
|
company, |
|
|
|
|
|
subkpi_ids, |
|
|
get_additional_move_line_filter=None, |
|
|
get_additional_move_line_filter=None, |
|
|
get_additional_query_filter=None, |
|
|
|
|
|
period_id=None): |
|
|
|
|
|
""" Evaluate a report for a given period. |
|
|
|
|
|
|
|
|
|
|
|
It returns a dictionary keyed on kpi.name with the following values: |
|
|
|
|
|
* val: the evaluated kpi, or None if there is no data or an error |
|
|
|
|
|
* val_r: the rendered kpi as a string, or #ERR, #DIV |
|
|
|
|
|
* val_c: a comment (explaining the error, typically) |
|
|
|
|
|
* style: the css style of the kpi |
|
|
|
|
|
(may change in the future!) |
|
|
|
|
|
* prefix: a prefix to display in front of the rendered value |
|
|
|
|
|
* suffix: a prefix to display after rendered value |
|
|
|
|
|
* dp: the decimal precision of the kpi |
|
|
|
|
|
* is_percentage: true if the kpi is of percentage type |
|
|
|
|
|
(may change in the future!) |
|
|
|
|
|
* expr: the kpi expression |
|
|
|
|
|
* drilldown: true if the drilldown method of |
|
|
|
|
|
mis.report.instance.period is going to do something |
|
|
|
|
|
useful in this kpi |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_additional_query_filter=None): |
|
|
|
|
|
""" Compute |
|
|
:param lang_id: id of a res.lang object |
|
|
:param lang_id: id of a res.lang object |
|
|
:param aep: an AccountingExpressionProcessor instance created |
|
|
:param aep: an AccountingExpressionProcessor instance created |
|
|
using _prepare_aep() |
|
|
using _prepare_aep() |
|
|
:param date_from, date_to: the starting and ending date |
|
|
:param date_from, date_to: the starting and ending date |
|
|
:param target_move: all|posted |
|
|
:param target_move: all|posted |
|
|
|
|
|
:param company: |
|
|
:param get_additional_move_line_filter: a bound method that takes |
|
|
:param get_additional_move_line_filter: a bound method that takes |
|
|
no arguments and returns |
|
|
no arguments and returns |
|
|
a domain compatible with |
|
|
a domain compatible with |
|
@ -496,9 +480,6 @@ class MisReport(models.Model): |
|
|
query argument and returns a |
|
|
query argument and returns a |
|
|
domain compatible with the query |
|
|
domain compatible with the query |
|
|
underlying model |
|
|
underlying model |
|
|
:param period_id: an optional opaque value that is returned as |
|
|
|
|
|
query_id field in the result (may change in the |
|
|
|
|
|
future!) |
|
|
|
|
|
""" |
|
|
""" |
|
|
self.ensure_one() |
|
|
self.ensure_one() |
|
|
res = {} |
|
|
res = {} |
|
@ -526,14 +507,13 @@ class MisReport(models.Model): |
|
|
|
|
|
|
|
|
compute_queue = self.kpi_ids |
|
|
compute_queue = self.kpi_ids |
|
|
recompute_queue = [] |
|
|
recompute_queue = [] |
|
|
period = self.env['mis.report.instance.period'].browse(period_id) |
|
|
|
|
|
while True: |
|
|
while True: |
|
|
for kpi in compute_queue: |
|
|
for kpi in compute_queue: |
|
|
vals = [] |
|
|
vals = [] |
|
|
has_error = False |
|
|
has_error = False |
|
|
for expression in kpi.expression_ids: |
|
|
for expression in kpi.expression_ids: |
|
|
if expression.subkpi_id \ |
|
|
if expression.subkpi_id \ |
|
|
and expression.subkpi_id not in period.subkpi_ids: |
|
|
|
|
|
|
|
|
and expression.subkpi_id not in subkpi_ids: |
|
|
continue |
|
|
continue |
|
|
try: |
|
|
try: |
|
|
kpi_eval_expression = aep.replace_expr(expression.name) |
|
|
kpi_eval_expression = aep.replace_expr(expression.name) |
|
@ -575,7 +555,7 @@ class MisReport(models.Model): |
|
|
# try again |
|
|
# try again |
|
|
compute_queue = recompute_queue |
|
|
compute_queue = recompute_queue |
|
|
recompute_queue = [] |
|
|
recompute_queue = [] |
|
|
return res |
|
|
|
|
|
|
|
|
return res, localdict |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MisReportInstancePeriod(models.Model): |
|
|
class MisReportInstancePeriod(models.Model): |
|
@ -736,20 +716,42 @@ class MisReportInstancePeriod(models.Model): |
|
|
return False |
|
|
return False |
|
|
|
|
|
|
|
|
@api.multi |
|
|
@api.multi |
|
|
def _render(self, data, lang_id): |
|
|
|
|
|
|
|
|
def _compute(self, lang_id, aep): |
|
|
|
|
|
""" Compute and render a mis report instance period |
|
|
|
|
|
|
|
|
|
|
|
It returns a dictionary keyed on kpi.name with a list of dictionaries |
|
|
|
|
|
with the following values (one item in the list for each subkpi): |
|
|
|
|
|
* val: the evaluated kpi, or None if there is no data or an error |
|
|
|
|
|
* val_r: the rendered kpi as a string, or #ERR, #DIV |
|
|
|
|
|
* val_c: a comment (explaining the error, typically) |
|
|
|
|
|
* style: the css style of the kpi |
|
|
|
|
|
(may change in the future!) |
|
|
|
|
|
* prefix: a prefix to display in front of the rendered value |
|
|
|
|
|
* suffix: a prefix to display after rendered value |
|
|
|
|
|
* dp: the decimal precision of the kpi |
|
|
|
|
|
* is_percentage: true if the kpi is of percentage type |
|
|
|
|
|
(may change in the future!) |
|
|
|
|
|
* expr: the kpi expression |
|
|
|
|
|
* drilldown: true if the drilldown method of |
|
|
|
|
|
mis.report.instance.period is going to do something |
|
|
|
|
|
useful in this kpi |
|
|
|
|
|
""" |
|
|
self.ensure_one() |
|
|
self.ensure_one() |
|
|
|
|
|
# first invoke the compute method on the mis report template |
|
|
|
|
|
# passing it all the information regarding period and filters |
|
|
|
|
|
data, localdict = self.report_instance_id.report_id._compute( |
|
|
|
|
|
lang_id, aep, |
|
|
|
|
|
self.date_from, self.date_to, |
|
|
|
|
|
self.report_instance_id.target_move, |
|
|
|
|
|
self.report_instance_id.company_id, |
|
|
|
|
|
self.subkpi_ids, |
|
|
|
|
|
self._get_additional_move_line_filter, |
|
|
|
|
|
self._get_additional_query_filter, |
|
|
|
|
|
) |
|
|
|
|
|
# second, render it to something that can be used by the widget |
|
|
res = {} |
|
|
res = {} |
|
|
if self.subkpi_ids: |
|
|
|
|
|
index2subkpi = { |
|
|
|
|
|
idx: subkpi.name |
|
|
|
|
|
for idx, subkpi in enumerate(self.subkpi_ids) |
|
|
|
|
|
} |
|
|
|
|
|
else: |
|
|
|
|
|
index2subkpi = {0: 'default'} |
|
|
|
|
|
|
|
|
|
|
|
for kpi, vals in data.items(): |
|
|
for kpi, vals in data.items(): |
|
|
res[kpi.name] = [] |
|
|
res[kpi.name] = [] |
|
|
# TODO FIXME localdict |
|
|
|
|
|
try: |
|
|
try: |
|
|
kpi_style = None |
|
|
kpi_style = None |
|
|
if kpi.css_style: |
|
|
if kpi.css_style: |
|
@ -775,10 +777,11 @@ class MisReportInstancePeriod(models.Model): |
|
|
'val': subkpi_val.name, |
|
|
'val': subkpi_val.name, |
|
|
'val_r': subkpi_val.name, |
|
|
'val_r': subkpi_val.name, |
|
|
'val_c': subkpi_val.msg, |
|
|
'val_c': subkpi_val.msg, |
|
|
'drilldown': None, |
|
|
|
|
|
|
|
|
'drilldown': False, |
|
|
}) |
|
|
}) |
|
|
else: |
|
|
else: |
|
|
drilldown = (subkpi_val is not None and |
|
|
|
|
|
|
|
|
# TODO FIXME: has_account_var on each subkpi expression? |
|
|
|
|
|
drilldown = (subkpi_val is not AccountingNone and |
|
|
AEP.has_account_var(kpi.expression)) |
|
|
AEP.has_account_var(kpi.expression)) |
|
|
if kpi.multi: |
|
|
if kpi.multi: |
|
|
expression = kpi.expression_ids[idx].name |
|
|
expression = kpi.expression_ids[idx].name |
|
@ -786,8 +789,9 @@ class MisReportInstancePeriod(models.Model): |
|
|
expression = kpi.expression |
|
|
expression = kpi.expression |
|
|
comment = kpi.name + " = " + expression |
|
|
comment = kpi.name + " = " + expression |
|
|
vals.update({ |
|
|
vals.update({ |
|
|
'val': None if subkpi_val is AccountingNone |
|
|
|
|
|
else subkpi_val, |
|
|
|
|
|
|
|
|
'val': (None |
|
|
|
|
|
if subkpi_val is AccountingNone |
|
|
|
|
|
else subkpi_val), |
|
|
'val_r': kpi.render(lang_id, subkpi_val), |
|
|
'val_r': kpi.render(lang_id, subkpi_val), |
|
|
'val_c': comment, |
|
|
'val_c': comment, |
|
|
'drilldown': drilldown, |
|
|
'drilldown': drilldown, |
|
@ -795,20 +799,6 @@ class MisReportInstancePeriod(models.Model): |
|
|
res[kpi.name].append(vals) |
|
|
res[kpi.name].append(vals) |
|
|
return res |
|
|
return res |
|
|
|
|
|
|
|
|
@api.multi |
|
|
|
|
|
def _compute(self, lang_id, aep): |
|
|
|
|
|
self.ensure_one() |
|
|
|
|
|
data = self.report_instance_id.report_id._compute( |
|
|
|
|
|
lang_id, aep, |
|
|
|
|
|
self.date_from, self.date_to, |
|
|
|
|
|
self.report_instance_id.target_move, |
|
|
|
|
|
self.report_instance_id.company_id, |
|
|
|
|
|
self._get_additional_move_line_filter, |
|
|
|
|
|
self._get_additional_query_filter, |
|
|
|
|
|
period_id=self.id, |
|
|
|
|
|
) |
|
|
|
|
|
return self._render(data, lang_id) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MisReportInstance(models.Model): |
|
|
class MisReportInstance(models.Model): |
|
|
"""The MIS report instance combines everything to compute |
|
|
"""The MIS report instance combines everything to compute |
|
@ -947,7 +937,7 @@ class MisReportInstance(models.Model): |
|
|
header = [{ |
|
|
header = [{ |
|
|
'kpi_name': '', |
|
|
'kpi_name': '', |
|
|
'cols': [] |
|
|
'cols': [] |
|
|
},{ |
|
|
|
|
|
|
|
|
}, { |
|
|
'kpi_name': '', |
|
|
'kpi_name': '', |
|
|
'cols': [] |
|
|
'cols': [] |
|
|
}] |
|
|
}] |
|
@ -976,17 +966,17 @@ class MisReportInstance(models.Model): |
|
|
header[0]['cols'].append(dict( |
|
|
header[0]['cols'].append(dict( |
|
|
name=period.name, |
|
|
name=period.name, |
|
|
date=header_date, |
|
|
date=header_date, |
|
|
colspan = len(period.subkpi_ids) or 1, |
|
|
|
|
|
|
|
|
colspan=len(period.subkpi_ids) or 1, |
|
|
)) |
|
|
)) |
|
|
for subkpi in period.subkpi_ids: |
|
|
for subkpi in period.subkpi_ids: |
|
|
header[1]['cols'].append(dict( |
|
|
header[1]['cols'].append(dict( |
|
|
name=subkpi.name, |
|
|
name=subkpi.name, |
|
|
colspan = 1, |
|
|
|
|
|
|
|
|
colspan=1, |
|
|
)) |
|
|
)) |
|
|
if not period.subkpi_ids: |
|
|
if not period.subkpi_ids: |
|
|
header[1]['cols'].append(dict( |
|
|
header[1]['cols'].append(dict( |
|
|
name="", |
|
|
name="", |
|
|
colspan = 1, |
|
|
|
|
|
|
|
|
colspan=1, |
|
|
)) |
|
|
)) |
|
|
# add kpi values |
|
|
# add kpi values |
|
|
kpi_values = kpi_values_by_period_ids[period.id] |
|
|
kpi_values = kpi_values_by_period_ids[period.id] |
|
|