diff --git a/product_contract/models/sale_order_line.py b/product_contract/models/sale_order_line.py index 8386477a..3b1cafd9 100644 --- a/product_contract/models/sale_order_line.py +++ b/product_contract/models/sale_order_line.py @@ -98,8 +98,13 @@ class SaleOrderLine(models.Model): @api.multi def _prepare_contract_line_values( - self, contract, predecessor_contract_line + self, contract, predecessor_contract_line_id=False ): + """ + :param contract: related contract + :param predecessor_contract_line_id: contract line to replace id + :return: new contract line dict + """ self.ensure_one() recurring_next_date = self.env[ 'account.analytic.invoice.line' @@ -148,27 +153,43 @@ class SaleOrderLine(models.Model): 'termination_notice_rule_type': termination_notice_rule_type, 'contract_id': contract.id, 'sale_order_line_id': self.id, - 'predecessor_contract_line_id': predecessor_contract_line.id, + 'predecessor_contract_line_id': predecessor_contract_line_id, } @api.multi def create_contract_line(self, contract): contract_line_env = self.env['account.analytic.invoice.line'] contract_line = self.env['account.analytic.invoice.line'] + predecessor_contract_line = False for rec in self: if rec.contract_line_id: - rec.contract_line_id.stop( - rec.date_start - relativedelta(days=1) - ) - new_contract_line = contract_line_env.create( - rec._prepare_contract_line_values( - contract, rec.contract_line_id + # If the upsell/downsell line start at the same date or before + # the contract line to replace supposed to start, we cancel + # the one to be replaced. Otherwise we stop it. + if rec.date_start <= rec.contract_line_id.date_start: + # The contract will handel the contract line integrity + # An exception will be raised if we try to cancel an + # invoiced contract line + rec.contract_line_id.cancel() + elif ( + not rec.contract_line_id.date_end + or rec.date_start <= rec.contract_line_id.date_end + ): + rec.contract_line_id.stop( + rec.date_start - relativedelta(days=1) + ) + predecessor_contract_line = rec.contract_line_id + if predecessor_contract_line: + new_contract_line = contract_line_env.create( + rec._prepare_contract_line_values(contract, predecessor_contract_line.id) ) - ) - if rec.contract_line_id: - rec.contract_line_id.successor_contract_line_id = ( + predecessor_contract_line.successor_contract_line_id = ( new_contract_line ) + else: + new_contract_line = contract_line_env.create( + rec._prepare_contract_line_values(contract) + ) contract_line |= new_contract_line return contract_line diff --git a/product_contract/tests/test_sale_order.py b/product_contract/tests/test_sale_order.py index 2cbd86b9..054a362e 100644 --- a/product_contract/tests/test_sale_order.py +++ b/product_contract/tests/test_sale_order.py @@ -107,7 +107,9 @@ class TestSaleOrder(TransactionCase): contract_line = self.order_line1.contract_id.recurring_invoice_line_ids self.assertEqual(contract_line.date_start, Date.to_date('2018-01-01')) self.assertEqual(contract_line.date_end, Date.to_date('2018-12-31')) - self.assertEqual(contract_line.recurring_next_date, Date.to_date('2018-01-31')) + self.assertEqual( + contract_line.recurring_next_date, Date.to_date('2018-01-31') + ) def test_sale_contract_count(self): """It should count contracts as many different contract template used @@ -221,6 +223,23 @@ class TestSaleOrder(TransactionCase): new_contract_line.predecessor_contract_line_id, self.contract_line ) + def test_contract_upsell_2(self): + """Should stop contract line at sale order line start date""" + self.order_line1.contract_id = self.contract + self.order_line1.contract_line_id = self.contract_line + self.contract_line.write( + { + 'date_start': "2018-06-01", + 'recurring_next_date': "2018-06-01", + 'date_end': False, + } + ) + self.order_line1.date_start = "2018-06-01" + self.order_line1.onchange_product() + self.sale.action_confirm() + self.assertFalse(self.contract_line.date_end) + self.assertTrue(self.contract_line.is_canceled) + def test_onchange_product_id_recurring_info(self): self.product2.write( {