diff --git a/contract/models/abstract_contract_line.py b/contract/models/abstract_contract_line.py index c2daeb45b..94f81342b 100644 --- a/contract/models/abstract_contract_line.py +++ b/contract/models/abstract_contract_line.py @@ -164,11 +164,6 @@ class ContractAbstractContractLine(models.AbstractModel): def _compute_date_start(self): self._set_recurrence_field("date_start") - @api.depends("contract_id.recurring_next_date", "contract_id.line_recurrence") - def _compute_recurring_next_date(self): - super()._compute_recurring_next_date() - self._set_recurrence_field("recurring_next_date") - @api.depends("display_type", "note_invoicing_mode") def _compute_is_recurring_note(self): for record in self: diff --git a/contract/models/contract.py b/contract/models/contract.py index de67a3ce9..d29eb896c 100644 --- a/contract/models/contract.py +++ b/contract/models/contract.py @@ -314,6 +314,8 @@ class ContractContract(models.Model): "contract_line_ids.is_canceled", ) def _compute_recurring_next_date(self): + # Compute the recurring_next_date on the contract based on the one + # defined on line level. for contract in self: recurring_next_date = contract.contract_line_ids.filtered( lambda l: ( @@ -322,15 +324,11 @@ class ContractContract(models.Model): and (not l.display_type or l.is_recurring_note) ) ).mapped("recurring_next_date") - # we give priority to computation from date_start if modified - if ( - contract._origin - and contract._origin.date_start != contract.date_start - or not recurring_next_date - ): - super(ContractContract, contract)._compute_recurring_next_date() - else: - contract.recurring_next_date = min(recurring_next_date) + # Take the earliest or set it as False if contract is stopped + # (no recurring_next_date). + contract.recurring_next_date = ( + min(recurring_next_date) if recurring_next_date else False + ) @api.depends("contract_line_ids.create_invoice_visibility") def _compute_create_invoice_visibility(self): diff --git a/contract/models/contract_line.py b/contract/models/contract_line.py index b438e0677..80a3592ad 100644 --- a/contract/models/contract_line.py +++ b/contract/models/contract_line.py @@ -671,16 +671,12 @@ class ContractLine(models.Model): "date_end": date_end, "is_auto_renew": False, "manual_renew_needed": manual_renew_needed, - "recurring_next_date": self.get_next_invoice_date( - self.next_period_date_start, - self.recurring_invoicing_type, - self.recurring_invoicing_offset, - self.recurring_rule_type, - self.recurring_interval, - max_date_end=date_end, - ), } + def _prepare_value_for_contract_stop(self, date_end): + self.ensure_one() + return {"date_end": date_end} + def stop(self, date_end, manual_renew_needed=False, post_message=True): """ Put date_end on contract line @@ -699,6 +695,15 @@ class ContractLine(models.Model): rec.write( rec._prepare_value_for_stop(date_end, manual_renew_needed) ) + if not rec.contract_id.line_recurrence: + # FIXME: This should not happen. As recurring_next_date + # is computed on contract from lines ones, the only + # write({"date_end"}) on lines should be sufficent + # The set_recurrence_field() on date_end should be + # suppressed. + rec.contract_id.write( + rec._prepare_value_for_contract_stop(date_end) + ) if post_message: msg = _( """Contract line for {product} diff --git a/contract/tests/test_contract.py b/contract/tests/test_contract.py index 2410a248e..e4ced1f34 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -2324,6 +2324,40 @@ class TestContract(TestContractBase): self.assertFalse(self.contract.terminate_reason_id) self.assertFalse(self.contract.terminate_comment) + def test_action_terminate_contract_check_recurring_dates(self): + """ + The use case here is to use a contract with recurrence on its level. + + Create a first invoice + Then, terminate it => Lines should have a end_date + Then, create a new invoice (the last one). + The recurring next date should be False. + """ + group_can_terminate_contract = self.env.ref("contract.can_terminate_contract") + group_can_terminate_contract.users |= self.env.user + self.contract3.contract_line_ids.write({"date_start": "2018-03-01"}) + self.contract3.recurring_create_invoice() + self.assertEqual(to_date("2018-04-01"), self.contract3.recurring_next_date) + + action = self.contract3.action_terminate_contract() + wizard = ( + self.env[action["res_model"]] + .with_context(action["context"]) + .create( + { + "terminate_date": "2018-04-02", + "terminate_reason_id": self.terminate_reason.id, + "terminate_comment": "terminate_comment", + } + ) + ) + wizard.terminate_contract() + # This is the last invoice + self.contract3.recurring_create_invoice() + + # Recurring next date should be False + self.assertFalse(self.contract3.recurring_next_date) + def test_terminate_date_before_last_date_invoiced(self): self.contract.recurring_create_invoice() self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-02-14")) diff --git a/contract_sale_generation/tests/common.py b/contract_sale_generation/tests/common.py index cea97f152..dad87c2d9 100644 --- a/contract_sale_generation/tests/common.py +++ b/contract_sale_generation/tests/common.py @@ -100,7 +100,10 @@ class ContractSaleCommon: line_form.recurring_rule_type = "monthly" line_form.recurring_interval = 1 line_form.date_start = "2020-01-15" - line_form.recurring_next_date = "2020-01-15" + # TODO: Check why this is needed after Form use + # At _exit_, during the recurring_next_date compute on contract, + # contract_line_ids is void... + cls.contract._compute_recurring_next_date() cls.contract_line = cls.contract.contract_line_ids[1] cls.contract2 = cls.env["contract.contract"].create(