From 09245d0e0e344d2c3e0bea5d65b67925ad8b6df4 Mon Sep 17 00:00:00 2001 From: Ronald Portier Date: Sun, 5 May 2019 14:49:52 +0200 Subject: [PATCH] [FIX] product_contract. Correctly create contract from template. --- product_contract/README.rst | 7 ++-- product_contract/__init__.py | 4 +-- product_contract/__manifest__.py | 7 ++-- product_contract/models/__init__.py | 2 -- product_contract/models/sale_order.py | 21 ++++------- product_contract/models/sale_order_line.py | 36 ++++++++++++++++--- .../tests/test_product_template.py | 2 +- product_contract/tests/test_sale_order.py | 34 +++++++----------- 8 files changed, 58 insertions(+), 55 deletions(-) diff --git a/product_contract/README.rst b/product_contract/README.rst index 6319dcf5..7addcdf8 100644 --- a/product_contract/README.rst +++ b/product_contract/README.rst @@ -1,5 +1,5 @@ .. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg - :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 ================ @@ -7,8 +7,8 @@ Product Contract ================ This module adds support for products to be linked to contract templates. -It also adds functionality to automatically create a contract, from the template, -when a ``sale.order`` contains a product that implements a contract. +It also adds functionality to automatically create a contract from the +template, when a ``sale.order`` contains a product that implements a contract. Usage ===== @@ -48,6 +48,7 @@ Contributors ------------ * Ted Salmon +* Ronald Portier Maintainer diff --git a/product_contract/__init__.py b/product_contract/__init__.py index 44db863b..9732283c 100644 --- a/product_contract/__init__.py +++ b/product_contract/__init__.py @@ -1,5 +1,3 @@ # -*- coding: utf-8 -*- -# Copyright 2017 LasLabs Inc. -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). from . import models diff --git a/product_contract/__manifest__.py b/product_contract/__manifest__.py index e1d4d8ac..47b2d232 100644 --- a/product_contract/__manifest__.py +++ b/product_contract/__manifest__.py @@ -1,15 +1,14 @@ # -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). { 'name': 'Product Contract', - 'version': '10.0.1.0.0', + 'version': '10.0.1.1.0', 'category': 'Contract Management', 'license': 'AGPL-3', 'author': "LasLabs, " "Odoo Community Association (OCA)", - 'website': 'https://laslabs.com', + 'website': 'https://github.com/oca/contract', 'depends': [ 'contract', 'product', diff --git a/product_contract/models/__init__.py b/product_contract/models/__init__.py index 388717d2..58936207 100644 --- a/product_contract/models/__init__.py +++ b/product_contract/models/__init__.py @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2017 LasLabs Inc. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - from . import product_template from . import sale_order from . import sale_order_line diff --git a/product_contract/models/sale_order.py b/product_contract/models/sale_order.py index 45f2eec7..995fb9ff 100644 --- a/product_contract/models/sale_order.py +++ b/product_contract/models/sale_order.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - +# Copyright 2019 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +# pylint: disable=missing-docstring,protected-access from odoo import api, models @@ -11,17 +12,7 @@ class SaleOrder(models.Model): @api.multi def action_confirm(self): """ If we have a contract in the order, set it up """ - for rec in self: - order_lines = self.mapped('order_line').filtered( - lambda r: r.product_id.is_contract - ) - for line in order_lines: - contract_tmpl = line.product_id.contract_template_id - contract = self.env['account.analytic.account'].create({ - 'name': '%s Contract' % rec.name, - 'partner_id': rec.partner_id.id, - 'contract_template_id': contract_tmpl.id, - }) - line.contract_id = contract.id - contract.recurring_create_invoice() + for order in self: + # create_contract() already filters on contract order lines. + order.order_line.create_contract() return super(SaleOrder, self).action_confirm() diff --git a/product_contract/models/sale_order_line.py b/product_contract/models/sale_order_line.py index c76c1059..3c087fcc 100644 --- a/product_contract/models/sale_order_line.py +++ b/product_contract/models/sale_order_line.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from odoo import fields, models +# Copyright 2019 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +# pylint: disable=missing-docstring,protected-access +from odoo import api, fields, models class SaleOrderLine(models.Model): @@ -10,5 +11,30 @@ class SaleOrderLine(models.Model): contract_id = fields.Many2one( comodel_name='account.analytic.account', - string='Contract' - ) + string='Contract') + + @api.multi + def create_contract(self): + """Create contract for sale order line. + + Should be called on confirmation of sale order. + """ + for line in self.filtered('product_id.is_contract'): + contract_vals = line._prepare_contract_vals() + contract = self.env['account.analytic.account'].create( + contract_vals) + line.contract_id = contract.id + + @api.multi + def _prepare_contract_vals(self): + """Prepare values to create contract from template.""" + self.ensure_one() + contract_tmpl = self.product_id.contract_template_id + order = self.order_id + contract = self.env['account.analytic.account'].new({ + 'name': '%s Contract' % order.name, + 'partner_id': order.partner_id.id, + 'contract_template_id': contract_tmpl.id, + 'recurring_invoices': True}) + contract._onchange_contract_template_id() + return contract._convert_to_write(contract._cache) diff --git a/product_contract/tests/test_product_template.py b/product_contract/tests/test_product_template.py index 2938cc7f..8d2398fa 100644 --- a/product_contract/tests/test_product_template.py +++ b/product_contract/tests/test_product_template.py @@ -15,7 +15,7 @@ class TestProductTemplate(TransactionCase): self.contract = self.env['account.analytic.contract'].create({ 'name': 'Test', 'recurring_rule_type': 'yearly', - 'recurring_interval': 12345, + 'recurring_interval': 1, }) def test_change_is_contract(self): diff --git a/product_contract/tests/test_sale_order.py b/product_contract/tests/test_sale_order.py index 61f33858..2e37f89d 100644 --- a/product_contract/tests/test_sale_order.py +++ b/product_contract/tests/test_sale_order.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # Copyright 2017 LasLabs Inc. -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from mock import MagicMock +# Copyright 2019 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +# pylint: disable=missing-docstring,protected-access,invalid-name from odoo.tests.common import TransactionCase @@ -15,26 +15,16 @@ class TestSaleOrder(TransactionCase): self.contract = self.env['account.analytic.contract'].create({ 'name': 'Test', 'recurring_rule_type': 'yearly', - 'recurring_interval': 12345, - }) + 'recurring_interval': 1}) self.product.product_tmpl_id.is_contract = True self.product.product_tmpl_id.contract_template_id = self.contract.id - def tearDown(self): - self.env['account.analytic.account']._revert_method( - 'create', - ) - super(TestSaleOrder, self).tearDown() - - def test_action_done(self): - """ It should create a contract when the sale for a contract is set - to done for the first time """ - self.env['account.analytic.account']._patch_method( - 'create', MagicMock() - ) + def test_action_confirm(self): + """Contract should be created when sale is confirmed.""" self.sale.action_confirm() - self.env['account.analytic.account'].create.assert_called_once_with({ - 'name': '%s Contract' % self.sale.name, - 'partner_id': self.sale.partner_id.id, - 'contract_template_id': self.contract.id, - }) + contract_model = self.env['account.analytic.account'] + product_contract = contract_model.search([ + ('recurring_invoices', '=', True), + ('partner_id', '=', self.sale.partner_id.id), + ('contract_template_id', '=', self.contract.id)], limit=1) + self.assertTrue(product_contract)