[WIP] mis_builder refactoring: restore drilldown with support for account details
parent
d287d34748
commit
d2bc009961
|
@ -165,7 +165,8 @@ class AccountingExpressionProcessor(object):
|
||||||
|
|
||||||
def get_aml_domain_for_expr(self, expr,
|
def get_aml_domain_for_expr(self, expr,
|
||||||
date_from, date_to,
|
date_from, date_to,
|
||||||
target_move, company):
|
target_move, company,
|
||||||
|
account_id=None):
|
||||||
""" Get a domain on account.move.line for an expression.
|
""" Get a domain on account.move.line for an expression.
|
||||||
|
|
||||||
Prerequisite: done_parsing() must have been invoked.
|
Prerequisite: done_parsing() must have been invoked.
|
||||||
|
@ -180,7 +181,14 @@ class AccountingExpressionProcessor(object):
|
||||||
account_ids = set()
|
account_ids = set()
|
||||||
for account_code in account_codes:
|
for account_code in account_codes:
|
||||||
account_ids.update(self._account_ids_by_code[account_code])
|
account_ids.update(self._account_ids_by_code[account_code])
|
||||||
|
if not account_id:
|
||||||
aml_domain.append(('account_id', 'in', tuple(account_ids)))
|
aml_domain.append(('account_id', 'in', tuple(account_ids)))
|
||||||
|
else:
|
||||||
|
# filter on account_id
|
||||||
|
if account_id in account_ids:
|
||||||
|
aml_domain.append(('account_id', '=', account_id))
|
||||||
|
else:
|
||||||
|
continue
|
||||||
if field == 'crd':
|
if field == 'crd':
|
||||||
aml_domain.append(('credit', '>', 0))
|
aml_domain.append(('credit', '>', 0))
|
||||||
elif field == 'deb':
|
elif field == 'deb':
|
||||||
|
@ -191,6 +199,7 @@ class AccountingExpressionProcessor(object):
|
||||||
self.get_aml_domain_for_dates(date_from, date_to,
|
self.get_aml_domain_for_dates(date_from, date_to,
|
||||||
mode, target_move,
|
mode, target_move,
|
||||||
company)
|
company)
|
||||||
|
assert aml_domains
|
||||||
return expression.OR(aml_domains) + \
|
return expression.OR(aml_domains) + \
|
||||||
expression.OR(date_domain_by_mode.values())
|
expression.OR(date_domain_by_mode.values())
|
||||||
|
|
||||||
|
|
|
@ -134,14 +134,14 @@ class KpiMatrixCell(object):
|
||||||
|
|
||||||
def __init__(self, row, subcol,
|
def __init__(self, row, subcol,
|
||||||
val, val_rendered, val_comment,
|
val, val_rendered, val_comment,
|
||||||
style=None, drilldown_key=None):
|
style=None, drilldown_arg=None):
|
||||||
self.row = row
|
self.row = row
|
||||||
self.subcol = subcol
|
self.subcol = subcol
|
||||||
self.val = val
|
self.val = val
|
||||||
self.val_rendered = val_rendered
|
self.val_rendered = val_rendered
|
||||||
self.val_comment = val_comment
|
self.val_comment = val_comment
|
||||||
self.style = style
|
self.style = style
|
||||||
self.drilldown_key = None
|
self.drilldown_arg = drilldown_arg
|
||||||
|
|
||||||
|
|
||||||
class KpiMatrix(object):
|
class KpiMatrix(object):
|
||||||
|
@ -191,14 +191,17 @@ class KpiMatrix(object):
|
||||||
self._comparison_todo[last_period_key].append(
|
self._comparison_todo[last_period_key].append(
|
||||||
(period_key, base_period_key))
|
(period_key, base_period_key))
|
||||||
|
|
||||||
def set_values(self, kpi, period_key, vals):
|
def set_values(self, kpi, period_key, vals,
|
||||||
|
drilldown_args):
|
||||||
""" Set values for a kpi and a period.
|
""" Set values for a kpi and a period.
|
||||||
|
|
||||||
Invoke this after declaring the kpi and the period.
|
Invoke this after declaring the kpi and the period.
|
||||||
"""
|
"""
|
||||||
self.set_values_detail_account(kpi, period_key, None, vals)
|
self.set_values_detail_account(kpi, period_key, None, vals,
|
||||||
|
drilldown_args)
|
||||||
|
|
||||||
def set_values_detail_account(self, kpi, period_key, account_id, vals):
|
def set_values_detail_account(self, kpi, period_key, account_id, vals,
|
||||||
|
drilldown_args):
|
||||||
""" Set values for a kpi and a period and a detail account.
|
""" Set values for a kpi and a period and a detail account.
|
||||||
|
|
||||||
Invoke this after declaring the kpi and the period.
|
Invoke this after declaring the kpi and the period.
|
||||||
|
@ -215,7 +218,8 @@ class KpiMatrix(object):
|
||||||
col = self._cols[period_key]
|
col = self._cols[period_key]
|
||||||
cell_tuple = []
|
cell_tuple = []
|
||||||
assert len(vals) == col.colspan
|
assert len(vals) == col.colspan
|
||||||
for val, subcol in izip(vals, col.iter_subcols()):
|
for val, drilldown_arg, subcol in \
|
||||||
|
izip(vals, drilldown_args, col.iter_subcols()):
|
||||||
if isinstance(val, DataError):
|
if isinstance(val, DataError):
|
||||||
val_rendered = val.name
|
val_rendered = val.name
|
||||||
val_comment = val.msg
|
val_comment = val.msg
|
||||||
|
@ -231,8 +235,8 @@ class KpiMatrix(object):
|
||||||
row.kpi.name,
|
row.kpi.name,
|
||||||
row.kpi.expression)
|
row.kpi.expression)
|
||||||
# TODO style
|
# TODO style
|
||||||
# TODO drilldown_key
|
cell = KpiMatrixCell(row, subcol, val, val_rendered, val_comment,
|
||||||
cell = KpiMatrixCell(row, subcol, val, val_rendered, val_comment)
|
None, drilldown_arg)
|
||||||
cell_tuple.append(cell)
|
cell_tuple.append(cell)
|
||||||
col._set_cell_tuple(row, cell_tuple)
|
col._set_cell_tuple(row, cell_tuple)
|
||||||
|
|
||||||
|
@ -358,14 +362,16 @@ class KpiMatrix(object):
|
||||||
if cell is None:
|
if cell is None:
|
||||||
row_data['cols'].append({})
|
row_data['cols'].append({})
|
||||||
else:
|
else:
|
||||||
row_data['cols'].append({
|
col_data = {
|
||||||
'val': (cell.val
|
'val': (cell.val
|
||||||
if cell.val is not AccountingNone else None),
|
if cell.val is not AccountingNone else None),
|
||||||
'val_r': cell.val_rendered,
|
'val_r': cell.val_rendered,
|
||||||
'val_c': cell.val_comment,
|
'val_c': cell.val_comment,
|
||||||
# TODO FIXME style
|
# TODO FIXME style
|
||||||
# TODO FIXME drilldown
|
}
|
||||||
})
|
if cell.drilldown_arg:
|
||||||
|
col_data['drilldown_arg'] = cell.drilldown_arg
|
||||||
|
row_data['cols'].append(col_data)
|
||||||
content.append(row_data)
|
content.append(row_data)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -975,11 +981,19 @@ class MisReport(models.Model):
|
||||||
expressions.append(expression.name)
|
expressions.append(expression.name)
|
||||||
|
|
||||||
vals = []
|
vals = []
|
||||||
|
drilldown_args = []
|
||||||
try:
|
try:
|
||||||
for expression in expressions:
|
for expression in expressions:
|
||||||
replaced_expr = aep.replace_expr(expression)
|
replaced_expr = aep.replace_expr(expression)
|
||||||
vals.append(
|
vals.append(
|
||||||
mis_safe_eval(replaced_expr, locals_dict))
|
mis_safe_eval(replaced_expr, locals_dict))
|
||||||
|
if replaced_expr != expression:
|
||||||
|
drilldown_args.append({
|
||||||
|
'period_id': period_key,
|
||||||
|
'expr': expression,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
drilldown_args.append(None)
|
||||||
except NameError:
|
except NameError:
|
||||||
recompute_queue.append(kpi)
|
recompute_queue.append(kpi)
|
||||||
break
|
break
|
||||||
|
@ -991,19 +1005,29 @@ class MisReport(models.Model):
|
||||||
else:
|
else:
|
||||||
locals_dict[kpi.name] = SimpleArray(vals)
|
locals_dict[kpi.name] = SimpleArray(vals)
|
||||||
|
|
||||||
kpi_matrix.set_values(kpi, period_key, vals)
|
kpi_matrix.set_values(
|
||||||
|
kpi, period_key, vals, drilldown_args)
|
||||||
|
|
||||||
if not kpi.auto_expand_accounts:
|
if not kpi.auto_expand_accounts:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for account_id, replaced_exprs in \
|
for account_id, replaced_exprs in \
|
||||||
aep.replace_exprs_by_account_id(expressions):
|
aep.replace_exprs_by_account_id(expressions):
|
||||||
account_id_vals = []
|
vals = []
|
||||||
for replaced_expr in replaced_exprs:
|
drilldown_args = []
|
||||||
account_id_vals.append(
|
for expression, replaced_expr in \
|
||||||
mis_safe_eval(replaced_expr, locals_dict))
|
izip(expressions, replaced_exprs):
|
||||||
|
vals.append(mis_safe_eval(replaced_expr, locals_dict))
|
||||||
|
if replaced_expr != expression:
|
||||||
|
drilldown_args.append({
|
||||||
|
'period_id': period_key,
|
||||||
|
'expr': expression,
|
||||||
|
'account_id': account_id
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
drilldown_args.append(None)
|
||||||
kpi_matrix.set_values_detail_account(
|
kpi_matrix.set_values_detail_account(
|
||||||
kpi, period_key, account_id, account_id_vals)
|
kpi, period_key, account_id, vals, drilldown_args)
|
||||||
|
|
||||||
if len(recompute_queue) == 0:
|
if len(recompute_queue) == 0:
|
||||||
# nothing to recompute, we are done
|
# nothing to recompute, we are done
|
||||||
|
|
|
@ -169,33 +169,6 @@ class MisReportInstancePeriod(models.Model):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def drilldown(self, expr):
|
|
||||||
self.ensure_one()
|
|
||||||
# TODO FIXME: drilldown by account
|
|
||||||
if AEP.has_account_var(expr):
|
|
||||||
aep = AEP(self.env)
|
|
||||||
aep.parse_expr(expr)
|
|
||||||
aep.done_parsing(self.report_instance_id.company_id)
|
|
||||||
domain = aep.get_aml_domain_for_expr(
|
|
||||||
expr,
|
|
||||||
self.date_from, self.date_to,
|
|
||||||
self.report_instance_id.target_move,
|
|
||||||
self.report_instance_id.company_id)
|
|
||||||
domain.extend(self._get_additional_move_line_filter())
|
|
||||||
return {
|
|
||||||
'name': expr + ' - ' + self.name,
|
|
||||||
'domain': domain,
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'res_model': 'account.move.line',
|
|
||||||
'views': [[False, 'list'], [False, 'form']],
|
|
||||||
'view_type': 'list',
|
|
||||||
'view_mode': 'list',
|
|
||||||
'target': 'current',
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class MisReportInstance(models.Model):
|
class MisReportInstance(models.Model):
|
||||||
"""The MIS report instance combines everything to compute
|
"""The MIS report instance combines everything to compute
|
||||||
|
@ -383,11 +356,9 @@ class MisReportInstance(models.Model):
|
||||||
aep = self.report_id._prepare_aep(self.company_id)
|
aep = self.report_id._prepare_aep(self.company_id)
|
||||||
kpi_matrix = self.report_id._prepare_kpi_matrix()
|
kpi_matrix = self.report_id._prepare_kpi_matrix()
|
||||||
for period in self.period_ids:
|
for period in self.period_ids:
|
||||||
# add the column header
|
|
||||||
if period.date_from == period.date_to:
|
if period.date_from == period.date_to:
|
||||||
comment = self._format_date(period.date_from)
|
comment = self._format_date(period.date_from)
|
||||||
else:
|
else:
|
||||||
# from, to
|
|
||||||
date_from = self._format_date(period.date_from)
|
date_from = self._format_date(period.date_from)
|
||||||
date_to = self._format_date(period.date_to)
|
date_to = self._format_date(period.date_to)
|
||||||
comment = _('from %s to %s') % (date_from, date_to)
|
comment = _('from %s to %s') % (date_from, date_to)
|
||||||
|
@ -414,3 +385,34 @@ class MisReportInstance(models.Model):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
kpi_matrix = self._compute_matrix()
|
kpi_matrix = self._compute_matrix()
|
||||||
return kpi_matrix.as_dict()
|
return kpi_matrix.as_dict()
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def drilldown(self, arg):
|
||||||
|
self.ensure_one()
|
||||||
|
period_id = arg.get('period_id')
|
||||||
|
expr = arg.get('expr')
|
||||||
|
account_id = arg.get('account_id')
|
||||||
|
if period_id and expr and AEP.has_account_var(expr):
|
||||||
|
period = self.env['mis.report.instance.period'].browse(period_id)
|
||||||
|
aep = AEP(self.env)
|
||||||
|
aep.parse_expr(expr)
|
||||||
|
aep.done_parsing(self.company_id)
|
||||||
|
domain = aep.get_aml_domain_for_expr(
|
||||||
|
expr,
|
||||||
|
period.date_from, period.date_to,
|
||||||
|
self.target_move,
|
||||||
|
self.company_id,
|
||||||
|
account_id)
|
||||||
|
domain.extend(period._get_additional_move_line_filter())
|
||||||
|
return {
|
||||||
|
'name': u'{} - {}'.format(expr, period.name),
|
||||||
|
'domain': domain,
|
||||||
|
'type': 'ir.actions.act_window',
|
||||||
|
'res_model': 'account.move.line',
|
||||||
|
'views': [[False, 'list'], [False, 'form']],
|
||||||
|
'view_type': 'list',
|
||||||
|
'view_mode': 'list',
|
||||||
|
'target': 'current',
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
|
@ -116,15 +116,11 @@ var MisReport = form_common.FormWidget.extend({
|
||||||
|
|
||||||
drilldown: function(event) {
|
drilldown: function(event) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var drilldown = JSON.parse($(event.target).data("drilldown"));
|
var drilldown = $(event.target).data("drilldown");
|
||||||
if (drilldown) {
|
if (drilldown) {
|
||||||
var period_id = JSON.parse($(event.target).data("period-id"));
|
new Model("mis.report.instance").call(
|
||||||
var val_c = JSON.parse($(event.target).data("expr"));
|
|
||||||
var context = new data.CompoundContext(self.build_context(), self.get_context()|| {})
|
|
||||||
new Model("mis.report.instance.period").call(
|
|
||||||
"drilldown",
|
"drilldown",
|
||||||
[period_id, val_c],
|
[self.mis_report_instance_id, drilldown]
|
||||||
{'context': context}
|
|
||||||
).then(function(result) {
|
).then(function(result) {
|
||||||
if (result) {
|
if (result) {
|
||||||
self.do_action(result);
|
self.do_action(result);
|
||||||
|
|
|
@ -32,17 +32,15 @@
|
||||||
<t t-foreach="c_value.cols" t-as="value">
|
<t t-foreach="c_value.cols" t-as="value">
|
||||||
<td t-att="{'style': c_value.style}" class="mis_builder_amount">
|
<td t-att="{'style': c_value.style}" class="mis_builder_amount">
|
||||||
<div t-att="{'style': value_value.style, 'title': value_value.val_c}">
|
<div t-att="{'style': value_value.style, 'title': value_value.val_c}">
|
||||||
<t t-if="value_value.drilldown">
|
<t t-if="value_value.drilldown_arg">
|
||||||
<a href="javascript:void(0)"
|
<a href="javascript:void(0)"
|
||||||
class="mis_builder_drilldown"
|
class="mis_builder_drilldown"
|
||||||
t-att-data-drilldown="JSON.stringify(value_value.drilldown)"
|
t-att-data-drilldown="JSON.stringify(value_value.drilldown_arg)"
|
||||||
t-att-data-period-id="JSON.stringify(value_value.period_id)"
|
|
||||||
t-att-data-expr="JSON.stringify(value_value.expr)"
|
|
||||||
>
|
>
|
||||||
<t t-esc="value_value.val_r"/>
|
<t t-esc="value_value.val_r"/>
|
||||||
</a>
|
</a>
|
||||||
</t>
|
</t>
|
||||||
<t t-if="!value_value.drilldown">
|
<t t-if="!value_value.drilldown_arg">
|
||||||
<t t-esc="value_value.val_r"/>
|
<t t-esc="value_value.val_r"/>
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,6 +12,7 @@ class TestFetchQuery(common.TransactionCase):
|
||||||
data = self.registry('mis.report.instance').compute(
|
data = self.registry('mis.report.instance').compute(
|
||||||
self.cr, self.uid,
|
self.cr, self.uid,
|
||||||
self.ref('mis_builder.mis_report_instance_test'))
|
self.ref('mis_builder.mis_report_instance_test'))
|
||||||
|
self.maxDiff = None
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
{'content':
|
{'content':
|
||||||
[{'description': u'total test',
|
[{'description': u'total test',
|
||||||
|
|
Loading…
Reference in New Issue