diff --git a/product_contract/migrations/12.0.4.0.0/pre-migration.py b/product_contract/migrations/12.0.4.0.0/pre-migration.py
new file mode 100644
index 000000000..f6e2351c0
--- /dev/null
+++ b/product_contract/migrations/12.0.4.0.0/pre-migration.py
@@ -0,0 +1,36 @@
+# Copyright 2019 Tecnativa - Ernesto Tejeda
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from openupgradelib import openupgrade
+
+
+@openupgrade.migrate()
+def migrate(env, version):
+ # Convert contract_template_id field of the product_template table
+ # to a company dependent field
+ model_name = "product.template"
+ model_table_name = "product_template"
+ origin_field_name = "contract_template_id"
+ destination_field_name = "property_contract_template_id"
+ # Add ir.model.fields entry
+ env.cr.execute(
+ "SELECT id FROM ir_model WHERE model = %s", (model_name, ),
+ )
+ model_id = env.cr.fetchone()[0]
+ openupgrade.logged_query(
+ env.cr, """
+ INSERT INTO ir_model_fields (
+ model_id, model, name, field_description, ttype, state, relation
+ ) VALUES (
+ %s, %s, %s, %s, %s, %s, %s
+ )""",
+ (model_id, model_name, destination_field_name, 'OU', "many2one",
+ 'base', 'contract.template'),
+ )
+ openupgrade.convert_to_company_dependent(
+ env,
+ model_name,
+ origin_field_name,
+ destination_field_name,
+ model_table_name,
+ )
diff --git a/product_contract/models/product_template.py b/product_contract/models/product_template.py
index 2eb2eca56..3ce6bdc44 100644
--- a/product_contract/models/product_template.py
+++ b/product_contract/models/product_template.py
@@ -10,8 +10,10 @@ class ProductTemplate(models.Model):
_inherit = 'product.template'
is_contract = fields.Boolean('Is a contract')
- contract_template_id = fields.Many2one(
- comodel_name='contract.template', string='Contract Template'
+ property_contract_template_id = fields.Many2one(
+ comodel_name='contract.template',
+ string='Contract Template',
+ company_dependent=True,
)
default_qty = fields.Integer(string="Default Quantity", default=1)
recurring_rule_type = fields.Selection(
@@ -58,13 +60,13 @@ class ProductTemplate(models.Model):
help="Specify Interval for automatic renewal.",
)
- @api.onchange('is_contract')
- def _change_is_contract(self):
- """ Clear the relation to contract_template_id when downgrading
- product from contract
- """
- if not self.is_contract:
- self.contract_template_id = False
+ @api.multi
+ def write(self, vals):
+ if 'is_contract' in vals and vals['is_contract'] is False:
+ for company in self.env['res.company'].search([]):
+ self.with_context(force_company=company.id).write(
+ {'property_contract_template_id': False})
+ super().write(vals)
@api.constrains('is_contract', 'type')
def _check_contract_product_type(self):
diff --git a/product_contract/models/sale_order.py b/product_contract/models/sale_order.py
index 4331d8079..70c65ae8c 100644
--- a/product_contract/models/sale_order.py
+++ b/product_contract/models/sale_order.py
@@ -2,7 +2,8 @@
# Copyright 2018 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-from odoo import fields, api, models
+from odoo import _, fields, api, models
+from odoo.exceptions import ValidationError
class SaleOrder(models.Model):
@@ -70,12 +71,23 @@ class SaleOrder(models.Model):
'sale_order_line_id'
)
)
- for contract_template in line_to_create_contract.mapped(
- 'product_id.contract_template_id'
- ):
+ for order_line in line_to_create_contract:
+ contract_template = order_line.product_id.with_context(
+ force_company=rec.company_id.id
+ ).property_contract_template_id
+ if not contract_template:
+ raise ValidationError(
+ _("You must specify a contract "
+ "template for '{}' product in '{}' company.").format(
+ order_line.product_id.name,
+ rec.company_id.name
+ )
+ )
order_lines = line_to_create_contract.filtered(
lambda r, template=contract_template:
- r.product_id.contract_template_id == template
+ r.product_id.with_context(
+ force_company=r.order_id.company_id.id
+ ).property_contract_template_id == template
)
contract = contract_model.create(
rec._prepare_contract_value(contract_template)
diff --git a/product_contract/models/sale_order_line.py b/product_contract/models/sale_order_line.py
index dc21fa9ad..02d0c91b2 100644
--- a/product_contract/models/sale_order_line.py
+++ b/product_contract/models/sale_order_line.py
@@ -19,8 +19,7 @@ class SaleOrderLine(models.Model):
contract_template_id = fields.Many2one(
comodel_name='contract.template',
string='Contract Template',
- related='product_id.product_tmpl_id.contract_template_id',
- readonly=True,
+ compute='_compute_contract_template_id',
)
recurring_rule_type = fields.Selection(
[
@@ -68,6 +67,14 @@ class SaleOrderLine(models.Model):
help="Specify Interval for automatic renewal.",
)
+ @api.multi
+ @api.depends('product_id')
+ def _compute_contract_template_id(self):
+ for rec in self:
+ rec.contract_template_id = rec.product_id.with_context(
+ force_company=rec.order_id.company_id.id
+ ).property_contract_template_id
+
@api.multi
def _get_auto_renew_rule_type(self):
"""monthly last day don't make sense for auto_renew_rule_type"""
diff --git a/product_contract/tests/test_product.py b/product_contract/tests/test_product.py
index 64a125c87..e5ef52c8a 100644
--- a/product_contract/tests/test_product.py
+++ b/product_contract/tests/test_product.py
@@ -16,13 +16,14 @@ class TestProductTemplate(TransactionCase):
)
def test_change_is_contract(self):
- """ It should verify that the contract_template_id is removed
- when is_contract is False """
+ """ It should verify that the property_contract_template_id
+ field value is removed for all the companies when
+ is_contract is set to False """
self.service_product.is_contract = True
- self.service_product.contract_template_id = self.contract.id
+ self.service_product.property_contract_template_id = self.contract.id
self.service_product.is_contract = False
- self.service_product.product_tmpl_id._change_is_contract()
- self.assertEquals(len(self.service_product.contract_template_id), 0)
+ self.assertEquals(len(
+ self.service_product.property_contract_template_id), 0)
def test_check_contract_product_type(self):
"""
diff --git a/product_contract/tests/test_sale_order.py b/product_contract/tests/test_sale_order.py
index a71d95b81..36705af7c 100644
--- a/product_contract/tests/test_sale_order.py
+++ b/product_contract/tests/test_sale_order.py
@@ -38,19 +38,21 @@ class TestSaleOrder(TransactionCase):
],
}
)
- self.product1.write(
+ self.product1.with_context(
+ force_company=self.sale.company_id.id).write(
{
'is_contract': True,
'default_qty': 12,
'recurring_rule_type': "monthlylastday",
'recurring_invoicing_type': "post-paid",
- 'contract_template_id': self.contract_template1.id,
+ 'property_contract_template_id': self.contract_template1.id,
}
)
- self.product2.write(
+ self.product2.with_context(
+ force_company=self.sale.company_id.id).write(
{
'is_contract': True,
- 'contract_template_id': self.contract_template2.id,
+ 'property_contract_template_id': self.contract_template2.id,
}
)
self.order_line1 = self.sale.order_line.filtered(
@@ -111,15 +113,28 @@ class TestSaleOrder(TransactionCase):
contract_line.recurring_next_date, Date.to_date('2018-01-31')
)
- def test_contract_company(self):
- """
- contract company must be the sale order company and not the user one
- """
+ def test_change_sale_company(self):
self.assertTrue(self.sale.company_id)
other_company = self.env['res.company'].create(
{'name': 'other company', 'parent_id': self.sale.company_id.id}
)
self.sale.company_id = other_company
+ with self.assertRaises(ValidationError):
+ self.sale.action_confirm()
+
+ def test_change_sale_company_2(self):
+ """Contract company must be the sale order company."""
+ self.assertTrue(self.sale.company_id)
+ other_company = self.env['res.company'].create(
+ {'name': 'other company', 'parent_id': self.sale.company_id.id}
+ )
+ self.product1.with_context(
+ force_company=other_company.id
+ ).property_contract_template_id = self.contract_template1
+ self.product2.with_context(
+ force_company=other_company.id
+ ).property_contract_template_id = self.contract_template2
+ self.sale.company_id = other_company
self.sale.action_confirm()
contracts = self.sale.order_line.mapped('contract_id')
self.assertEqual(contracts.mapped('company_id'), other_company)
@@ -132,7 +147,7 @@ class TestSaleOrder(TransactionCase):
self.assertEqual(self.order_line1.invoice_status, 'no')
invoice = self.order_line1.contract_id.recurring_create_invoice()
self.assertTrue(invoice)
- self.assertEqual(self.order_line1.invoice_qty, 1)
+ self.assertEqual(self.order_line1.qty_invoiced, 1)
self.assertEqual(self.order_line1.qty_to_invoice, 0)
def test_action_confirm_without_contract_creation(self):
@@ -217,7 +232,7 @@ class TestSaleOrder(TransactionCase):
self.sale.action_confirm()
self.assertEqual(self.order_line1.invoice_status, 'no')
- def test_sale_order_invoice_status(self):
+ def test_sale_order_invoice_status_2(self):
"""Sale order with only contract product should have nothing to
invoice status directtly"""
self.sale.order_line.filtered(
diff --git a/product_contract/views/product_template.xml b/product_contract/views/product_template.xml
index 59ad6e7eb..c6ecef126 100644
--- a/product_contract/views/product_template.xml
+++ b/product_contract/views/product_template.xml
@@ -24,8 +24,7 @@
name="contract"
attrs="{'invisible': [('is_contract', '=', False)],}">
-
+