From 20cdcdede2c0440090dba4a569b8cd3d56bdedb5 Mon Sep 17 00:00:00 2001 From: sbejaoui Date: Wed, 13 Nov 2019 11:29:18 +0100 Subject: [PATCH] [12.0][IMP] - Add an action for contracts manual invoicing It happen that a company has to trigger the invoicing action to generate invoices before the scheduled date (to print and prepare invoices documents, check invoices, etc.). This requires technical access for end users with the risk that this represents. This commit adds a new wizard to run the invoicing action for a given date with a helper to see and check the contract that will be invoiced. When the manual action is called, the system displays all created invoices. --- contract/__manifest__.py | 1 + contract/models/contract.py | 9 +-- contract/security/ir.model.access.csv | 1 + contract/tests/test_contract.py | 33 ++++++++++ contract/wizards/__init__.py | 1 + .../contract_manually_create_invoice.py | 62 +++++++++++++++++++ .../contract_manually_create_invoice.xml | 58 +++++++++++++++++ 7 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 contract/wizards/contract_manually_create_invoice.py create mode 100644 contract/wizards/contract_manually_create_invoice.xml diff --git a/contract/__manifest__.py b/contract/__manifest__.py index 2851e545..a610f509 100644 --- a/contract/__manifest__.py +++ b/contract/__manifest__.py @@ -29,6 +29,7 @@ 'data/contract_renew_cron.xml', 'data/mail_template.xml', 'wizards/contract_line_wizard.xml', + 'wizards/contract_manually_create_invoice.xml', 'views/abstract_contract_line.xml', 'views/contract.xml', 'views/contract_line.xml', diff --git a/contract/models/contract.py b/contract/models/contract.py index 30fe1d9a..a91fdf08 100644 --- a/contract/models/contract.py +++ b/contract/models/contract.py @@ -460,8 +460,9 @@ class ContractContract(models.Model): return self._finalize_and_create_invoices(invoices_values) @api.model - def cron_recurring_create_invoice(self): - domain = self._get_contracts_to_invoice_domain() + def cron_recurring_create_invoice(self, date_ref=None): + if not date_ref: + date_ref = fields.Date.context_today(self) + domain = self._get_contracts_to_invoice_domain(date_ref) contracts_to_invoice = self.search(domain) - date_ref = fields.Date.context_today(contracts_to_invoice) - contracts_to_invoice._recurring_create_invoice(date_ref) + return contracts_to_invoice._recurring_create_invoice(date_ref) diff --git a/contract/security/ir.model.access.csv b/contract/security/ir.model.access.csv index 4b3e42de..05395a7d 100644 --- a/contract/security/ir.model.access.csv +++ b/contract/security/ir.model.access.csv @@ -7,3 +7,4 @@ "contract_line_user","Recurring user","model_contract_line","account.group_account_invoice",1,0,0,0 "contract_template_line_manager","Recurring manager","model_contract_template_line","account.group_account_manager",1,1,1,1 "contract_template_line_user","Recurring user","model_contract_template_line","account.group_account_invoice",1,0,0,0 +"contract_manually_create_invoice_manager","Recurring manager access to manually invoice contract action","model_contract_manually_create_invoice","account.group_account_manager",1,1,1,0 diff --git a/contract/tests/test_contract.py b/contract/tests/test_contract.py index e406a45e..d694a516 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -1711,6 +1711,39 @@ class TestContract(TestContractBase): len(invoice_lines), ) + def test_contract_manually_create_invoice(self): + self.acct_line.date_start = '2018-01-01' + self.acct_line.recurring_invoicing_type = 'post-paid' + self.acct_line.date_end = '2018-03-15' + self.acct_line._onchange_date_start() + self.contract2.unlink() + contracts = self.contract + for i in range(10): + contracts |= self.contract.copy() + wizard = self.env['contract.manually.create.invoice'].create({ + 'invoice_date': self.today + }) + wizard.action_show_contract_to_invoice() + contract_to_invoice_count = wizard.contract_to_invoice_count + self.assertEqual( + contracts, + self.env['contract.contract'].search( + wizard.action_show_contract_to_invoice()['domain'] + ), + ) + action = wizard.create_invoice() + invoice_lines = self.env['account.invoice.line'].search( + [('contract_line_id', 'in', + contracts.mapped('contract_line_ids').ids)] + ) + self.assertEqual( + len(contracts.mapped('contract_line_ids')), + len(invoice_lines), + ) + invoices = self.env['account.invoice'].search(action['domain']) + self.assertEqual(invoice_lines.mapped('invoice_id'), invoices) + self.assertEqual(len(invoices), contract_to_invoice_count) + 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' diff --git a/contract/wizards/__init__.py b/contract/wizards/__init__.py index 146dcc66..1fa21bcc 100644 --- a/contract/wizards/__init__.py +++ b/contract/wizards/__init__.py @@ -1 +1,2 @@ from . import contract_line_wizard +from . import contract_manually_create_invoice diff --git a/contract/wizards/contract_manually_create_invoice.py b/contract/wizards/contract_manually_create_invoice.py new file mode 100644 index 00000000..3f64ec34 --- /dev/null +++ b/contract/wizards/contract_manually_create_invoice.py @@ -0,0 +1,62 @@ +# Copyright 2019 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ + + +class ContractManuallyCreateInvoice(models.Model): + + _name = 'contract.manually.create.invoice' + _description = 'Contract Manually Create Invoice Wizard' + + invoice_date = fields.Date(string="Invoice Date", required=True) + contract_to_invoice_count = fields.Integer( + compute="_compute_contract_to_invoice_count" + ) + + @api.multi + def action_show_contract_to_invoice(self): + self.ensure_one() + if not self.invoice_date: + contract_to_invoice_domain = [('id', '=', False)] + else: + contract_to_invoice_domain = self.env[ + 'contract.contract' + ]._get_contracts_to_invoice_domain(self.invoice_date) + + return { + "type": "ir.actions.act_window", + "name": _("Contracts to invoice"), + "res_model": "contract.contract", + "domain": contract_to_invoice_domain, + "view_mode": "tree,form", + "context": self.env.context, + } + + @api.depends('invoice_date') + def _compute_contract_to_invoice_count(self): + self.ensure_one() + if not self.invoice_date: + self.contract_to_invoice_count = 0 + else: + contract_model = self.env['contract.contract'] + self.contract_to_invoice_count = contract_model.search_count( + contract_model._get_contracts_to_invoice_domain( + self.invoice_date + ) + ) + + @api.multi + def create_invoice(self): + self.ensure_one() + invoices = self.env['contract.contract'].cron_recurring_create_invoice( + self.invoice_date + ) + return { + "type": "ir.actions.act_window", + "name": _("Invoices"), + "res_model": "account.invoice", + "domain": [('id', 'in', invoices.ids)], + "view_mode": "tree,form", + "context": self.env.context, + } diff --git a/contract/wizards/contract_manually_create_invoice.xml b/contract/wizards/contract_manually_create_invoice.xml new file mode 100644 index 00000000..b5786513 --- /dev/null +++ b/contract/wizards/contract_manually_create_invoice.xml @@ -0,0 +1,58 @@ + + + + + + + contract.manually.create.invoice + +
+ + + + + + + + +
+
+
+
+
+ + + Manually Invoice Contracts + contract.manually.create.invoice + form + {} + new + + + + Manually Invoice Contracts + + + + +