diff --git a/contract/migrations/12.0.5.0.0/pre-migration.py b/contract/migrations/12.0.5.0.0/pre-migration.py new file mode 100644 index 00000000..ca208e9d --- /dev/null +++ b/contract/migrations/12.0.5.0.0/pre-migration.py @@ -0,0 +1,10 @@ +def migrate(cr, version): + # pre-paid/post-paid becomes significant for monthlylastday too, + # make sure it has the value that was implied for previous versions. + cr.execute( + """\ + UPDATE contract_line + SET recurring_invoicing_type = 'post-paid' + WHERE recurring_rule_type = 'monthlylastday' + """ + ) diff --git a/contract/models/contract_line.py b/contract/models/contract_line.py index 93711c5d..1a5fa3d0 100644 --- a/contract/models/contract_line.py +++ b/contract/models/contract_line.py @@ -380,6 +380,22 @@ class ContractLine(models.Model): max_date_end=False, ) + @api.model + def _get_offset(self, recurring_invoicing_type, recurring_rule_type): + """Return a relativedelta to offset the invoice date compared + to the period start or end date. + + This method will disappear when the offset becomes user controlled. + """ + if ( + recurring_invoicing_type == 'pre-paid' + or recurring_rule_type == 'monthlylastday' + ): + offset = 0 + else: + offset = 1 + return relativedelta(days=offset) + @api.model def _get_recurring_next_date( self, @@ -398,12 +414,11 @@ class ContractLine(models.Model): ) if not next_period_date_end: return False - if recurring_rule_type == 'monthlylastday': - recurring_next_date = next_period_date_end - elif recurring_invoicing_type == 'pre-paid': - recurring_next_date = next_period_date_start + offset = self._get_offset(recurring_invoicing_type, recurring_rule_type) + if recurring_invoicing_type == 'pre-paid': + recurring_next_date = next_period_date_start + offset else: # post-paid - recurring_next_date = next_period_date_end + relativedelta(days=1) + recurring_next_date = next_period_date_end + offset return recurring_next_date @api.model @@ -433,20 +448,18 @@ class ContractLine(models.Model): ) else: # special algorithm when the next invoice date is forced - if recurring_rule_type == 'monthlylastday': - next_period_date_end = next_invoice_date - elif recurring_invoicing_type == 'pre-paid': + offset = self._get_offset(recurring_invoicing_type, recurring_rule_type) + if recurring_invoicing_type == 'pre-paid': next_period_date_end = ( next_invoice_date + - offset + self.get_relative_delta( recurring_rule_type, recurring_interval ) - relativedelta(days=1) ) else: # post-paid - next_period_date_end = next_invoice_date - relativedelta( - days=1 - ) + next_period_date_end = next_invoice_date - offset if max_date_end and next_period_date_end > max_date_end: # end date is past max_date_end: trim it next_period_date_end = max_date_end diff --git a/contract/tests/test_contract.py b/contract/tests/test_contract.py index 925ab2ce..e6bf09ec 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -614,12 +614,17 @@ class TestContract(TestContractBase): False), ), ( - to_date('2018-01-31'), + to_date('2018-01-06'), (to_date('2018-01-06'), 'pre-paid', 'monthlylastday', 1, False), ), ( to_date('2018-02-28'), + (to_date('2018-01-05'), 'post-paid', 'monthlylastday', 2, + False), + ), + ( + to_date('2018-01-05'), (to_date('2018-01-05'), 'pre-paid', 'monthlylastday', 2, False), ), @@ -1363,7 +1368,7 @@ class TestContract(TestContractBase): len(invoice_lines), ) - def test_get_period_to_invoice_monthlylastday(self): + def test_get_period_to_invoice_monthlylastday_postpaid(self): self.acct_line.date_start = '2018-01-05' self.acct_line.recurring_invoicing_type = 'post-paid' self.acct_line.recurring_rule_type = 'monthlylastday' @@ -1394,6 +1399,37 @@ class TestContract(TestContractBase): self.assertEqual(last, to_date('2018-03-15')) self.acct_line.manual_renew_needed = True + def test_get_period_to_invoice_monthlylastday_prepaid(self): + self.acct_line.date_start = '2018-01-05' + self.acct_line.recurring_invoicing_type = 'pre-paid' + self.acct_line.recurring_rule_type = 'monthlylastday' + self.acct_line.date_end = '2018-03-15' + self.acct_line._onchange_date_start() + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date('2018-01-05')) + self.assertEqual(last, to_date('2018-01-31')) + self.contract.recurring_create_invoice() + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date('2018-02-01')) + self.assertEqual(last, to_date('2018-02-28')) + self.contract.recurring_create_invoice() + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date('2018-03-01')) + self.assertEqual(last, to_date('2018-03-15')) + self.acct_line.manual_renew_needed = True + def test_get_period_to_invoice_monthly_pre_paid_2(self): self.acct_line.date_start = '2018-01-05' self.acct_line.recurring_invoicing_type = 'pre-paid' diff --git a/contract/views/abstract_contract_line.xml b/contract/views/abstract_contract_line.xml index b66077ee..351ded65 100644 --- a/contract/views/abstract_contract_line.xml +++ b/contract/views/abstract_contract_line.xml @@ -59,8 +59,7 @@ - + diff --git a/contract_sale_mandate/tests/test_contract_sale_mandate.py b/contract_sale_mandate/tests/test_contract_sale_mandate.py index eb36adcd..04515133 100644 --- a/contract_sale_mandate/tests/test_contract_sale_mandate.py +++ b/contract_sale_mandate/tests/test_contract_sale_mandate.py @@ -26,6 +26,7 @@ class TestContractSaleMandate(TestContractBase): 'is_contract': True, 'default_qty': 12, 'recurring_rule_type': "monthlylastday", + 'recurring_invoicing_type': "post-paid", 'contract_template_id': cls.contract_template1.id, } ) diff --git a/product_contract/tests/test_sale_order.py b/product_contract/tests/test_sale_order.py index 7a630cbb..307cf908 100644 --- a/product_contract/tests/test_sale_order.py +++ b/product_contract/tests/test_sale_order.py @@ -43,6 +43,7 @@ class TestSaleOrder(TransactionCase): 'is_contract': True, 'default_qty': 12, 'recurring_rule_type': "monthlylastday", + 'recurring_invoicing_type': "post-paid", 'contract_template_id': self.contract_template1.id, } ) diff --git a/product_contract/views/product_template.xml b/product_contract/views/product_template.xml index 400afa99..057ec95b 100644 --- a/product_contract/views/product_template.xml +++ b/product_contract/views/product_template.xml @@ -33,8 +33,7 @@ - + diff --git a/product_contract/views/sale_order.xml b/product_contract/views/sale_order.xml index e5da25fe..4fd1b90b 100644 --- a/product_contract/views/sale_order.xml +++ b/product_contract/views/sale_order.xml @@ -58,8 +58,7 @@ - +