diff --git a/contract/__manifest__.py b/contract/__manifest__.py
index a29196d64..3d93c989d 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 3592a28ae..7b16dafd6 100644
--- a/contract/models/contract.py
+++ b/contract/models/contract.py
@@ -457,7 +457,17 @@ class ContractContract(models.Model):
This method triggers the creation of the next invoices of the contracts
even if their next invoicing date is in the future.
"""
- return self._recurring_create_invoice()
+ invoice = self._recurring_create_invoice()
+ if invoice:
+ self.message_post(
+ body=_(
+ 'Contract manually invoiced: '
+ 'Invoice'
+ ''
+ )
+ % (invoice._name, invoice.id)
+ )
+ return invoice
@api.multi
def _recurring_create_invoice(self, date_ref=False):
@@ -465,8 +475,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/tests/test_contract.py b/contract/tests/test_contract.py
index 6e59ab640..9f613de8c 100644
--- a/contract/tests/test_contract.py
+++ b/contract/tests/test_contract.py
@@ -1737,6 +1737,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 146dcc66d..1fa21bcc9 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 000000000..6531d3352
--- /dev/null
+++ b/contract/wizards/contract_manually_create_invoice.py
@@ -0,0 +1,66 @@
+# 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.TransientModel):
+
+ _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_ids"
+ )
+ contract_to_invoice_ids = fields.Many2many(
+ comodel_name="contract.contract",
+ compute="_compute_contract_to_invoice_ids",
+ )
+ contract_type = fields.Selection(
+ selection=[('sale', 'Customer'), ('purchase', 'Supplier')],
+ default='sale',
+ required=True,
+ )
+
+ @api.depends('invoice_date')
+ def _compute_contract_to_invoice_ids(self):
+ if not self.invoice_date:
+ # trick to show no invoice when no date has been entered yet
+ contract_to_invoice_domain = [('id', '=', False)]
+ else:
+ contract_to_invoice_domain = self.env[
+ 'contract.contract'
+ ]._get_contracts_to_invoice_domain(self.invoice_date)
+ self.contract_to_invoice_ids = self.env['contract.contract'].search(
+ contract_to_invoice_domain
+ + [('contract_type', '=', self.contract_type)]
+ )
+ self.contract_to_invoice_count = len(self.contract_to_invoice_ids)
+
+ @api.multi
+ def action_show_contract_to_invoice(self):
+ self.ensure_one()
+ return {
+ "type": "ir.actions.act_window",
+ "name": _("Contracts to invoice"),
+ "res_model": "contract.contract",
+ "domain": [('id', 'in', self.contract_to_invoice_ids.ids)],
+ "view_mode": "tree,form",
+ "context": self.env.context,
+ }
+
+ @api.multi
+ def create_invoice(self):
+ self.ensure_one()
+ invoices = self.env['account.invoice']
+ for contract in self.contract_to_invoice_ids:
+ invoices |= contract.recurring_create_invoice()
+ 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 000000000..cd396f894
--- /dev/null
+++ b/contract/wizards/contract_manually_create_invoice.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+ contract.manually.create.invoice
+
+
+
+
+
+
+ Manually Invoice Sale Contracts
+ contract.manually.create.invoice
+ form
+ {'default_contract_type': 'sale'}
+ new
+
+
+
+
+
+ Manually Invoice Purchase Contracts
+ contract.manually.create.invoice
+ form
+ {'default_contract_type': 'purchase'}
+ new
+
+
+
+