diff --git a/mis_builder/models/mis_report_instance.py b/mis_builder/models/mis_report_instance.py index f7d50faba..122362b11 100644 --- a/mis_builder/models/mis_report_instance.py +++ b/mis_builder/models/mis_report_instance.py @@ -284,6 +284,17 @@ def _compute_dates(self): help="A domain to additionally filter move lines considered in this column.", ) + hide_period_based_on_instance_date = fields.Boolean( + string="Dynamically Hide Column", + help="""Hide this column if the pivot date is before the end date. + In the case of a column computed from other columns (e.g. compare column), + the column is displayed if all subcolumns should be displayed. + """, + compute="_compute_hide_period_base_on_instance_date", + store=True, + readonly=False, + ) + _order = "sequence, id" _sql_constraints = [ @@ -300,6 +311,14 @@ def _compute_dates(self): ), ] + @api.depends("source") + def _compute_hide_period_base_on_instance_date(self): + for rec in self: + # Coluwns with source 'Actuals' or 'Actuals (alternative)' + # will be displayed depending on their subcolumns + if rec.source in (SRC_CMPCOL, SRC_SUMCOL): + rec.hide_period_based_on_instance_date = True + @api.depends("source", "report_instance_id.report_id.move_lines_source") def _compute_source_aml_model_id(self): for record in self: @@ -458,6 +477,45 @@ def copy_data(self, default=None): ] return super().copy_data(default=default) + def _period_should_be_displayed(self, pivot_date): + """ + Returns true if period should be displayed + + - If the field to dynamically hide period is not set to true, + the col is always displayed + - If the mode is fix, the period is displayed if the pivot date + is before the end + - A period with a source 'Acutals' or 'Actuals (alternative)' + will always be displayed if the mode is not 'fix' + - A period that sums columnns will be displayed if its 'source + columns' should be displayed + - A period that compares columns will be displayed if its + 'source columns' should be displayed + """ + self.ensure_one() + if not self.hide_period_based_on_instance_date: + return True + + if self.mode == MODE_FIX: + return not (self.date_to and pivot_date < self.date_to) + + if self.source == SRC_ACTUALS or self.source == SRC_ACTUALS_ALT: + return True + elif self.source == SRC_SUMCOL: + return all( + sumcol.period_to_sum_id._period_should_be_displayed(pivot_date) + for sumcol in self.source_sumcol_ids + ) + elif self.source == SRC_CMPCOL: + return ( + bool(self.source_cmpcol_from_id) + and bool(self.source_cmpcol_to_id) + and self.source_cmpcol_from_id._period_should_be_displayed(pivot_date) + and self.source_cmpcol_to_id._period_should_be_displayed(pivot_date) + ) + else: + return False + class MisReportInstance(models.Model): """The MIS report instance combines everything to compute @@ -844,6 +902,11 @@ def _add_column(self, aep, kpi_matrix, period, label, description): elif period.source == SRC_CMPCOL: return self._add_column_cmpcol(aep, kpi_matrix, period, label, description) + def _get_periods(self): + return self.period_ids.filtered( + lambda rec: rec._period_should_be_displayed(self.pivot_date) + ) + def _compute_matrix(self): """Compute a report and return a KpiMatrix. @@ -853,7 +916,8 @@ def _compute_matrix(self): self.ensure_one() aep = self.report_id._prepare_aep(self.query_company_ids, self.currency_id) kpi_matrix = self.report_id.prepare_kpi_matrix(self.multi_company) - for period in self.period_ids: + + for period in self._get_periods(): description = None if period.mode == MODE_NONE: pass diff --git a/mis_builder/tests/test_mis_report_instance.py b/mis_builder/tests/test_mis_report_instance.py index 42937d38d..d477fbebe 100644 --- a/mis_builder/tests/test_mis_report_instance.py +++ b/mis_builder/tests/test_mis_report_instance.py @@ -620,6 +620,48 @@ def test_mis_report_analytic_filters(self): elif row.kpi.name == "k4": self.assertEqual(vals, [AccountingNone, AccountingNone, 1.0]) + def test_hide_period(self): + instance = self.report_instance + _, p2 = instance.period_ids + p2.hide_period_based_on_instance_date = True + + self.assertTrue(p2.date_to <= instance.pivot_date) + + matrix = instance.compute() + periods_header = matrix["header"][0]["cols"] + self.assertEqual(len(periods_header), 2) + + # set date to exactly the end of period should keep period + instance.write({"date": "2014-12-31"}) + + self.assertTrue(p2.date_to <= instance.pivot_date) + + matrix = instance.compute() + periods_header = matrix["header"][0]["cols"] + self.assertEqual(len(periods_header), 2) + + # set date to a date in period should remove the period + + instance.write({"date": "2014-12-30"}) + + self.assertFalse(p2.date_to <= instance.pivot_date) + + matrix = instance.compute() + periods_header = matrix["header"][0]["cols"] + self.assertEqual(len(periods_header), 1) + self.assertEqual(periods_header[0]["label"], "p1") + + # set date before period should also remove the period + + instance.write({"date": "2013-12-30"}) + + self.assertFalse(p2.date_to <= instance.pivot_date) + + matrix = instance.compute() + periods_header = matrix["header"][0]["cols"] + self.assertEqual(len(periods_header), 1) + self.assertEqual(periods_header[0]["label"], "p1") + def test_raise_when_unknown_kpi_value_type(self): with self.assertRaises(SubKPIUnknownTypeError): self.report_instance_2.compute() diff --git a/mis_builder/views/mis_report_instance.xml b/mis_builder/views/mis_report_instance.xml index f13fce50e..bf1b54429 100644 --- a/mis_builder/views/mis_report_instance.xml +++ b/mis_builder/views/mis_report_instance.xml @@ -414,6 +414,11 @@ options="{'model': 'source_aml_model_name'}" attrs="{'invisible': [('source_aml_model_name', '=', False)]}" /> +