mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
@@ -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