diff --git a/mis_builder/__openerp__.py b/mis_builder/__openerp__.py index 47047cd2..95e8dbda 100644 --- a/mis_builder/__openerp__.py +++ b/mis_builder/__openerp__.py @@ -30,6 +30,9 @@ Build 'Management Information System' Reports and Dashboards """, 'description': """ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 =========== MIS Builder =========== @@ -60,13 +63,34 @@ To configure this module, you need to: * From the MIS Report view, you can preview the report, add it to and Odoo dashboard, and export it to Excel. +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/91/7.0 + For further information, please visit: * https://www.odoo.com/forum/help-1 +Developer notes +=============== + +A typical extension is to provide a mechanism to filter reports on analytic dimensions +or operational units. To implement this, you can override _get_additional_move_line_filter +and _get_additional_filter to further filter move lines or queries based on a user +selection. A typical use case could be to add an analytic account field on mis.report.instance, +or even on mis.report.instance.period if you want different columns to show different +analytic accounts. + Known issues / Roadmap ====================== +* Add 'Fiscal Year' period type. + +* Allow selecting accounts by type. This is currently possible by expressing + a query such as balp[][('account_id.user_type.code', '=', ...)]. This will work + but would be more efficient if one could write balp[user_type=...], as it would + involve much less queries to the database. + * More tests should be added. The first part is creating test data, then it will be easier. At the minimum, We need the following test data: diff --git a/mis_builder/models/aep.py b/mis_builder/models/aep.py index f749a31c..e7b76a48 100644 --- a/mis_builder/models/aep.py +++ b/mis_builder/models/aep.py @@ -373,7 +373,8 @@ class AccountingExpressionProcessor(object): return expression.normalize_domain(domain) def do_queries(self, cr, uid, date_from, date_to, period_from, period_to, - target_move, context=None): + target_move, additional_move_line_filter=None, + context=None): """Query sums of debit and credit for all accounts and domains used in expressions. @@ -394,6 +395,8 @@ class AccountingExpressionProcessor(object): context=context) domain = list(domain) + domain_by_mode[mode] domain.append(('account_id', 'in', self._map_account_ids[key])) + if additional_move_line_filter: + domain.extend(additional_move_line_filter) # fetch sum of debit/credit, grouped by account_id accs = aml_model.read_group(cr, uid, domain, ['debit', 'credit', 'account_id'], diff --git a/mis_builder/models/mis_builder.py b/mis_builder/models/mis_builder.py index 79c5d0f0..38f6dcca 100644 --- a/mis_builder/models/mis_builder.py +++ b/mis_builder/models/mis_builder.py @@ -64,7 +64,8 @@ def _utc_midnight(d, tz_name, add_day=0): d = d + datetime.timedelta(days=add_day) context_tz = pytz.timezone(tz_name) local_timestamp = context_tz.localize(d, is_dst=False) - return datetime.datetime.strftime(local_timestamp.astimezone(utc_tz)) + return local_timestamp.astimezone(utc_tz).strftime( + tools.DEFAULT_SERVER_DATE_FORMAT) def _python_var(var_str): @@ -75,30 +76,6 @@ def _is_valid_python_var(name): return re.match("[_A-Za-z][_a-zA-Z0-9]*$", name) -def _sum(l): - if not l: - return None - return sum(l) - - -def _avg(l): - if not l: - return None - return sum(l) / float(len(l)) - - -def _min(*l): - if not l: - return None - return min(*l) - - -def _max(*l): - if not l: - return None - return max(*l) - - class MisReportKpi(orm.Model): """ A KPI is an element (ie a line) of a MIS report. @@ -516,6 +493,28 @@ class MisReportInstancePeriod(orm.Model): 'Period name should be unique by report'), ] + def _get_additional_move_line_filter(self, cr, uid, _id, context=None): + """ Prepare a filter to apply on all move lines + This filter is applied with a AND operator on all + accounting expression domains. This hook is intended + to be inherited, and is useful to implement filtering + on analytic dimensions or operational units. + Returns an Odoo domain expression (a python list) + compatible with account.move.line.""" + return [] + + def _get_additional_query_filter(self, cr, uid, _id, query, context=None): + """ Prepare an additional filter to apply on the query + + This filter is combined to the query domain with a AND + operator. This hook is intended + to be inherited, and is useful to implement filtering + on analytic dimensions or operational units. + + Returns an Odoo domain expression (a python list) + compatible with the model of the query.""" + return [] + def drilldown(self, cr, uid, _id, expr, context=None): this = self.browse(cr, uid, _id, context=context) if AEP.has_account_var(expr): @@ -529,6 +528,8 @@ class MisReportInstancePeriod(orm.Model): this.period_from, this.period_to, this.report_instance_id.target_move, context=context) + domain.extend(self._get_additional_move_line_filter( + cr, uid, _id, context=context)) return { 'name': expr + ' - ' + this.name, 'domain': domain, @@ -545,7 +546,6 @@ class MisReportInstancePeriod(orm.Model): def _fetch_queries(self, cr, uid, c, context): res = {} report = c.report_instance_id.report_id - query_obj = self.pool['mis.report.query'] for query in report.query_ids: obj = self.pool[query.model_id.model] eval_context = { @@ -563,9 +563,8 @@ class MisReportInstancePeriod(orm.Model): 'period %s.') % c.name) domain = query.domain and \ safe_eval(query.domain, eval_context) or [] - domain.extend(query_obj._get_additional_filter(cr, uid, - query.id, - context=context)) + domain.extend(self._get_additional_query_filter( + cr, uid, c.id, query, context=context)) if query.date_field.ttype == 'date': domain.extend([(query.date_field.name, '>=', c.date_from), (query.date_field.name, '<=', c.date_to)]) @@ -633,6 +632,8 @@ class MisReportInstancePeriod(orm.Model): aep.do_queries(cr, uid, c.date_from, c.date_to, c.period_from, c.period_to, c.report_instance_id.target_move, + self._get_additional_move_line_filter(cr, uid, c.id, + context=context), context=context) compute_queue = c.report_instance_id.report_id.kpi_ids