mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[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. [12.0][IMP] - log the manual invoice action in contract chatter [IMP] - Add alink to the invoice in contract message at manual invoicing [IMP] - Improve code [FIX] - log message for invoice creation only when there is an invoice [IMP] - split the manual invoice menu into to menus sale & purhcase [IMP] - hide invoice button if there is nothing to invoice
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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: '
|
||||
'<a href="#" data-oe-model="%s" data-oe-id="%s">Invoice'
|
||||
'</a>'
|
||||
)
|
||||
% (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)
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
from . import contract_line_wizard
|
||||
from . import contract_manually_create_invoice
|
||||
|
||||
66
contract/wizards/contract_manually_create_invoice.py
Normal file
66
contract/wizards/contract_manually_create_invoice.py
Normal file
@@ -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,
|
||||
}
|
||||
79
contract/wizards/contract_manually_create_invoice.xml
Normal file
79
contract/wizards/contract_manually_create_invoice.xml
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2019 ACSONE SA/NV
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="contract_manually_create_invoice_form_view">
|
||||
<field name="model">contract.manually.create.invoice</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Contract Manually Create Invoice">
|
||||
<group>
|
||||
<group>
|
||||
<field name="invoice_date"/>
|
||||
<field name="contract_type" invisible="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<button name="action_show_contract_to_invoice" type="object"
|
||||
class="btn-link"
|
||||
attrs="{'invisible': [('contract_to_invoice_count', '=', 0)]}">
|
||||
<field name="contract_to_invoice_count"/>
|
||||
<span attrs="{'invisible': [('contract_to_invoice_count', '>', 1)]}">
|
||||
contract to invoice
|
||||
</span>
|
||||
<span attrs="{'invisible': [('contract_to_invoice_count', '<', 1)]}">
|
||||
contracts to invoice
|
||||
</span>
|
||||
</button>
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="create_invoice"
|
||||
attrs="{'invisible': [('contract_to_invoice_count', '=', 0)]}"
|
||||
string="Create Invoices"
|
||||
class="btn-primary"
|
||||
type="object"/>
|
||||
<button string="Cancel"
|
||||
class="btn-default"
|
||||
special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window"
|
||||
id="sale_contract_manually_create_invoice_act_window">
|
||||
<field name="name">Manually Invoice Sale Contracts</field>
|
||||
<field name="res_model">contract.manually.create.invoice</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="context">{'default_contract_type': 'sale'}</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.menu" id="sale_contract_manually_create_invoice_menu">
|
||||
<field name="name">Manually Invoice Sale Contracts</field>
|
||||
<field name="parent_id" ref="account.menu_finance_receivables"/>
|
||||
<field name="groups_id" eval="[(6, 0, [ref('account.group_account_manager')])]"/>
|
||||
<field name="action"
|
||||
ref="sale_contract_manually_create_invoice_act_window"/>
|
||||
<field name="sequence" eval="999"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window"
|
||||
id="purchase_contract_manually_create_invoice_act_window">
|
||||
<field name="name">Manually Invoice Purchase Contracts</field>
|
||||
<field name="res_model">contract.manually.create.invoice</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="context">{'default_contract_type': 'purchase'}</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.menu" id="purchase_contract_manually_create_invoice_menu">
|
||||
<field name="name">Manually Invoice Purchase Contracts</field>
|
||||
<field name="parent_id" ref="account.menu_finance_payables"/>
|
||||
<field name="groups_id" eval="[(6, 0, [ref('account.group_account_manager')])]"/>
|
||||
<field name="action"
|
||||
ref="purchase_contract_manually_create_invoice_act_window"/>
|
||||
<field name="sequence" eval="999"/>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user