From 9b503acd0fb7f34dc28f68899e834e73e98cd062 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 Nov 2019 09:24:10 +0100 Subject: [PATCH 01/12] sale_product_set: test coverage 100% --- sale_product_set/__init__.py | 4 +-- sale_product_set/models/product_set.py | 0 sale_product_set/tests/test_product_set.py | 40 +++++++++++++++------- sale_product_set/wizard/product_set_add.py | 33 ++++++++++-------- 4 files changed, 48 insertions(+), 29 deletions(-) mode change 100755 => 100644 sale_product_set/models/product_set.py diff --git a/sale_product_set/__init__.py b/sale_product_set/__init__.py index 9b4296142f4..de8d18cd28a 100644 --- a/sale_product_set/__init__.py +++ b/sale_product_set/__init__.py @@ -1,2 +1,2 @@ -from . import models -from . import wizard +from . import models # pragma: no cover +from . import wizard # pragma: no cover diff --git a/sale_product_set/models/product_set.py b/sale_product_set/models/product_set.py old mode 100755 new mode 100644 diff --git a/sale_product_set/tests/test_product_set.py b/sale_product_set/tests/test_product_set.py index 809a7d735ba..7b74f559141 100644 --- a/sale_product_set/tests/test_product_set.py +++ b/sale_product_set/tests/test_product_set.py @@ -15,10 +15,6 @@ def setUp(self): def test_add_set(self): so = self.env.ref('sale.sale_order_6') count_lines = len(so.order_line) - untaxed_amount = so.amount_untaxed - tax_amount = so.amount_tax - total_amount = so.amount_total - product_set = self.env.ref( 'sale_product_set.product_set_i5_computer') # Simulation the opening of the wizard and adding a set on the @@ -29,18 +25,19 @@ def test_add_set(self): so_set.add_set() # checking our sale order self.assertEqual(len(so.order_line), count_lines + 3) - # untaxed_amount + ((147*1*0.75)+(2100*1)+(85*2)) * 2 - # 0.75 due to a 25% discount on Custom Computer (kit) product - self.assertEqual(so.amount_untaxed, untaxed_amount + 4760.5) - self.assertEqual(so.amount_tax, tax_amount + 0) # without tax - self.assertEqual(so.amount_total, total_amount + 4760.5) + # check all lines are included + for line in product_set.set_line_ids: + order_line = so.order_line.filtered( + lambda x: x.product_id == line.product_id + ) + order_line.ensure_one() + self.assertEqual( + order_line.product_uom_qty, line.quantity * so_set.quantity + ) + sequence = {} for line in so.order_line: sequence[line.product_id.id] = line.sequence - for set_line in product_set.set_line_ids: - if line.product_id.id == set_line.product_id.id: - self.assertEqual(line.product_id.name, - set_line.product_id.name) # make sure sale order line sequence keep sequence set on set seq_line1 = sequence.pop( self.env.ref( @@ -67,3 +64,20 @@ def test_add_set_on_empty_so(self): 'quantity': 2}) so_set.add_set() self.assertEqual(len(so.order_line), 3) + + def test_name(self): + product_set = self.env.ref( + 'sale_product_set.product_set_i5_computer') + # no ref + product_set.name = 'Foo' + product_set.ref = '' + self.assertEqual( + product_set.name_get(), + [(product_set.id, 'Foo')] + ) + # with ref + product_set.ref = '123' + self.assertEqual( + product_set.name_get(), + [(product_set.id, '[123] Foo')] + ) diff --git a/sale_product_set/wizard/product_set_add.py b/sale_product_set/wizard/product_set_add.py index 26ada3e5bef..0e16b1f18c2 100644 --- a/sale_product_set/wizard/product_set_add.py +++ b/sale_product_set/wizard/product_set_add.py @@ -10,6 +10,10 @@ class ProductSetAdd(models.TransientModel): _rec_name = 'product_set_id' _description = "Wizard model to add product set into a quotation" + order_id = fields.Many2one( + 'sale.order', 'Sale Order', required=True, + default=lambda self: self.env.context.get('active_id') + ) product_set_id = fields.Many2one( 'product.set', 'Product set', required=True) quantity = fields.Float( @@ -19,28 +23,29 @@ class ProductSetAdd(models.TransientModel): @api.multi def add_set(self): """ Add product set, multiplied by quantity in sale order line """ - so_id = self._context['active_id'] - if not so_id: - return - so = self.env['sale.order'].browse(so_id) max_sequence = 0 - if so.order_line: - max_sequence = max([line.sequence for line in so.order_line]) - sale_order_line_env = self.env['sale.order.line'] - sale_order_line = self.env['sale.order.line'] - for set_line in self.product_set_id.set_line_ids: - sale_order_line |= sale_order_line_env.create( + if self.order_id.order_line: + max_sequence = max([ + line.sequence for line in self.order_id.order_line + ]) + order_lines = self.env['sale.order.line'].browse() + for set_line in self._get_lines(): + order_lines |= self.env['sale.order.line'].create( self.prepare_sale_order_line_data( - so_id, set_line, + set_line, max_sequence=max_sequence)) - return sale_order_line + return order_lines + + def _get_lines(self): + # hook here to take control on used lines + return self.product_set_id.set_line_ids @api.multi - def prepare_sale_order_line_data(self, sale_order_id, set_line, + def prepare_sale_order_line_data(self, set_line, max_sequence=0): self.ensure_one() sale_line = self.env['sale.order.line'].new({ - 'order_id': sale_order_id, + 'order_id': self.order_id.id, 'product_id': set_line.product_id.id, 'product_uom_qty': set_line.quantity * self.quantity, 'product_uom': set_line.product_id.uom_id.id, From 91f17902ff4f5bd2240be251e7235f5a313779b9 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 14 Nov 2019 09:50:03 +0100 Subject: [PATCH 02/12] sale_product_set: add optional partner Add `partner_id` to product.set allowing to define specific sets per customer --- sale_product_set/models/product_set.py | 30 ++++++++++++++-------- sale_product_set/tests/test_product_set.py | 22 ++++++++++++++++ sale_product_set/views/product_set.xml | 19 ++++++++++---- sale_product_set/wizard/product_set_add.py | 15 ++++++++++- 4 files changed, 69 insertions(+), 17 deletions(-) diff --git a/sale_product_set/models/product_set.py b/sale_product_set/models/product_set.py index b35d9fa9fa1..a5486efb92b 100644 --- a/sale_product_set/models/product_set.py +++ b/sale_product_set/models/product_set.py @@ -24,17 +24,25 @@ class ProductSet(models.Model): default=lambda self: self.env.user.company_id, ondelete='cascade', ) + partner_id = fields.Many2one( + comodel_name="res.partner", + required=False, + ondelete="cascade", + index=True, + help="You can attache the set to a specific partner " + "or no one. If you don't specify one, " + "it's going to be available for all of them." + ) @api.multi def name_get(self): - return [ - ( - product_set.id, - '%s%s' - % ( - product_set.ref and '[%s] ' % product_set.ref or '', - product_set.name, - ), - ) - for product_set in self - ] + return [(rec.id, rec._name_get()) for rec in self] + + def _name_get(self): + parts = [] + if self.ref: + parts.append('[%s]' % self.ref) + parts.append(self.name) + if self.partner_id: + parts.append('@ %s' % self.partner_id.name) + return ' '.join(parts) diff --git a/sale_product_set/tests/test_product_set.py b/sale_product_set/tests/test_product_set.py index 7b74f559141..840c81cff46 100644 --- a/sale_product_set/tests/test_product_set.py +++ b/sale_product_set/tests/test_product_set.py @@ -2,6 +2,7 @@ # Copyright 2016-2018 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo.tests import common +from odoo import exceptions class TestProductSet(common.TransactionCase): @@ -65,6 +66,20 @@ def test_add_set_on_empty_so(self): so_set.add_set() self.assertEqual(len(so.order_line), 3) + def test_add_set_non_matching_partner(self): + so = self.sale_order.create({ + 'partner_id': self.ref('base.res_partner_1')}) + product_set = self.env.ref( + 'sale_product_set.product_set_i5_computer') + product_set.partner_id = self.ref('base.res_partner_2') + so_set = self.product_set_add.with_context( + active_id=so.id).create({'product_set_id': product_set.id, + 'quantity': 2}) + with self.assertRaises(exceptions.ValidationError): + so_set._onchange_product_set_id() + with self.assertRaises(exceptions.ValidationError): + so_set.add_set() + def test_name(self): product_set = self.env.ref( 'sale_product_set.product_set_i5_computer') @@ -81,3 +96,10 @@ def test_name(self): product_set.name_get(), [(product_set.id, '[123] Foo')] ) + # with partner + partner = self.env.ref('base.res_partner_1') + product_set.partner_id = partner + self.assertEqual( + product_set.name_get(), + [(product_set.id, '[123] Foo @ %s' % partner.name)] + ) diff --git a/sale_product_set/views/product_set.xml b/sale_product_set/views/product_set.xml index df570dba44c..8a4091839b3 100644 --- a/sale_product_set/views/product_set.xml +++ b/sale_product_set/views/product_set.xml @@ -9,6 +9,7 @@ + @@ -29,11 +30,17 @@ options="{"terminology": "archive"}"/> - - - - - + + + + + + + + + +