From 4101adb12506cb5d9feec28c70b3c9c27b1d32ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Tue, 28 Apr 2015 00:09:28 +0200 Subject: [PATCH] [IMP] mis_builder: rework periods computation * readability of algorithm * attempt to be correct in presence of multiple companies * attempt to be correct with initial balance computation * handle corner cases for initial balance --- mis_builder/models/aep.py | 135 +++++++++++++++++++++--------- mis_builder/models/mis_builder.py | 4 +- 2 files changed, 96 insertions(+), 43 deletions(-) diff --git a/mis_builder/models/aep.py b/mis_builder/models/aep.py index b09ab729..bc2f4021 100644 --- a/mis_builder/models/aep.py +++ b/mis_builder/models/aep.py @@ -178,48 +178,101 @@ class AccountingExpressionProcessor(object): raise RuntimeError("") # TODO return [('date', '>=', date_start), ('date', '<=', date_end)] - def get_aml_domain_for_periods(self, period_start, period_end, mode): - period_obj = self.env['account.period'] - move_obj = self.env['account.move'] - domain_list = [] - if mode == MODE_VARIATION: - compute_period_ids = period_obj.build_ctx_periods( - period_start.id, - period_end.id) - domain_list.extend([('period_id', 'in', compute_period_ids)]) - else: - period_to = period_end - if mode == MODE_INITIAL: - # Processing to get the first period which isn't special - # before end period - move = move_obj\ - .search([('period_id.special', '=', False), - ('period_id.date_start', '<', - period_to.date_start)], - order="period_id desc", limit=1) - if move.id: - computed_period_to = move.period_id - else: - computed_period_to = period_obj.search( - [('company_id', '=', period_start.company_id.id)], - order='date_start desc', limit=1) - # Change start period to search correctly period from - period_to = computed_period_to - move = move_obj.search( - [('period_id.special', '=', True), - ('period_id.date_start', '<=', - period_to.date_start)], - order="period_id desc", limit=1) - if move.id: - computed_period_from = move.period_id + def _period_has_moves(self, period): + move_model = self.env['account.move'] + return bool(move_model.search([('period_id', '=', period.id)], + limit=1)) + + def _get_previous_opening_period(self, period, company_id): + period_model = self.env['account.period'] + periods = period_model.search( + [('date_start', '<=', period.date_start), + ('special', '=', True), + ('company_id', '=', company_id)], + order="date_start desc", + limit=1) + return periods and periods[0] + + def _get_previous_normal_period(self, period, company_id): + period_model = self.env['account.period'] + periods = period_model.search( + [('date_start', '<', period.date_start), + ('special', '=', False), + ('company_id', '=', company_id)], + order="date_start desc", + limit=1) + return periods and periods[0] + + def _get_first_normal_period(self, company_id): + period_model = self.env['account.period'] + periods = period_model.search( + [('special', '=', False), + ('company_id', '=', company_id)], + order="date_start asc", + limit=1) + return periods and periods[0] + + def _get_period_ids_between(self, period_from, period_to, company_id): + period_model = self.env['account.period'] + periods = period_model.search( + [('date_start', '>=', period_from.date_start), + ('date_stop', '<=', period_to.date_stop), + ('special', '=', False), + ('company_id', '=', company_id)]) + period_ids = [p.id for p in periods] + if period_from.special: + period_ids.append(period_from.id) + return period_ids + + def _get_period_company_ids(self, period_from, period_to): + period_model = self.env['account.period'] + periods = period_model.search( + [('date_start', '>=', period_from.date_start), + ('date_stop', '<=', period_to.date_stop), + ('special', '=', False)]) + return set([p.company_id.id for p in periods]) + + def _get_period_ids_for_mode(self, period_from, period_to, mode): + assert not period_from.special + assert not period_to.special + assert period_from.company_id == period_to.company_id + assert period_from.date_start <= period_to.date_start + period_ids = [] + for company_id in self._get_period_company_ids(period_from, period_to): + if mode == MODE_VARIATION: + period_ids.extend(self._get_period_ids_between( + period_from, period_to, company_id)) else: - computed_period_from = period_obj.search( - [('company_id', '=', period_start.company_id.id)], - order='date_start', limit=1) - compute_period_ids = period_obj.build_ctx_periods( - computed_period_from.id, period_to.id) - domain_list.extend([('period_id', 'in', compute_period_ids)]) - return domain_list + if mode == MODE_INITIAL: + period_to = self._get_previous_normal_period( + period_from, company_id) + # look for opening period with moves + opening_period = self._get_previous_opening_period( + period_from, company_id) + if opening_period and \ + self._period_has_moves(opening_period[0]): + # found opening period with moves + if opening_period.date_start == period_from.date_start and \ + mode == MODE_INITIAL: + # if the opening period has the same start date as + # period_from, the we'll find the initial balance + # in the initial period and that's it + period_ids.append(opening_period[0].id) + continue + period_from = opening_period[0] + else: + # no opening period with moves, + # use very first normal period + period_from = self._get_first_normal_period(company_id) + if period_to: + period_ids.extend(self._get_period_ids_between( + period_from, period_to, company_id)) + return period_ids + + def get_aml_domain_for_periods(self, period_from, period_to, mode): + period_ids = self._get_period_ids_for_mode( + period_from, period_to, mode) + return [('period_id', 'in', period_ids)] def do_queries(self, period_domain, period_domain_i, period_domain_e): aml_model = self.env['account.move.line'] diff --git a/mis_builder/models/mis_builder.py b/mis_builder/models/mis_builder.py index 37586042..73932f15 100644 --- a/mis_builder/models/mis_builder.py +++ b/mis_builder/models/mis_builder.py @@ -412,8 +412,8 @@ class mis_report_instance_period(orm.Model): res[c.id] = { 'date_from': date_from, 'date_to': date_to, - 'period_from': period_ids and period_ids[0], - 'period_to': period_ids and period_ids[-1], + 'period_from': period_ids and period_ids[0] or False, + 'period_to': period_ids and period_ids[-1] or False, } return res