mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[IMP] - Add recurrence fields to product template and sale order line
This commit is contained in:
@@ -17,7 +17,8 @@
|
|||||||
'contract_sale',
|
'contract_sale',
|
||||||
],
|
],
|
||||||
'data': [
|
'data': [
|
||||||
'views/product_template_view.xml',
|
'views/product_template.xml',
|
||||||
|
'views/sale_order.xml',
|
||||||
],
|
],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'application': False,
|
'application': False,
|
||||||
|
|||||||
@@ -15,6 +15,30 @@ class ProductTemplate(models.Model):
|
|||||||
comodel_name='account.analytic.contract', string='Contract Template'
|
comodel_name='account.analytic.contract', string='Contract Template'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
recurring_rule_type = fields.Selection(
|
||||||
|
[
|
||||||
|
('daily', 'Day(s)'),
|
||||||
|
('weekly', 'Week(s)'),
|
||||||
|
('monthly', 'Month(s)'),
|
||||||
|
('monthlylastday', 'Month(s) last day'),
|
||||||
|
('yearly', 'Year(s)'),
|
||||||
|
],
|
||||||
|
default='monthly',
|
||||||
|
string='Recurrence',
|
||||||
|
help="Specify Interval for automatic invoice generation.",
|
||||||
|
)
|
||||||
|
recurring_invoicing_type = fields.Selection(
|
||||||
|
[('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
|
||||||
|
default='pre-paid',
|
||||||
|
string='Invoicing type',
|
||||||
|
help="Specify if process date is 'from' or 'to' invoicing date",
|
||||||
|
)
|
||||||
|
recurring_interval = fields.Integer(
|
||||||
|
default=1,
|
||||||
|
string='Repeat Every',
|
||||||
|
help="Repeat every (Days/Week/Month/Year)",
|
||||||
|
)
|
||||||
|
|
||||||
@api.onchange('is_contract')
|
@api.onchange('is_contract')
|
||||||
def _change_is_contract(self):
|
def _change_is_contract(self):
|
||||||
""" Clear the relation to contract_template_id when downgrading
|
""" Clear the relation to contract_template_id when downgrading
|
||||||
|
|||||||
@@ -2,12 +2,22 @@
|
|||||||
# Copyright 2017 LasLabs Inc.
|
# Copyright 2017 LasLabs Inc.
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
from odoo import api, models
|
from odoo import fields, api, models
|
||||||
|
|
||||||
|
|
||||||
class SaleOrder(models.Model):
|
class SaleOrder(models.Model):
|
||||||
_inherit = 'sale.order'
|
_inherit = 'sale.order'
|
||||||
|
|
||||||
|
is_contract = fields.Boolean(
|
||||||
|
string='Is a contract', compute="_compute_is_contract"
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.depends('order_line')
|
||||||
|
def _compute_is_contract(self):
|
||||||
|
self.is_contract = any(
|
||||||
|
self.order_line.mapped('is_contract')
|
||||||
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_confirm(self):
|
def action_confirm(self):
|
||||||
""" If we have a contract in the order, set it up """
|
""" If we have a contract in the order, set it up """
|
||||||
|
|||||||
@@ -1,14 +1,57 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright 2017 LasLabs Inc.
|
# Copyright 2017 LasLabs Inc.
|
||||||
|
# Copyright 2017 ACSONE SA/NV.
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
from odoo import fields, models
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
class SaleOrderLine(models.Model):
|
class SaleOrderLine(models.Model):
|
||||||
_inherit = 'sale.order.line'
|
_inherit = 'sale.order.line'
|
||||||
|
|
||||||
contract_id = fields.Many2one(
|
is_contract = fields.Boolean(
|
||||||
comodel_name='account.analytic.account',
|
string='Is a contract', related="product_id.is_contract"
|
||||||
string='Contract'
|
|
||||||
)
|
)
|
||||||
|
contract_id = fields.Many2one(
|
||||||
|
comodel_name='account.analytic.account', string='Contract'
|
||||||
|
)
|
||||||
|
recurring_rule_type = fields.Selection(
|
||||||
|
[
|
||||||
|
('daily', 'Day(s)'),
|
||||||
|
('weekly', 'Week(s)'),
|
||||||
|
('monthly', 'Month(s)'),
|
||||||
|
('monthlylastday', 'Month(s) last day'),
|
||||||
|
('yearly', 'Year(s)'),
|
||||||
|
],
|
||||||
|
default='monthly',
|
||||||
|
string='Recurrence',
|
||||||
|
help="Specify Interval for automatic invoice generation.",
|
||||||
|
copy=False,
|
||||||
|
)
|
||||||
|
recurring_invoicing_type = fields.Selection(
|
||||||
|
[('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
|
||||||
|
default='pre-paid',
|
||||||
|
string='Invoicing type',
|
||||||
|
help="Specify if process date is 'from' or 'to' invoicing date",
|
||||||
|
copy=False,
|
||||||
|
)
|
||||||
|
recurring_interval = fields.Integer(
|
||||||
|
default=1,
|
||||||
|
string='Repeat Every',
|
||||||
|
help="Repeat every (Days/Week/Month/Year)",
|
||||||
|
copy=False,
|
||||||
|
)
|
||||||
|
date_start = fields.Date(string='Date Start', default=fields.Date.today())
|
||||||
|
date_end = fields.Date(string='Date End', index=True)
|
||||||
|
recurring_next_date = fields.Date(
|
||||||
|
default=fields.Date.today(), copy=False, string='Date of Next Invoice'
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.onchange('product_id')
|
||||||
|
def onchange_product(self):
|
||||||
|
if self.product_id.is_contract:
|
||||||
|
self.recurring_rule_type = self.product_id.recurring_rule_type
|
||||||
|
self.recurring_invoicing_type = (
|
||||||
|
self.product_id.recurring_invoicing_type
|
||||||
|
)
|
||||||
|
self.recurring_interval = self.product_id.recurring_interval
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright 2017 LasLabs Inc.
|
# Copyright 2017 LasLabs Inc.
|
||||||
|
# Copyright 2018 ACSONE SA/NV.
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
from . import test_product
|
from . import test_product
|
||||||
from . import test_sale_order
|
from . import test_sale_order
|
||||||
|
from . import test_sale_order_line
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ class TestSaleOrder(TransactionCase):
|
|||||||
def test_action_done(self):
|
def test_action_done(self):
|
||||||
""" It should create a contract when the sale for a contract is set
|
""" It should create a contract when the sale for a contract is set
|
||||||
to done for the first time """
|
to done for the first time """
|
||||||
|
|
||||||
|
self.assertTrue(self.sale.is_contract)
|
||||||
self.env['account.analytic.account']._patch_method(
|
self.env['account.analytic.account']._patch_method(
|
||||||
'create', MagicMock()
|
'create', MagicMock()
|
||||||
)
|
)
|
||||||
|
|||||||
37
product_contract/tests/test_sale_order_line.py
Normal file
37
product_contract/tests/test_sale_order_line.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2018 ACSONE SA/NV.
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from mock import MagicMock
|
||||||
|
from odoo.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestSaleOrder(TransactionCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestSaleOrder, self).setUp()
|
||||||
|
self.product = self.env.ref('product.product_product_1')
|
||||||
|
self.sale = self.env.ref('sale.sale_order_2')
|
||||||
|
self.contract = self.env['account.analytic.contract'].create({
|
||||||
|
'name': 'Test',
|
||||||
|
})
|
||||||
|
self.product.product_tmpl_id.is_contract = True
|
||||||
|
self.sale_order_line = self.sale.order_line.filtered(
|
||||||
|
lambda l: l.product_id == self.product
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_onchange_product(self):
|
||||||
|
""" It should get recurrence invoicing info to the sale line from
|
||||||
|
its product """
|
||||||
|
self.assertEqual(
|
||||||
|
self.sale_order_line.recurring_rule_type,
|
||||||
|
self.product.recurring_rule_type
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
self.sale_order_line.recurring_interval,
|
||||||
|
self.product.recurring_interval
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
self.sale_order_line.recurring_invoicing_type,
|
||||||
|
self.product.recurring_invoicing_type
|
||||||
|
)
|
||||||
44
product_contract/views/product_template.xml
Normal file
44
product_contract/views/product_template.xml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2017 LasLabs Inc.
|
||||||
|
Copyright 2018 ACSONE SA/NV.
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
-->
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="product_template_form_contract_view" model="ir.ui.view">
|
||||||
|
<field name="name">account.invoice.select.contract</field>
|
||||||
|
<field name="model">product.template</field>
|
||||||
|
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//div[@name='options']" position="inside">
|
||||||
|
<div>
|
||||||
|
<field name="is_contract"/>
|
||||||
|
<label for="is_contract"/>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//group[@name='group_standard_price']"
|
||||||
|
position="inside">
|
||||||
|
<field name="contract_template_id"
|
||||||
|
attrs="{'invisible': [('is_contract', '=', False)],
|
||||||
|
'required':[('is_contract', '=', True)]}"/>
|
||||||
|
<field name="recurring_invoicing_type"
|
||||||
|
attrs="{'invisible': [('is_contract', '=', False)],
|
||||||
|
'required':[('is_contract', '=', True)]}"/>
|
||||||
|
|
||||||
|
<label for="recurring_interval" attrs="{'invisible': [('is_contract', '=', False)],
|
||||||
|
'required':[('is_contract', '=', True)]}"/>
|
||||||
|
<div attrs="{'invisible': [('is_contract', '=', False)],
|
||||||
|
'required':[('is_contract', '=', True)]}">
|
||||||
|
<field name="recurring_interval"
|
||||||
|
class="oe_inline" nolabel="1"/>
|
||||||
|
<field name="recurring_rule_type"
|
||||||
|
class="oe_inline" nolabel="1"/>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Copyright 2017 LasLabs Inc.
|
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
||||||
-->
|
|
||||||
|
|
||||||
<odoo>
|
|
||||||
|
|
||||||
<record id="product_template_form_contract_view" model="ir.ui.view">
|
|
||||||
<field name="name">account.invoice.select.contract</field>
|
|
||||||
<field name="model">product.template</field>
|
|
||||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<xpath expr="//div[@name='options']" position="inside">
|
|
||||||
<div>
|
|
||||||
<field name="is_contract" />
|
|
||||||
<label for="is_contract" />
|
|
||||||
</div>
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//group[@name='group_standard_price']" position="inside">
|
|
||||||
<field name="contract_template_id"
|
|
||||||
attrs="{'invisible': [('is_contract', '=', False)],
|
|
||||||
'required':[('is_contract', '=', True)]}" />
|
|
||||||
</xpath>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</odoo>
|
|
||||||
63
product_contract/views/sale_order.xml
Normal file
63
product_contract/views/sale_order.xml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright 2018 ACSONE SA/NV.
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
-->
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="view_order_form" model="ir.ui.view">
|
||||||
|
<field name="name">sale.order.form (in product_contract)</field>
|
||||||
|
<field name="model">sale.order</field>
|
||||||
|
<field name="inherit_id" ref="sale.view_order_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='order_line']" position="before">
|
||||||
|
<field name="is_contract" invisible="1"/>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='order_line']/form//field[@name='tax_id']/parent::group"
|
||||||
|
position="after">
|
||||||
|
<separator colspan="4" string="Recurrence Invoicing"
|
||||||
|
attrs="{'invisible': [('is_contract', '=', False)]}"/>
|
||||||
|
<group attrs="{'invisible': [('is_contract', '=', False)]}">
|
||||||
|
<field name="is_contract" invisible="1"/>
|
||||||
|
<field name="recurring_invoicing_type"
|
||||||
|
attrs="{'invisible': [('is_contract', '=', False)],
|
||||||
|
'required':[('is_contract', '=', True)]}"/>
|
||||||
|
</group>
|
||||||
|
<group attrs="{'invisible': [('is_contract', '=', False)]}">
|
||||||
|
<label for="recurring_interval"/>
|
||||||
|
<div>
|
||||||
|
<field name="recurring_interval"
|
||||||
|
class="oe_inline" nolabel="1"
|
||||||
|
attrs="{'required':[('is_contract', '=', True)]}"/>
|
||||||
|
<field name="recurring_rule_type"
|
||||||
|
class="oe_inline" nolabel="1"
|
||||||
|
attrs="{'required':[('is_contract', '=', True)]}"/>
|
||||||
|
</div>
|
||||||
|
</group>
|
||||||
|
<group attrs="{'invisible': [('is_contract', '=', False)]}">
|
||||||
|
<field name="date_start"/>
|
||||||
|
<field name="recurring_next_date"/>
|
||||||
|
</group>
|
||||||
|
<group attrs="{'invisible': [('is_contract', '=', False)]}">
|
||||||
|
<field name="date_end"/>
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='order_line']/tree//field[@name='price_total']"
|
||||||
|
position="after">
|
||||||
|
<field name="date_start"
|
||||||
|
attrs="{'column_invisible': [('parent.is_contract', '=', False)]}"/>
|
||||||
|
<field name="date_end"
|
||||||
|
attrs="{'column_invisible': [('parent.is_contract', '=', False)]}"/>
|
||||||
|
<field name="recurring_next_date"
|
||||||
|
attrs="{'column_invisible': [('parent.is_contract', '=', False)]}"/>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='order_line']/tree"
|
||||||
|
position="attributes">
|
||||||
|
<attribute name="editable"/>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user