diff --git a/contract/__manifest__.py b/contract/__manifest__.py index 0a7549f1..17c66376 100644 --- a/contract/__manifest__.py +++ b/contract/__manifest__.py @@ -19,6 +19,7 @@ "Odoo Community Association (OCA)", 'website': 'https://github.com/oca/contract', 'depends': ['base', 'account', 'analytic'], + "external_dependencies": {"python": ["dateutil"]}, 'data': [ 'wizards/contract_line_wizard.xml', 'security/ir.model.access.csv', diff --git a/contract/models/contract_line.py b/contract/models/contract_line.py index 22f2525a..d6369456 100644 --- a/contract/models/contract_line.py +++ b/contract/models/contract_line.py @@ -265,14 +265,26 @@ class AccountAnalyticInvoiceLine(models.Model): % line.contract_id.name ) - @api.depends('recurring_next_date', 'date_end') + @api.depends('recurring_next_date', 'date_start', 'date_end') def _compute_create_invoice_visibility(self): + today = fields.Date.today() for line in self: - line.create_invoice_visibility = not line.date_end or ( - line.recurring_next_date - and line.date_end - and line.recurring_next_date <= line.date_end - ) + if today < line.date_start: + line.create_invoice_visibility = False + elif not line.date_end: + line.create_invoice_visibility = True + elif line.recurring_next_date: + if line.recurring_invoicing_type == 'pre-paid': + line.create_invoice_visibility = ( + line.recurring_next_date <= line.date_end + ) + else: + line.create_invoice_visibility = ( + line.recurring_next_date + - line.get_relative_delta( + line.recurring_rule_type, line.recurring_interval + ) + ) <= line.date_end @api.model def recurring_create_invoice(self, contract=False): @@ -288,9 +300,14 @@ class AccountAnalyticInvoiceLine(models.Model): ('contract_id.recurring_invoices', '=', True), ('recurring_next_date', '<=', date_ref), ('is_canceled', '=', False), - '|', - ('date_end', '=', False), - ('date_end', '>=', date_ref), + # '|', + # ('date_end', '=', False), + # ('date_end', '>=', date_ref), + # with this leaf, it's impossible to invoice the last period + # in post-paid case. + # i.e: date_end = 15/03 recurring_next_date = 31/03 + # A solution for this, is to only check recurring_next_date + # and filter with create_invoice_visibility ] ) lines = self.search(domain).filtered('create_invoice_visibility') diff --git a/contract/tests/test_contract.py b/contract/tests/test_contract.py index 5c87c8f8..b3b1eb72 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -212,6 +212,54 @@ class TestContract(TestContractBase): self.acct_line.recurring_next_date, recurring_next_date ) + def test_last_invoice_post_paid(self): + recurring_next_date = to_date('2018-04-30') + self.acct_line.recurring_next_date = '2018-03-31' + self.acct_line.date_end = '2018-03-15' + self.acct_line.recurring_invoicing_type = 'post-paid' + self.contract.recurring_create_invoice() + invoices = self.env['account.invoice'].search( + [('contract_id', '=', self.contract.id)] + ) + self.assertTrue(invoices) + self.assertEqual( + self.acct_line.recurring_next_date, recurring_next_date + ) + self.assertFalse(self.acct_line.create_invoice_visibility) + self.contract.recurring_create_invoice() + new_invoices = self.env['account.invoice'].search( + [('contract_id', '=', self.contract.id)] + ) + self.assertEqual( + invoices, + new_invoices, + "Should not create a new invoice after the last one", + ) + + def test_last_invoice_pre_paid(self): + recurring_next_date = to_date('2018-04-01') + self.acct_line.recurring_next_date = '2018-03-01' + self.acct_line.date_end = '2018-03-15' + self.acct_line.recurring_invoicing_type = 'pre-paid' + self.contract.recurring_create_invoice() + invoices = self.env['account.invoice'].search( + [('contract_id', '=', self.contract.id)] + ) + self.assertTrue(invoices) + self.assertEqual( + self.acct_line.recurring_next_date, recurring_next_date + ) + self.assertFalse(self.acct_line.create_invoice_visibility) + self.contract.recurring_create_invoice() + new_invoices = self.env['account.invoice'].search( + [('contract_id', '=', self.contract.id)] + ) + self.assertEqual( + invoices, + new_invoices, + "Should not create a new invoice after the last one", + ) + def test_onchange_partner_id(self): self.contract._onchange_partner_id() self.assertEqual( @@ -421,6 +469,31 @@ class TestContract(TestContractBase): self.contract.refresh() self.assertFalse(self.contract.create_invoice_visibility) + def test_compute_create_invoice_visibility_for_contract_line(self): + self.acct_line.write( + { + 'recurring_next_date': '2018-01-15', + 'date_start': '2018-01-01', + 'is_auto_renew': False, + 'date_end': False, + } + ) + self.assertTrue(self.acct_line.create_invoice_visibility) + self.acct_line.date_end = '2018-02-01' + self.assertTrue(self.acct_line.create_invoice_visibility) + self.acct_line.date_end = '2018-01-01' + self.assertFalse(self.acct_line.create_invoice_visibility) + self.acct_line.write( + { + 'date_start': fields.Date.today() + relativedelta(months=2), + 'recurring_next_date': fields.Date.today() + + relativedelta(months=2), + 'is_auto_renew': False, + 'date_end': False, + } + ) + self.assertFalse(self.acct_line.create_invoice_visibility) + def test_act_show_contract(self): show_contract = self.partner.with_context( contract_type='sale' diff --git a/contract/views/contract.xml b/contract/views/contract.xml index dad3ecc3..f1d4370c 100644 --- a/contract/views/contract.xml +++ b/contract/views/contract.xml @@ -66,7 +66,7 @@ />