From d2bc009961499c10dd239fee2d83d533637459af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Fri, 13 May 2016 21:40:33 +0200 Subject: [PATCH] [WIP] mis_builder refactoring: restore drilldown with support for account details --- mis_builder/models/aep.py | 13 ++++- mis_builder/models/mis_report.py | 58 +++++++++++++++------- mis_builder/models/mis_report_instance.py | 60 ++++++++++++----------- mis_builder/static/src/js/mis_builder.js | 10 ++-- mis_builder/static/src/xml/mis_widget.xml | 8 ++- mis_builder/tests/test_fetch_query.py | 1 + 6 files changed, 90 insertions(+), 60 deletions(-) diff --git a/mis_builder/models/aep.py b/mis_builder/models/aep.py index 49f6b5cb..f3c3b005 100644 --- a/mis_builder/models/aep.py +++ b/mis_builder/models/aep.py @@ -165,7 +165,8 @@ class AccountingExpressionProcessor(object): def get_aml_domain_for_expr(self, expr, date_from, date_to, - target_move, company): + target_move, company, + account_id=None): """ Get a domain on account.move.line for an expression. Prerequisite: done_parsing() must have been invoked. @@ -180,7 +181,14 @@ class AccountingExpressionProcessor(object): account_ids = set() for account_code in account_codes: account_ids.update(self._account_ids_by_code[account_code]) - aml_domain.append(('account_id', 'in', tuple(account_ids))) + if not account_id: + 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': aml_domain.append(('credit', '>', 0)) elif field == 'deb': @@ -191,6 +199,7 @@ class AccountingExpressionProcessor(object): self.get_aml_domain_for_dates(date_from, date_to, mode, target_move, company) + assert aml_domains return expression.OR(aml_domains) + \ expression.OR(date_domain_by_mode.values()) diff --git a/mis_builder/models/mis_report.py b/mis_builder/models/mis_report.py index 53519650..136f5c67 100644 --- a/mis_builder/models/mis_report.py +++ b/mis_builder/models/mis_report.py @@ -134,14 +134,14 @@ class KpiMatrixCell(object): def __init__(self, row, subcol, val, val_rendered, val_comment, - style=None, drilldown_key=None): + style=None, drilldown_arg=None): self.row = row self.subcol = subcol self.val = val self.val_rendered = val_rendered self.val_comment = val_comment self.style = style - self.drilldown_key = None + self.drilldown_arg = drilldown_arg class KpiMatrix(object): @@ -191,14 +191,17 @@ class KpiMatrix(object): self._comparison_todo[last_period_key].append( (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. 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. Invoke this after declaring the kpi and the period. @@ -215,7 +218,8 @@ class KpiMatrix(object): col = self._cols[period_key] cell_tuple = [] 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): val_rendered = val.name val_comment = val.msg @@ -231,8 +235,8 @@ class KpiMatrix(object): row.kpi.name, row.kpi.expression) # 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) col._set_cell_tuple(row, cell_tuple) @@ -358,14 +362,16 @@ class KpiMatrix(object): if cell is None: row_data['cols'].append({}) else: - row_data['cols'].append({ + col_data = { 'val': (cell.val if cell.val is not AccountingNone else None), 'val_r': cell.val_rendered, 'val_c': cell.val_comment, # 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) return { @@ -975,11 +981,19 @@ class MisReport(models.Model): expressions.append(expression.name) vals = [] + drilldown_args = [] try: for expression in expressions: replaced_expr = aep.replace_expr(expression) vals.append( 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: recompute_queue.append(kpi) break @@ -991,19 +1005,29 @@ class MisReport(models.Model): else: 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: continue for account_id, replaced_exprs in \ aep.replace_exprs_by_account_id(expressions): - account_id_vals = [] - for replaced_expr in replaced_exprs: - account_id_vals.append( - mis_safe_eval(replaced_expr, locals_dict)) + vals = [] + drilldown_args = [] + for expression, replaced_expr in \ + 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, period_key, account_id, account_id_vals) + kpi, period_key, account_id, vals, drilldown_args) if len(recompute_queue) == 0: # nothing to recompute, we are done diff --git a/mis_builder/models/mis_report_instance.py b/mis_builder/models/mis_report_instance.py index eecfcf7a..2e65934c 100644 --- a/mis_builder/models/mis_report_instance.py +++ b/mis_builder/models/mis_report_instance.py @@ -169,33 +169,6 @@ class MisReportInstancePeriod(models.Model): self.ensure_one() 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): """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) kpi_matrix = self.report_id._prepare_kpi_matrix() for period in self.period_ids: - # add the column header if period.date_from == period.date_to: comment = self._format_date(period.date_from) else: - # from, to date_from = self._format_date(period.date_from) date_to = self._format_date(period.date_to) comment = _('from %s to %s') % (date_from, date_to) @@ -414,3 +385,34 @@ class MisReportInstance(models.Model): self.ensure_one() kpi_matrix = self._compute_matrix() 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 diff --git a/mis_builder/static/src/js/mis_builder.js b/mis_builder/static/src/js/mis_builder.js index cbd54f42..60dda3e9 100644 --- a/mis_builder/static/src/js/mis_builder.js +++ b/mis_builder/static/src/js/mis_builder.js @@ -116,15 +116,11 @@ var MisReport = form_common.FormWidget.extend({ drilldown: function(event) { var self = this; - var drilldown = JSON.parse($(event.target).data("drilldown")); + var drilldown = $(event.target).data("drilldown"); if (drilldown) { - var period_id = JSON.parse($(event.target).data("period-id")); - 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( + new Model("mis.report.instance").call( "drilldown", - [period_id, val_c], - {'context': context} + [self.mis_report_instance_id, drilldown] ).then(function(result) { if (result) { self.do_action(result); diff --git a/mis_builder/static/src/xml/mis_widget.xml b/mis_builder/static/src/xml/mis_widget.xml index baef3e27..bc5178a9 100644 --- a/mis_builder/static/src/xml/mis_widget.xml +++ b/mis_builder/static/src/xml/mis_widget.xml @@ -32,17 +32,15 @@
- + - +
diff --git a/mis_builder/tests/test_fetch_query.py b/mis_builder/tests/test_fetch_query.py index 980868f7..5b802b1c 100644 --- a/mis_builder/tests/test_fetch_query.py +++ b/mis_builder/tests/test_fetch_query.py @@ -12,6 +12,7 @@ class TestFetchQuery(common.TransactionCase): data = self.registry('mis.report.instance').compute( self.cr, self.uid, self.ref('mis_builder.mis_report_instance_test')) + self.maxDiff = None self.assertEquals( {'content': [{'description': u'total test',