From 63b1e519a78d948f36b56e90aa4514b90a792415 Mon Sep 17 00:00:00 2001 From: Kevin Khao Date: Thu, 30 Jan 2020 17:22:13 +0100 Subject: [PATCH 1/7] [ADD] 12.0: stock_putaway_product_form --- stock_putaway_product_template/README.rst | 72 +++ stock_putaway_product_template/__init__.py | 4 + .../__manifest__.py | 14 + .../demo/putaway_strategies.xml | 36 ++ .../models/__init__.py | 3 + .../models/product_product.py | 13 + .../models/product_template.py | 62 +++ .../models/putaway_strategy.py | 15 + .../readme/CONTRIBUTORS.rst | 3 + .../readme/DESCRIPTION.rst | 1 + .../readme/USAGE.rst | 3 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 421 ++++++++++++++++++ .../tests/__init__.py | 3 + .../tests/test_product_putaway.py | 61 +++ .../views/product.xml | 65 +++ 16 files changed, 776 insertions(+) create mode 100644 stock_putaway_product_template/README.rst create mode 100644 stock_putaway_product_template/__init__.py create mode 100644 stock_putaway_product_template/__manifest__.py create mode 100644 stock_putaway_product_template/demo/putaway_strategies.xml create mode 100644 stock_putaway_product_template/models/__init__.py create mode 100644 stock_putaway_product_template/models/product_product.py create mode 100644 stock_putaway_product_template/models/product_template.py create mode 100644 stock_putaway_product_template/models/putaway_strategy.py create mode 100644 stock_putaway_product_template/readme/CONTRIBUTORS.rst create mode 100644 stock_putaway_product_template/readme/DESCRIPTION.rst create mode 100644 stock_putaway_product_template/readme/USAGE.rst create mode 100644 stock_putaway_product_template/static/description/icon.png create mode 100644 stock_putaway_product_template/static/description/index.html create mode 100644 stock_putaway_product_template/tests/__init__.py create mode 100644 stock_putaway_product_template/tests/test_product_putaway.py create mode 100644 stock_putaway_product_template/views/product.xml diff --git a/stock_putaway_product_template/README.rst b/stock_putaway_product_template/README.rst new file mode 100644 index 000000000..d7ab84bc4 --- /dev/null +++ b/stock_putaway_product_template/README.rst @@ -0,0 +1,72 @@ +======================================= +Putaway strategies on product form view +======================================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-oca%2Fstock--logistics--warehouse-lightgray.png?logo=github + :target: https://github.com/oca/stock-logistics-warehouse/tree/12.0/stock_putaway_product_form + :alt: oca/stock-logistics-warehouse + +|badge1| |badge2| |badge3| + +This module adds an easy way to modify product-specific putaway strategies from the product view for a better UX. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +* In Settings, set "Storage Locations" to True +* User should be in "Manage push and pull inventory flows" +* Open the form view of a product template or a product and use the fields located under the "Inventory" tab + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Contributors +~~~~~~~~~~~~ + +* Akretion + + * Kevin Khao + +Maintainers +~~~~~~~~~~~ + +.. |maintainer-kevinkhao| image:: https://github.com/kevinkhao.png?size=40px + :target: https://github.com/kevinkhao + :alt: kevinkhao +.. |maintainer-sebastienbeau| image:: https://github.com/sebastienbeau.png?size=40px + :target: https://github.com/sebastienbeau + :alt: sebastienbeau + +Current maintainers: + +|maintainer-kevinkhao| |maintainer-sebastienbeau| + +This module is part of the `oca/stock-logistics-warehouse `_ project on GitHub. + +You are welcome to contribute. diff --git a/stock_putaway_product_template/__init__.py b/stock_putaway_product_template/__init__.py new file mode 100644 index 000000000..8a3fd4c08 --- /dev/null +++ b/stock_putaway_product_template/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models +from . import tests diff --git a/stock_putaway_product_template/__manifest__.py b/stock_putaway_product_template/__manifest__.py new file mode 100644 index 000000000..f50b53ab7 --- /dev/null +++ b/stock_putaway_product_template/__manifest__.py @@ -0,0 +1,14 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Putaway strategies on product form view", + "summary": "Edit putaway strategies directly from the product form view", + "version": "12.0.1.0.0", + "category": "Inventory", + "website": "https://github.com/OCA/stock-logistics-warehouse", + "author": "Akretion, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["stock"], + "data": ["views/product.xml"], + "demo": ["demo/putaway_strategies.xml"], + "maintainers": ["kevinkhao", "sebastienbeau"], +} diff --git a/stock_putaway_product_template/demo/putaway_strategies.xml b/stock_putaway_product_template/demo/putaway_strategies.xml new file mode 100644 index 000000000..40ea4ce98 --- /dev/null +++ b/stock_putaway_product_template/demo/putaway_strategies.xml @@ -0,0 +1,36 @@ + + + + + + Putaway Strategy 1 + + + + + + + + + + + + + + + + Putaway Strategy 2 + + + + + + + + + + + + + + diff --git a/stock_putaway_product_template/models/__init__.py b/stock_putaway_product_template/models/__init__.py new file mode 100644 index 000000000..46b77487a --- /dev/null +++ b/stock_putaway_product_template/models/__init__.py @@ -0,0 +1,3 @@ +from . import product_product +from . import product_template +from . import putaway_strategy diff --git a/stock_putaway_product_template/models/product_product.py b/stock_putaway_product_template/models/product_product.py new file mode 100644 index 000000000..d6bd5d145 --- /dev/null +++ b/stock_putaway_product_template/models/product_product.py @@ -0,0 +1,13 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ProductProduct(models.Model): + _inherit = "product.product" + + product_product_putaway_ids = fields.One2many( + comodel_name="stock.fixed.putaway.strat", + inverse_name="product_id", + string="Product putaway strategies by product variant", + ) diff --git a/stock_putaway_product_template/models/product_template.py b/stock_putaway_product_template/models/product_template.py new file mode 100644 index 000000000..5098eca07 --- /dev/null +++ b/stock_putaway_product_template/models/product_template.py @@ -0,0 +1,62 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + product_tmpl_putaway_ids = fields.One2many( + comodel_name="stock.fixed.putaway.strat", + inverse_name="product_tmpl_id", + string="Product putaway strategies by product", + ) + + product_putaway_categ_ids = fields.Many2many( + comodel_name="stock.fixed.putaway.strat", + string="Product putaway strategies by category", + compute="_compute_putaway_categ_ids", + ) + + def _find_closest_categ_match(self, categ, putaway_lines): + """Returns the putaway line with the nearest product category""" + lines_match_categ = putaway_lines.filtered( + lambda r: r.category_id == categ + ) + if lines_match_categ: + return lines_match_categ[0] + elif categ.parent_id: + return self._find_closest_categ_match( + categ.parent_id, putaway_lines + ) + else: + return self.env["stock.fixed.putaway.strat"] + + def _get_categ_and_parents(self, categ): + parent_categ_iterator = categ + res = self.env["product.category"] + while parent_categ_iterator: + res += parent_categ_iterator + parent_categ_iterator = parent_categ_iterator.parent_id + return res + + @api.depends("categ_id") + def _compute_putaway_categ_ids(self): + """Pay attention to keep only 1 (most specific, + i.e closest to our product category's parents) + putaway.strat per product.putaway""" + for rec in self: + res = self.env["stock.fixed.putaway.strat"] + categ = rec.categ_id + categs = self._get_categ_and_parents(categ) + # get matching lines from our category or its parents + product_putaway_categ_lines = self.env[ + "stock.fixed.putaway.strat" + ].search([("category_id", "in", categs.ids)]) + # from these, get the matching putaway.strats and find + # the lowest-level category match + product_putaways = product_putaway_categ_lines.mapped("putaway_id") + for el in product_putaways: + lines = el.fixed_location_ids + res += self._find_closest_categ_match(categ, lines) + rec.product_putaway_categ_ids = res diff --git a/stock_putaway_product_template/models/putaway_strategy.py b/stock_putaway_product_template/models/putaway_strategy.py new file mode 100644 index 000000000..64eeb8f54 --- /dev/null +++ b/stock_putaway_product_template/models/putaway_strategy.py @@ -0,0 +1,15 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class FixedPutAwayStrategy(models.Model): + _inherit = "stock.fixed.putaway.strat" + + product_tmpl_id = fields.Many2one( + comodel_name="product.template", + ondelete="cascade", + readonly=True, + related="product_id.product_tmpl_id", + store=True + ) diff --git a/stock_putaway_product_template/readme/CONTRIBUTORS.rst b/stock_putaway_product_template/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..3a6013026 --- /dev/null +++ b/stock_putaway_product_template/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* Akretion + + * Kevin Khao diff --git a/stock_putaway_product_template/readme/DESCRIPTION.rst b/stock_putaway_product_template/readme/DESCRIPTION.rst new file mode 100644 index 000000000..d4507868e --- /dev/null +++ b/stock_putaway_product_template/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module adds an easy way to modify product-specific putaway strategies from the product view for a better UX. diff --git a/stock_putaway_product_template/readme/USAGE.rst b/stock_putaway_product_template/readme/USAGE.rst new file mode 100644 index 000000000..7657200db --- /dev/null +++ b/stock_putaway_product_template/readme/USAGE.rst @@ -0,0 +1,3 @@ +* In Settings, set "Storage Locations" to True +* User should be in "Manage push and pull inventory flows" +* Open the form view of a product template or a product and use the fields located under the "Inventory" tab diff --git a/stock_putaway_product_template/static/description/icon.png b/stock_putaway_product_template/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/stock_putaway_product_template/static/description/index.html b/stock_putaway_product_template/static/description/index.html new file mode 100644 index 000000000..7c0c0f01f --- /dev/null +++ b/stock_putaway_product_template/static/description/index.html @@ -0,0 +1,421 @@ + + + + + + +Putaway strategies on product form view + + + +
+

Putaway strategies on product form view

+ + +

Beta License: AGPL-3 oca/stock-logistics-warehouse

+

This module adds an easy way to modify product-specific putaway strategies from the product view for a better UX.

+

Table of contents

+ +
+

Usage

+
    +
  • In Settings, set “Storage Locations” to True
  • +
  • User should be in “Manage push and pull inventory flows”
  • +
  • Open the form view of a product template or a product and use the fields located under the “Inventory” tab
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Contributors

+ +
+
+

Maintainers

+

Current maintainers:

+

kevinkhao sebastienbeau

+

This module is part of the oca/stock-logistics-warehouse project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/stock_putaway_product_template/tests/__init__.py b/stock_putaway_product_template/tests/__init__.py new file mode 100644 index 000000000..a5b56cbc2 --- /dev/null +++ b/stock_putaway_product_template/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_product_putaway diff --git a/stock_putaway_product_template/tests/test_product_putaway.py b/stock_putaway_product_template/tests/test_product_putaway.py new file mode 100644 index 000000000..ea309f022 --- /dev/null +++ b/stock_putaway_product_template/tests/test_product_putaway.py @@ -0,0 +1,61 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestProductPutaway(TransactionCase): + def setUp(self): + super().setUp() + self.putawayObj = self.env["product.putaway"] + self.putawayLineObj = self.env["stock.fixed.putaway.strat"] + ref = self.env.ref + self.product_tmpl_chair = ref( + "product.product_product_11_product_template" + ) + self.product_product_chair = ref("product.product_product_11") + self.category_services = ref("product.product_category_3") + self.putaway_line_1 = ref( + "stock_putaway_product_form.putaway_strat_1_line_1" + ) + self.putaway_line_2 = ref( + "stock_putaway_product_form.putaway_strat_1_line_2" + ) + self.putaway_line_3 = ref( + "stock_putaway_product_form.putaway_strat_2_line_1" + ) + self.putaway_line_4 = ref( + "stock_putaway_product_form.putaway_strat_2_line_2" + ) + + def test_tmpl_has_putaways_from_products(self): + self.assertIn( + self.putaway_line_1, + self.product_tmpl_chair.product_tmpl_putaway_ids, + ) + self.putaway_line_1.product_id = self.env["product.product"] + self.assertNotIn( + self.putaway_line_1, + self.product_tmpl_chair.product_tmpl_putaway_ids, + ) + + def test_tmpl_has_putaways_from_category_simple(self): + self.assertIn( + self.putaway_line_2, + self.product_tmpl_chair.product_putaway_categ_ids, + ) + self.product_tmpl_chair.categ_id = self.category_services + self.assertNotIn( + self.putaway_line_2, + self.product_tmpl_chair.product_putaway_categ_ids, + ) + + def test_tmpl_has_putaways_from_category_parent(self): + # chair is under category: all/saleable/office + self.assertIn( + self.putaway_line_3, + self.product_tmpl_chair.product_putaway_categ_ids, + ) + self.assertNotIn( + self.putaway_line_4, + self.product_tmpl_chair.product_putaway_categ_ids, + ) diff --git a/stock_putaway_product_template/views/product.xml b/stock_putaway_product_template/views/product.xml new file mode 100644 index 000000000..27a3e7781 --- /dev/null +++ b/stock_putaway_product_template/views/product.xml @@ -0,0 +1,65 @@ + + + + + product.template.product.form + product.template + + + +
+ + + + +

+ The rules defined per product will be applied before the rules defined per product category. +

+
+ + + + + + + +
+ + + + + + + + + +
+
+
+
+ + + product.product.form.putaway + product.product + + + + + + + + + + + + + + + +
From 3550437ec3e8ec5e4e2e2352975ab4ed20698f05 Mon Sep 17 00:00:00 2001 From: Sergio Teruel Date: Sun, 12 Apr 2020 12:21:09 +0200 Subject: [PATCH 2/7] [IMP] stock_putaway_product_form: Allow to define rules by product template --- stock_putaway_product_template/__init__.py | 1 + .../__manifest__.py | 6 ++ stock_putaway_product_template/hooks.py | 19 ++++++ .../models/putaway_strategy.py | 41 ++++++++++-- .../readme/CONTRIBUTORS.rst | 6 +- .../tests/test_product_putaway.py | 65 +++++++++++++++++++ .../views/product.xml | 12 ++-- 7 files changed, 138 insertions(+), 12 deletions(-) create mode 100644 stock_putaway_product_template/hooks.py diff --git a/stock_putaway_product_template/__init__.py b/stock_putaway_product_template/__init__.py index 8a3fd4c08..1553865ca 100644 --- a/stock_putaway_product_template/__init__.py +++ b/stock_putaway_product_template/__init__.py @@ -2,3 +2,4 @@ from . import models from . import tests +from .hooks import post_init_hook diff --git a/stock_putaway_product_template/__manifest__.py b/stock_putaway_product_template/__manifest__.py index f50b53ab7..9cacc4285 100644 --- a/stock_putaway_product_template/__manifest__.py +++ b/stock_putaway_product_template/__manifest__.py @@ -8,7 +8,13 @@ "author": "Akretion, Odoo Community Association (OCA)", "license": "AGPL-3", "depends": ["stock"], + "external_dependencies": { + "python": [ + "openupgradelib", + ], + }, "data": ["views/product.xml"], "demo": ["demo/putaway_strategies.xml"], "maintainers": ["kevinkhao", "sebastienbeau"], + "post_init_hook": "post_init_hook", } diff --git a/stock_putaway_product_template/hooks.py b/stock_putaway_product_template/hooks.py new file mode 100644 index 000000000..3da582463 --- /dev/null +++ b/stock_putaway_product_template/hooks.py @@ -0,0 +1,19 @@ +# Copyright 2020 Tecnativa - Sergio Teruel +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import logging +from openupgradelib import openupgrade + +_logger = logging.getLogger(__name__) + + +def post_init_hook(cr, registry): + openupgrade.logged_query( + cr, """ + UPDATE stock_fixed_putaway_strat sfps + SET product_tmpl_id=pp.product_tmpl_id + FROM product_product pp + WHERE pp.id=sfps.product_id AND + sfps.product_tmpl_id <> pp.product_tmpl_id + """ + ) diff --git a/stock_putaway_product_template/models/putaway_strategy.py b/stock_putaway_product_template/models/putaway_strategy.py index 64eeb8f54..99da525cc 100644 --- a/stock_putaway_product_template/models/putaway_strategy.py +++ b/stock_putaway_product_template/models/putaway_strategy.py @@ -1,6 +1,18 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# Copyright 2020 Sergio Teruel - Tecnativa -from odoo import fields, models +from odoo import api, fields, models + + +class PutAwayStrategy(models.Model): + _inherit = 'product.putaway' + + # Remove product domain to allow to select product templates + product_location_ids = fields.One2many(domain=[]) + + def _get_putaway_rule(self, product): + return super(PutAwayStrategy, self.with_context( + filter_putaway_rule=True))._get_putaway_rule(product) class FixedPutAwayStrategy(models.Model): @@ -8,8 +20,29 @@ class FixedPutAwayStrategy(models.Model): product_tmpl_id = fields.Many2one( comodel_name="product.template", + compute="_compute_product_tmpl_id", + store=True, + inverse=lambda self: self, ondelete="cascade", - readonly=True, - related="product_id.product_tmpl_id", - store=True ) + + @api.depends('product_id') + def _compute_product_tmpl_id(self): + for rec in self: + if rec.product_id: + rec.product_tmpl_id = rec.product_id.product_tmpl_id + else: + params = self.env.context.get('params', {}) + if params.get('model', '') == 'product.template': + rec.product_tmpl_id = params.get('id', False) + + def filtered(self, func): + res = super(FixedPutAwayStrategy, self).filtered(func) + if res or not self.env.context.get('filter_putaway_rule'): + return res + product = func.__closure__[0].cell_contents + if product._name != 'product.product': + return res + return self.with_context(filter_putaway_rule=False).filtered( + lambda x: (x.product_tmpl_id == product.product_tmpl_id and + not x.product_id)) diff --git a/stock_putaway_product_template/readme/CONTRIBUTORS.rst b/stock_putaway_product_template/readme/CONTRIBUTORS.rst index 3a6013026..ae30e064e 100644 --- a/stock_putaway_product_template/readme/CONTRIBUTORS.rst +++ b/stock_putaway_product_template/readme/CONTRIBUTORS.rst @@ -1,3 +1,7 @@ -* Akretion +* `Akretion `_: * Kevin Khao + +* `Tecnativa `_: + + * Sergio Teruel diff --git a/stock_putaway_product_template/tests/test_product_putaway.py b/stock_putaway_product_template/tests/test_product_putaway.py index ea309f022..3790488a2 100644 --- a/stock_putaway_product_template/tests/test_product_putaway.py +++ b/stock_putaway_product_template/tests/test_product_putaway.py @@ -8,6 +8,10 @@ class TestProductPutaway(TransactionCase): super().setUp() self.putawayObj = self.env["product.putaway"] self.putawayLineObj = self.env["stock.fixed.putaway.strat"] + ProductTemplate = self.env["product.template"] + ProductAttribute = self.env["product.attribute"] + ProductAttributeValue = self.env["product.attribute.value"] + TemplateAttributeLine = self.env["product.template.attribute.line"] ref = self.env.ref self.product_tmpl_chair = ref( "product.product_product_11_product_template" @@ -27,6 +31,32 @@ class TestProductPutaway(TransactionCase): "stock_putaway_product_form.putaway_strat_2_line_2" ) + # Add a product with variants + self.template = ProductTemplate.create({ + 'name': 'Product test', + 'type': 'consu', + }) + self.size_attribute = ProductAttribute.create({ + 'name': 'Test size', + 'sequence': 1, + }) + self.size_m = ProductAttributeValue.create({ + 'name': 'Size M', + 'attribute_id': self.size_attribute.id, + 'sequence': 1, + }) + self.size_l = ProductAttributeValue.create({ + 'name': 'Size L', + 'attribute_id': self.size_attribute.id, + 'sequence': 2, + }) + self.template_attribute_lines = TemplateAttributeLine.create({ + 'product_tmpl_id': self.template.id, + 'attribute_id': self.size_attribute.id, + 'value_ids': [(6, 0, [self.size_m.id, self.size_l.id])], + }) + self.template.create_variant_ids() + def test_tmpl_has_putaways_from_products(self): self.assertIn( self.putaway_line_1, @@ -59,3 +89,38 @@ class TestProductPutaway(TransactionCase): self.putaway_line_4, self.product_tmpl_chair.product_putaway_categ_ids, ) + + def test_apply_putaway(self): + # Create one strategy line for product template and other with a + # specific variant + location = self.env.ref('stock.stock_location_shop0') + location1 = location.copy({ + 'name': 'Location test 1', + 'location_id': location.id + }) + location2 = location.copy({ + 'name': 'Location test 2', + 'location_id': location.id + }) + variant1 = self.template.product_variant_ids[0] + variant2 = self.template.product_variant_ids[1] + putaway = self.putawayObj.create({'name': 'Putaway for test'}) + val_list = [ + { + 'putaway_id': putaway.id, + 'product_tmpl_id': self.template.id, + 'fixed_location_id': location1.id, + }, + { + 'putaway_id': putaway.id, + 'product_id': variant2.id, + 'fixed_location_id': location2.id, + }, + ] + self.putawayLineObj.create(val_list) + location_applied = putaway._get_putaway_rule( + variant1).fixed_location_id + self.assertEqual(location_applied, location1) + location_applied = putaway._get_putaway_rule( + variant2).fixed_location_id + self.assertEqual(location_applied, location2) diff --git a/stock_putaway_product_template/views/product.xml b/stock_putaway_product_template/views/product.xml index 27a3e7781..61f1bba70 100644 --- a/stock_putaway_product_template/views/product.xml +++ b/stock_putaway_product_template/views/product.xml @@ -9,20 +9,18 @@
-

The rules defined per product will be applied before the rules defined per product category. +

Keep empty product field to apply strategy to all variants.

- + - - + + @@ -53,7 +51,7 @@ attrs="{'invisible': [('is_product_variant', '=', False)]}"> - + From 534c6239202b34f030d7eddfe87e070d190e2290 Mon Sep 17 00:00:00 2001 From: Kevin Khao Date: Sun, 9 Aug 2020 12:41:11 +0200 Subject: [PATCH 3/7] [IMP] Add group permissions to views --- stock_putaway_product_template/views/product.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stock_putaway_product_template/views/product.xml b/stock_putaway_product_template/views/product.xml index 61f1bba70..6b75712ed 100644 --- a/stock_putaway_product_template/views/product.xml +++ b/stock_putaway_product_template/views/product.xml @@ -5,6 +5,7 @@ product.template.product.form product.template +
@@ -45,6 +46,7 @@ product.product.form.putaway product.product + - From ea1f1f8e2816a4bea894e9f1f2c09ca02a6955f7 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Fri, 11 Sep 2020 13:59:22 +0000 Subject: [PATCH 4/7] [UPD] Update stock_putaway_product_form.pot --- .../i18n/stock_putaway_product_form.pot | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 stock_putaway_product_template/i18n/stock_putaway_product_form.pot diff --git a/stock_putaway_product_template/i18n/stock_putaway_product_form.pot b/stock_putaway_product_template/i18n/stock_putaway_product_form.pot new file mode 100644 index 000000000..652ddc6f9 --- /dev/null +++ b/stock_putaway_product_template/i18n/stock_putaway_product_form.pot @@ -0,0 +1,88 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_putaway_product_form +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_putaway_product_form +#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_putaway__product_location_ids +msgid "Fixed Locations Per Product" +msgstr "" + +#. module: stock_putaway_product_form +#: model:ir.model,name:stock_putaway_product_form.model_stock_fixed_putaway_strat +msgid "Fixed Putaway Strategy on Location" +msgstr "" + +#. module: stock_putaway_product_form +#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway +msgid "Keep empty product field to apply strategy to all variants." +msgstr "" + +#. module: stock_putaway_product_form +#: model:ir.model,name:stock_putaway_product_form.model_product_product +msgid "Product" +msgstr "" + +#. module: stock_putaway_product_form +#: model:ir.model,name:stock_putaway_product_form.model_product_template +msgid "Product Template" +msgstr "" + +#. module: stock_putaway_product_form +#: model:ir.model.fields,field_description:stock_putaway_product_form.field_stock_fixed_putaway_strat__product_tmpl_id +msgid "Product Tmpl" +msgstr "" + +#. module: stock_putaway_product_form +#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_product__product_putaway_categ_ids +#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_template__product_putaway_categ_ids +msgid "Product putaway strategies by category" +msgstr "" + +#. module: stock_putaway_product_form +#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_product__product_tmpl_putaway_ids +#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_template__product_tmpl_putaway_ids +msgid "Product putaway strategies by product" +msgstr "" + +#. module: stock_putaway_product_form +#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_product__product_product_putaway_ids +msgid "Product putaway strategies by product variant" +msgstr "" + +#. module: stock_putaway_product_form +#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway +msgid "Put Away Strategies by category" +msgstr "" + +#. module: stock_putaway_product_form +#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_product_form_putaway +#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway +msgid "Put Away Strategies by products" +msgstr "" + +#. module: stock_putaway_product_form +#: model:ir.model,name:stock_putaway_product_form.model_product_putaway +msgid "Put Away Strategy" +msgstr "" + +#. module: stock_putaway_product_form +#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway +msgid "Putaway strategies" +msgstr "" + +#. module: stock_putaway_product_form +#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway +msgid "The rules defined per product will be applied before the rules defined per product category." +msgstr "" + From 9cce1668cdb7880df000b56e69f9467122eac51f Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Fri, 11 Sep 2020 14:41:27 +0000 Subject: [PATCH 5/7] [UPD] README.rst --- stock_putaway_product_template/README.rst | 45 ++++++++++++++----- .../static/description/index.html | 40 ++++++++++++----- 2 files changed, 63 insertions(+), 22 deletions(-) diff --git a/stock_putaway_product_template/README.rst b/stock_putaway_product_template/README.rst index d7ab84bc4..30eec09d6 100644 --- a/stock_putaway_product_template/README.rst +++ b/stock_putaway_product_template/README.rst @@ -13,11 +13,17 @@ Putaway strategies on product form view .. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 -.. |badge3| image:: https://img.shields.io/badge/github-oca%2Fstock--logistics--warehouse-lightgray.png?logo=github - :target: https://github.com/oca/stock-logistics-warehouse/tree/12.0/stock_putaway_product_form - :alt: oca/stock-logistics-warehouse +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_putaway_product_form + :alt: OCA/stock-logistics-warehouse +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-12-0/stock-logistics-warehouse-12-0-stock_putaway_product_form + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/153/12.0 + :alt: Try me on Runbot -|badge1| |badge2| |badge3| +|badge1| |badge2| |badge3| |badge4| |badge5| This module adds an easy way to modify product-specific putaway strategies from the product view for a better UX. @@ -36,26 +42,45 @@ Usage Bug Tracker =========== -Bugs are tracked on `GitHub Issues `_. +Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. Credits ======= +Authors +~~~~~~~ + +* Akretion + Contributors ~~~~~~~~~~~~ -* Akretion +* `Akretion `_: * Kevin Khao +* `Tecnativa `_: + + * Sergio Teruel + Maintainers ~~~~~~~~~~~ +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + .. |maintainer-kevinkhao| image:: https://github.com/kevinkhao.png?size=40px :target: https://github.com/kevinkhao :alt: kevinkhao @@ -63,10 +88,10 @@ Maintainers :target: https://github.com/sebastienbeau :alt: sebastienbeau -Current maintainers: +Current `maintainers `__: |maintainer-kevinkhao| |maintainer-sebastienbeau| -This module is part of the `oca/stock-logistics-warehouse `_ project on GitHub. +This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. -You are welcome to contribute. +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_putaway_product_template/static/description/index.html b/stock_putaway_product_template/static/description/index.html index 7c0c0f01f..8e00f4ce5 100644 --- a/stock_putaway_product_template/static/description/index.html +++ b/stock_putaway_product_template/static/description/index.html @@ -367,7 +367,7 @@ ul.auto-toc { !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 oca/stock-logistics-warehouse

+

Beta License: AGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runbot

This module adds an easy way to modify product-specific putaway strategies from the product view for a better UX.

Table of contents

@@ -375,8 +375,9 @@ ul.auto-toc {
  • Usage
  • Bug Tracker
  • Credits
  • @@ -391,29 +392,44 @@ ul.auto-toc {

    Bug Tracker

    -

    Bugs are tracked on GitHub Issues. +

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -feedback.

    +feedback.

    Do not contact contributors directly about support or help with technical issues.

    Credits

    -
    -

    Contributors

    +
    +

    Authors

    +
    +

    Contributors

    +
    -

    Maintainers

    -

    Current maintainers:

    +

    Maintainers

    +

    This module is maintained by the OCA.

    +Odoo Community Association +

    OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

    +

    Current maintainers:

    kevinkhao sebastienbeau

    -

    This module is part of the oca/stock-logistics-warehouse project on GitHub.

    -

    You are welcome to contribute.

    +

    This module is part of the OCA/stock-logistics-warehouse project on GitHub.

    +

    You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

    From cd4680d27eef70b57f1b4a7416330096c45c5ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Tue, 27 Oct 2020 17:18:12 +0100 Subject: [PATCH 6/7] [IMP] stock_putaway_product_form: black, isort, prettier --- .../__manifest__.py | 6 +- .../demo/putaway_strategies.xml | 31 ++--- stock_putaway_product_template/hooks.py | 6 +- .../models/product_template.py | 14 +-- .../models/putaway_strategy.py | 25 ++-- .../tests/test_product_putaway.py | 116 +++++++----------- .../views/product.xml | 71 +++++++---- 7 files changed, 128 insertions(+), 141 deletions(-) diff --git a/stock_putaway_product_template/__manifest__.py b/stock_putaway_product_template/__manifest__.py index 9cacc4285..9ee31bc46 100644 --- a/stock_putaway_product_template/__manifest__.py +++ b/stock_putaway_product_template/__manifest__.py @@ -8,11 +8,7 @@ "author": "Akretion, Odoo Community Association (OCA)", "license": "AGPL-3", "depends": ["stock"], - "external_dependencies": { - "python": [ - "openupgradelib", - ], - }, + "external_dependencies": {"python": ["openupgradelib"]}, "data": ["views/product.xml"], "demo": ["demo/putaway_strategies.xml"], "maintainers": ["kevinkhao", "sebastienbeau"], diff --git a/stock_putaway_product_template/demo/putaway_strategies.xml b/stock_putaway_product_template/demo/putaway_strategies.xml index 40ea4ce98..c1ffcc5f3 100644 --- a/stock_putaway_product_template/demo/putaway_strategies.xml +++ b/stock_putaway_product_template/demo/putaway_strategies.xml @@ -1,36 +1,31 @@ - + - Putaway Strategy 1 - - - + + + - - - - + + + - Putaway Strategy 2 - - - + + + - - - - + + + - diff --git a/stock_putaway_product_template/hooks.py b/stock_putaway_product_template/hooks.py index 3da582463..3287c519a 100644 --- a/stock_putaway_product_template/hooks.py +++ b/stock_putaway_product_template/hooks.py @@ -2,6 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import logging + from openupgradelib import openupgrade _logger = logging.getLogger(__name__) @@ -9,11 +10,12 @@ _logger = logging.getLogger(__name__) def post_init_hook(cr, registry): openupgrade.logged_query( - cr, """ + cr, + """ UPDATE stock_fixed_putaway_strat sfps SET product_tmpl_id=pp.product_tmpl_id FROM product_product pp WHERE pp.id=sfps.product_id AND sfps.product_tmpl_id <> pp.product_tmpl_id - """ + """, ) diff --git a/stock_putaway_product_template/models/product_template.py b/stock_putaway_product_template/models/product_template.py index 5098eca07..39d4b6893 100644 --- a/stock_putaway_product_template/models/product_template.py +++ b/stock_putaway_product_template/models/product_template.py @@ -20,15 +20,11 @@ class ProductTemplate(models.Model): def _find_closest_categ_match(self, categ, putaway_lines): """Returns the putaway line with the nearest product category""" - lines_match_categ = putaway_lines.filtered( - lambda r: r.category_id == categ - ) + lines_match_categ = putaway_lines.filtered(lambda r: r.category_id == categ) if lines_match_categ: return lines_match_categ[0] elif categ.parent_id: - return self._find_closest_categ_match( - categ.parent_id, putaway_lines - ) + return self._find_closest_categ_match(categ.parent_id, putaway_lines) else: return self.env["stock.fixed.putaway.strat"] @@ -50,9 +46,9 @@ class ProductTemplate(models.Model): categ = rec.categ_id categs = self._get_categ_and_parents(categ) # get matching lines from our category or its parents - product_putaway_categ_lines = self.env[ - "stock.fixed.putaway.strat" - ].search([("category_id", "in", categs.ids)]) + product_putaway_categ_lines = self.env["stock.fixed.putaway.strat"].search( + [("category_id", "in", categs.ids)] + ) # from these, get the matching putaway.strats and find # the lowest-level category match product_putaways = product_putaway_categ_lines.mapped("putaway_id") diff --git a/stock_putaway_product_template/models/putaway_strategy.py b/stock_putaway_product_template/models/putaway_strategy.py index 99da525cc..1a0411559 100644 --- a/stock_putaway_product_template/models/putaway_strategy.py +++ b/stock_putaway_product_template/models/putaway_strategy.py @@ -5,14 +5,15 @@ from odoo import api, fields, models class PutAwayStrategy(models.Model): - _inherit = 'product.putaway' + _inherit = "product.putaway" # Remove product domain to allow to select product templates product_location_ids = fields.One2many(domain=[]) def _get_putaway_rule(self, product): - return super(PutAwayStrategy, self.with_context( - filter_putaway_rule=True))._get_putaway_rule(product) + return super( + PutAwayStrategy, self.with_context(filter_putaway_rule=True) + )._get_putaway_rule(product) class FixedPutAwayStrategy(models.Model): @@ -26,23 +27,25 @@ class FixedPutAwayStrategy(models.Model): ondelete="cascade", ) - @api.depends('product_id') + @api.depends("product_id") def _compute_product_tmpl_id(self): for rec in self: if rec.product_id: rec.product_tmpl_id = rec.product_id.product_tmpl_id else: - params = self.env.context.get('params', {}) - if params.get('model', '') == 'product.template': - rec.product_tmpl_id = params.get('id', False) + params = self.env.context.get("params", {}) + if params.get("model", "") == "product.template": + rec.product_tmpl_id = params.get("id", False) def filtered(self, func): res = super(FixedPutAwayStrategy, self).filtered(func) - if res or not self.env.context.get('filter_putaway_rule'): + if res or not self.env.context.get("filter_putaway_rule"): return res product = func.__closure__[0].cell_contents - if product._name != 'product.product': + if product._name != "product.product": return res return self.with_context(filter_putaway_rule=False).filtered( - lambda x: (x.product_tmpl_id == product.product_tmpl_id and - not x.product_id)) + lambda x: ( + x.product_tmpl_id == product.product_tmpl_id and not x.product_id + ) + ) diff --git a/stock_putaway_product_template/tests/test_product_putaway.py b/stock_putaway_product_template/tests/test_product_putaway.py index 3790488a2..f4de9f10f 100644 --- a/stock_putaway_product_template/tests/test_product_putaway.py +++ b/stock_putaway_product_template/tests/test_product_putaway.py @@ -13,114 +13,90 @@ class TestProductPutaway(TransactionCase): ProductAttributeValue = self.env["product.attribute.value"] TemplateAttributeLine = self.env["product.template.attribute.line"] ref = self.env.ref - self.product_tmpl_chair = ref( - "product.product_product_11_product_template" - ) + self.product_tmpl_chair = ref("product.product_product_11_product_template") self.product_product_chair = ref("product.product_product_11") self.category_services = ref("product.product_category_3") - self.putaway_line_1 = ref( - "stock_putaway_product_form.putaway_strat_1_line_1" - ) - self.putaway_line_2 = ref( - "stock_putaway_product_form.putaway_strat_1_line_2" - ) - self.putaway_line_3 = ref( - "stock_putaway_product_form.putaway_strat_2_line_1" - ) - self.putaway_line_4 = ref( - "stock_putaway_product_form.putaway_strat_2_line_2" - ) + self.putaway_line_1 = ref("stock_putaway_product_form.putaway_strat_1_line_1") + self.putaway_line_2 = ref("stock_putaway_product_form.putaway_strat_1_line_2") + self.putaway_line_3 = ref("stock_putaway_product_form.putaway_strat_2_line_1") + self.putaway_line_4 = ref("stock_putaway_product_form.putaway_strat_2_line_2") # Add a product with variants - self.template = ProductTemplate.create({ - 'name': 'Product test', - 'type': 'consu', - }) - self.size_attribute = ProductAttribute.create({ - 'name': 'Test size', - 'sequence': 1, - }) - self.size_m = ProductAttributeValue.create({ - 'name': 'Size M', - 'attribute_id': self.size_attribute.id, - 'sequence': 1, - }) - self.size_l = ProductAttributeValue.create({ - 'name': 'Size L', - 'attribute_id': self.size_attribute.id, - 'sequence': 2, - }) - self.template_attribute_lines = TemplateAttributeLine.create({ - 'product_tmpl_id': self.template.id, - 'attribute_id': self.size_attribute.id, - 'value_ids': [(6, 0, [self.size_m.id, self.size_l.id])], - }) + self.template = ProductTemplate.create( + {"name": "Product test", "type": "consu"} + ) + self.size_attribute = ProductAttribute.create( + {"name": "Test size", "sequence": 1} + ) + self.size_m = ProductAttributeValue.create( + {"name": "Size M", "attribute_id": self.size_attribute.id, "sequence": 1} + ) + self.size_l = ProductAttributeValue.create( + {"name": "Size L", "attribute_id": self.size_attribute.id, "sequence": 2} + ) + self.template_attribute_lines = TemplateAttributeLine.create( + { + "product_tmpl_id": self.template.id, + "attribute_id": self.size_attribute.id, + "value_ids": [(6, 0, [self.size_m.id, self.size_l.id])], + } + ) self.template.create_variant_ids() def test_tmpl_has_putaways_from_products(self): self.assertIn( - self.putaway_line_1, - self.product_tmpl_chair.product_tmpl_putaway_ids, + self.putaway_line_1, self.product_tmpl_chair.product_tmpl_putaway_ids, ) self.putaway_line_1.product_id = self.env["product.product"] self.assertNotIn( - self.putaway_line_1, - self.product_tmpl_chair.product_tmpl_putaway_ids, + self.putaway_line_1, self.product_tmpl_chair.product_tmpl_putaway_ids, ) def test_tmpl_has_putaways_from_category_simple(self): self.assertIn( - self.putaway_line_2, - self.product_tmpl_chair.product_putaway_categ_ids, + self.putaway_line_2, self.product_tmpl_chair.product_putaway_categ_ids, ) self.product_tmpl_chair.categ_id = self.category_services self.assertNotIn( - self.putaway_line_2, - self.product_tmpl_chair.product_putaway_categ_ids, + self.putaway_line_2, self.product_tmpl_chair.product_putaway_categ_ids, ) def test_tmpl_has_putaways_from_category_parent(self): # chair is under category: all/saleable/office self.assertIn( - self.putaway_line_3, - self.product_tmpl_chair.product_putaway_categ_ids, + self.putaway_line_3, self.product_tmpl_chair.product_putaway_categ_ids, ) self.assertNotIn( - self.putaway_line_4, - self.product_tmpl_chair.product_putaway_categ_ids, + self.putaway_line_4, self.product_tmpl_chair.product_putaway_categ_ids, ) def test_apply_putaway(self): # Create one strategy line for product template and other with a # specific variant - location = self.env.ref('stock.stock_location_shop0') - location1 = location.copy({ - 'name': 'Location test 1', - 'location_id': location.id - }) - location2 = location.copy({ - 'name': 'Location test 2', - 'location_id': location.id - }) + location = self.env.ref("stock.stock_location_shop0") + location1 = location.copy( + {"name": "Location test 1", "location_id": location.id} + ) + location2 = location.copy( + {"name": "Location test 2", "location_id": location.id} + ) variant1 = self.template.product_variant_ids[0] variant2 = self.template.product_variant_ids[1] - putaway = self.putawayObj.create({'name': 'Putaway for test'}) + putaway = self.putawayObj.create({"name": "Putaway for test"}) val_list = [ { - 'putaway_id': putaway.id, - 'product_tmpl_id': self.template.id, - 'fixed_location_id': location1.id, + "putaway_id": putaway.id, + "product_tmpl_id": self.template.id, + "fixed_location_id": location1.id, }, { - 'putaway_id': putaway.id, - 'product_id': variant2.id, - 'fixed_location_id': location2.id, + "putaway_id": putaway.id, + "product_id": variant2.id, + "fixed_location_id": location2.id, }, ] self.putawayLineObj.create(val_list) - location_applied = putaway._get_putaway_rule( - variant1).fixed_location_id + location_applied = putaway._get_putaway_rule(variant1).fixed_location_id self.assertEqual(location_applied, location1) - location_applied = putaway._get_putaway_rule( - variant2).fixed_location_id + location_applied = putaway._get_putaway_rule(variant2).fixed_location_id self.assertEqual(location_applied, location2) diff --git a/stock_putaway_product_template/views/product.xml b/stock_putaway_product_template/views/product.xml index 6b75712ed..1102606d2 100644 --- a/stock_putaway_product_template/views/product.xml +++ b/stock_putaway_product_template/views/product.xml @@ -1,39 +1,52 @@ - + product.template.product.form product.template - - + + -
    - - +
    + +

    The rules defined per product will be applied before the rules defined per product category. -

    Keep empty product field to apply strategy to all variants.
    +
    Keep empty product field to apply strategy to all variants.

    - - - + + +
    - - + + - - - + + + @@ -41,20 +54,26 @@ - product.product.form.putaway product.product - - + + - - + + - - + + From 75cf49e9a0e6d40e83e2dfa86af0ebf511c0db5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Wed, 28 Oct 2020 10:07:42 +0100 Subject: [PATCH 7/7] [MIG] stock_putaway_product_template: Migration to 13.0 --- .../addons/stock_putaway_product_template | 1 + setup/stock_putaway_product_template/setup.py | 6 + stock_putaway_product_template/README.rst | 10 +- stock_putaway_product_template/__init__.py | 2 - .../__manifest__.py | 11 +- .../demo/putaway_strategies.xml | 31 ----- stock_putaway_product_template/hooks.py | 21 ---- .../i18n/stock_putaway_product_form.pot | 88 -------------- .../i18n/stock_putaway_product_template.pot | 26 +++++ .../models/__init__.py | 6 +- .../models/product.py | 19 +++ .../models/product_product.py | 13 --- .../models/product_template.py | 58 --------- .../models/stock_location.py | 13 +++ ...away_strategy.py => stock_putaway_rule.py} | 24 ++-- .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 2 +- .../readme/USAGE.rst | 5 +- .../static/description/index.html | 6 +- .../tests/__init__.py | 2 +- .../tests/test_product_putaway.py | 102 ---------------- .../tests/test_stock_putaway_rule.py | 110 ++++++++++++++++++ .../views/product.xml | 83 ------------- .../views/stock_putaway_rule_views.xml | 31 +++++ 24 files changed, 234 insertions(+), 437 deletions(-) create mode 120000 setup/stock_putaway_product_template/odoo/addons/stock_putaway_product_template create mode 100644 setup/stock_putaway_product_template/setup.py delete mode 100644 stock_putaway_product_template/demo/putaway_strategies.xml delete mode 100644 stock_putaway_product_template/hooks.py delete mode 100644 stock_putaway_product_template/i18n/stock_putaway_product_form.pot create mode 100644 stock_putaway_product_template/i18n/stock_putaway_product_template.pot create mode 100644 stock_putaway_product_template/models/product.py delete mode 100644 stock_putaway_product_template/models/product_product.py delete mode 100644 stock_putaway_product_template/models/product_template.py create mode 100644 stock_putaway_product_template/models/stock_location.py rename stock_putaway_product_template/models/{putaway_strategy.py => stock_putaway_rule.py} (64%) delete mode 100644 stock_putaway_product_template/tests/test_product_putaway.py create mode 100644 stock_putaway_product_template/tests/test_stock_putaway_rule.py delete mode 100644 stock_putaway_product_template/views/product.xml create mode 100644 stock_putaway_product_template/views/stock_putaway_rule_views.xml diff --git a/setup/stock_putaway_product_template/odoo/addons/stock_putaway_product_template b/setup/stock_putaway_product_template/odoo/addons/stock_putaway_product_template new file mode 120000 index 000000000..2b9ca4b93 --- /dev/null +++ b/setup/stock_putaway_product_template/odoo/addons/stock_putaway_product_template @@ -0,0 +1 @@ +../../../../stock_putaway_product_template \ No newline at end of file diff --git a/setup/stock_putaway_product_template/setup.py b/setup/stock_putaway_product_template/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/stock_putaway_product_template/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/stock_putaway_product_template/README.rst b/stock_putaway_product_template/README.rst index 30eec09d6..3252d0829 100644 --- a/stock_putaway_product_template/README.rst +++ b/stock_putaway_product_template/README.rst @@ -14,13 +14,13 @@ Putaway strategies on product form view :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github - :target: https://github.com/OCA/stock-logistics-warehouse/tree/12.0/stock_putaway_product_form + :target: https://github.com/OCA/stock-logistics-warehouse/tree/1.0/stock_putaway_product_template :alt: OCA/stock-logistics-warehouse .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-12-0/stock-logistics-warehouse-12-0-stock_putaway_product_form + :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-12-0/stock-logistics-warehouse-12-0-stock_putaway_product_template :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/153/12.0 + :target: https://runbot.odoo-community.org/runbot/153/1.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -45,7 +45,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -92,6 +92,6 @@ Current `maintainers `__: |maintainer-kevinkhao| |maintainer-sebastienbeau| -This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. +This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_putaway_product_template/__init__.py b/stock_putaway_product_template/__init__.py index 1553865ca..69f7babdf 100644 --- a/stock_putaway_product_template/__init__.py +++ b/stock_putaway_product_template/__init__.py @@ -1,5 +1,3 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import models -from . import tests -from .hooks import post_init_hook diff --git a/stock_putaway_product_template/__manifest__.py b/stock_putaway_product_template/__manifest__.py index 9ee31bc46..6af72f212 100644 --- a/stock_putaway_product_template/__manifest__.py +++ b/stock_putaway_product_template/__manifest__.py @@ -1,16 +1,13 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - "name": "Putaway strategies on product form view", - "summary": "Edit putaway strategies directly from the product form view", - "version": "12.0.1.0.0", + "name": "Product template in putaway strategies", + "summary": "Add product template in putaway strategies from the product view", + "version": "13.0.1.0.0", "category": "Inventory", "website": "https://github.com/OCA/stock-logistics-warehouse", "author": "Akretion, Odoo Community Association (OCA)", "license": "AGPL-3", "depends": ["stock"], - "external_dependencies": {"python": ["openupgradelib"]}, - "data": ["views/product.xml"], - "demo": ["demo/putaway_strategies.xml"], + "data": ["views/stock_putaway_rule_views.xml"], "maintainers": ["kevinkhao", "sebastienbeau"], - "post_init_hook": "post_init_hook", } diff --git a/stock_putaway_product_template/demo/putaway_strategies.xml b/stock_putaway_product_template/demo/putaway_strategies.xml deleted file mode 100644 index c1ffcc5f3..000000000 --- a/stock_putaway_product_template/demo/putaway_strategies.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - Putaway Strategy 1 - - - - - - - - - - - - - - Putaway Strategy 2 - - - - - - - - - - - - diff --git a/stock_putaway_product_template/hooks.py b/stock_putaway_product_template/hooks.py deleted file mode 100644 index 3287c519a..000000000 --- a/stock_putaway_product_template/hooks.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2020 Tecnativa - Sergio Teruel -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - -import logging - -from openupgradelib import openupgrade - -_logger = logging.getLogger(__name__) - - -def post_init_hook(cr, registry): - openupgrade.logged_query( - cr, - """ - UPDATE stock_fixed_putaway_strat sfps - SET product_tmpl_id=pp.product_tmpl_id - FROM product_product pp - WHERE pp.id=sfps.product_id AND - sfps.product_tmpl_id <> pp.product_tmpl_id - """, - ) diff --git a/stock_putaway_product_template/i18n/stock_putaway_product_form.pot b/stock_putaway_product_template/i18n/stock_putaway_product_form.pot deleted file mode 100644 index 652ddc6f9..000000000 --- a/stock_putaway_product_template/i18n/stock_putaway_product_form.pot +++ /dev/null @@ -1,88 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * stock_putaway_product_form -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 12.0\n" -"Report-Msgid-Bugs-To: \n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: stock_putaway_product_form -#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_putaway__product_location_ids -msgid "Fixed Locations Per Product" -msgstr "" - -#. module: stock_putaway_product_form -#: model:ir.model,name:stock_putaway_product_form.model_stock_fixed_putaway_strat -msgid "Fixed Putaway Strategy on Location" -msgstr "" - -#. module: stock_putaway_product_form -#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway -msgid "Keep empty product field to apply strategy to all variants." -msgstr "" - -#. module: stock_putaway_product_form -#: model:ir.model,name:stock_putaway_product_form.model_product_product -msgid "Product" -msgstr "" - -#. module: stock_putaway_product_form -#: model:ir.model,name:stock_putaway_product_form.model_product_template -msgid "Product Template" -msgstr "" - -#. module: stock_putaway_product_form -#: model:ir.model.fields,field_description:stock_putaway_product_form.field_stock_fixed_putaway_strat__product_tmpl_id -msgid "Product Tmpl" -msgstr "" - -#. module: stock_putaway_product_form -#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_product__product_putaway_categ_ids -#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_template__product_putaway_categ_ids -msgid "Product putaway strategies by category" -msgstr "" - -#. module: stock_putaway_product_form -#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_product__product_tmpl_putaway_ids -#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_template__product_tmpl_putaway_ids -msgid "Product putaway strategies by product" -msgstr "" - -#. module: stock_putaway_product_form -#: model:ir.model.fields,field_description:stock_putaway_product_form.field_product_product__product_product_putaway_ids -msgid "Product putaway strategies by product variant" -msgstr "" - -#. module: stock_putaway_product_form -#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway -msgid "Put Away Strategies by category" -msgstr "" - -#. module: stock_putaway_product_form -#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_product_form_putaway -#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway -msgid "Put Away Strategies by products" -msgstr "" - -#. module: stock_putaway_product_form -#: model:ir.model,name:stock_putaway_product_form.model_product_putaway -msgid "Put Away Strategy" -msgstr "" - -#. module: stock_putaway_product_form -#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway -msgid "Putaway strategies" -msgstr "" - -#. module: stock_putaway_product_form -#: model_terms:ir.ui.view,arch_db:stock_putaway_product_form.view_template_form_putaway -msgid "The rules defined per product will be applied before the rules defined per product category." -msgstr "" - diff --git a/stock_putaway_product_template/i18n/stock_putaway_product_template.pot b/stock_putaway_product_template/i18n/stock_putaway_product_template.pot new file mode 100644 index 000000000..407361a64 --- /dev/null +++ b/stock_putaway_product_template/i18n/stock_putaway_product_template.pot @@ -0,0 +1,26 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_putaway_product_template +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-02-10 15:21+0000\n" +"PO-Revision-Date: 2021-02-10 15:21+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_putaway_product_template +#: model:ir.model.fields,field_description:stock_putaway_product_template.field_stock_putaway_rule__product_tmpl_id +msgid "Product Tmpl" +msgstr "" + +#. module: stock_putaway_product_template +#: model:ir.model,name:stock_putaway_product_template.model_stock_putaway_rule +msgid "Putaway Rule" +msgstr "" diff --git a/stock_putaway_product_template/models/__init__.py b/stock_putaway_product_template/models/__init__.py index 46b77487a..ec67c6f7b 100644 --- a/stock_putaway_product_template/models/__init__.py +++ b/stock_putaway_product_template/models/__init__.py @@ -1,3 +1,3 @@ -from . import product_product -from . import product_template -from . import putaway_strategy +from . import product +from . import stock_location +from . import stock_putaway_rule diff --git a/stock_putaway_product_template/models/product.py b/stock_putaway_product_template/models/product.py new file mode 100644 index 000000000..8e7dce477 --- /dev/null +++ b/stock_putaway_product_template/models/product.py @@ -0,0 +1,19 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# Copyright 2021 Tecnativa - Víctor Martínez + +from odoo import models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + def action_view_related_putaway_rules(self): + self.ensure_one() + domain = [ + "|", + "|", + ("product_tmpl_id", "=", self.id), + ("category_id", "=", self.categ_id.id), + ("product_id.product_tmpl_id", "=", self.id), + ] + return self._get_action_view_related_putaway_rules(domain) diff --git a/stock_putaway_product_template/models/product_product.py b/stock_putaway_product_template/models/product_product.py deleted file mode 100644 index d6bd5d145..000000000 --- a/stock_putaway_product_template/models/product_product.py +++ /dev/null @@ -1,13 +0,0 @@ -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import fields, models - - -class ProductProduct(models.Model): - _inherit = "product.product" - - product_product_putaway_ids = fields.One2many( - comodel_name="stock.fixed.putaway.strat", - inverse_name="product_id", - string="Product putaway strategies by product variant", - ) diff --git a/stock_putaway_product_template/models/product_template.py b/stock_putaway_product_template/models/product_template.py deleted file mode 100644 index 39d4b6893..000000000 --- a/stock_putaway_product_template/models/product_template.py +++ /dev/null @@ -1,58 +0,0 @@ -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import api, fields, models - - -class ProductTemplate(models.Model): - _inherit = "product.template" - - product_tmpl_putaway_ids = fields.One2many( - comodel_name="stock.fixed.putaway.strat", - inverse_name="product_tmpl_id", - string="Product putaway strategies by product", - ) - - product_putaway_categ_ids = fields.Many2many( - comodel_name="stock.fixed.putaway.strat", - string="Product putaway strategies by category", - compute="_compute_putaway_categ_ids", - ) - - def _find_closest_categ_match(self, categ, putaway_lines): - """Returns the putaway line with the nearest product category""" - lines_match_categ = putaway_lines.filtered(lambda r: r.category_id == categ) - if lines_match_categ: - return lines_match_categ[0] - elif categ.parent_id: - return self._find_closest_categ_match(categ.parent_id, putaway_lines) - else: - return self.env["stock.fixed.putaway.strat"] - - def _get_categ_and_parents(self, categ): - parent_categ_iterator = categ - res = self.env["product.category"] - while parent_categ_iterator: - res += parent_categ_iterator - parent_categ_iterator = parent_categ_iterator.parent_id - return res - - @api.depends("categ_id") - def _compute_putaway_categ_ids(self): - """Pay attention to keep only 1 (most specific, - i.e closest to our product category's parents) - putaway.strat per product.putaway""" - for rec in self: - res = self.env["stock.fixed.putaway.strat"] - categ = rec.categ_id - categs = self._get_categ_and_parents(categ) - # get matching lines from our category or its parents - product_putaway_categ_lines = self.env["stock.fixed.putaway.strat"].search( - [("category_id", "in", categs.ids)] - ) - # from these, get the matching putaway.strats and find - # the lowest-level category match - product_putaways = product_putaway_categ_lines.mapped("putaway_id") - for el in product_putaways: - lines = el.fixed_location_ids - res += self._find_closest_categ_match(categ, lines) - rec.product_putaway_categ_ids = res diff --git a/stock_putaway_product_template/models/stock_location.py b/stock_putaway_product_template/models/stock_location.py new file mode 100644 index 000000000..f2442e763 --- /dev/null +++ b/stock_putaway_product_template/models/stock_location.py @@ -0,0 +1,13 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# Copyright 2020 Tecnativa - Sergio Teruel + +from odoo import models + + +class StockLocation(models.Model): + _inherit = "stock.location" + + def _get_putaway_strategy(self, product): + return super( + StockLocation, self.with_context(filter_putaway_rule=True) + )._get_putaway_strategy(product) diff --git a/stock_putaway_product_template/models/putaway_strategy.py b/stock_putaway_product_template/models/stock_putaway_rule.py similarity index 64% rename from stock_putaway_product_template/models/putaway_strategy.py rename to stock_putaway_product_template/models/stock_putaway_rule.py index 1a0411559..02a401ac8 100644 --- a/stock_putaway_product_template/models/putaway_strategy.py +++ b/stock_putaway_product_template/models/stock_putaway_rule.py @@ -1,35 +1,25 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -# Copyright 2020 Sergio Teruel - Tecnativa +# Copyright 2020 Sergio Teruel - Tecnativa +# Copyright 2020 Víctor Martínez - Tecnativa from odoo import api, fields, models -class PutAwayStrategy(models.Model): - _inherit = "product.putaway" - - # Remove product domain to allow to select product templates - product_location_ids = fields.One2many(domain=[]) - - def _get_putaway_rule(self, product): - return super( - PutAwayStrategy, self.with_context(filter_putaway_rule=True) - )._get_putaway_rule(product) - - -class FixedPutAwayStrategy(models.Model): - _inherit = "stock.fixed.putaway.strat" +class StockPutawayRule(models.Model): + _inherit = "stock.putaway.rule" product_tmpl_id = fields.Many2one( comodel_name="product.template", compute="_compute_product_tmpl_id", store=True, - inverse=lambda self: self, + readonly=False, ondelete="cascade", ) @api.depends("product_id") def _compute_product_tmpl_id(self): for rec in self: + rec.product_tmpl_id = False if rec.product_id: rec.product_tmpl_id = rec.product_id.product_tmpl_id else: @@ -38,7 +28,7 @@ class FixedPutAwayStrategy(models.Model): rec.product_tmpl_id = params.get("id", False) def filtered(self, func): - res = super(FixedPutAwayStrategy, self).filtered(func) + res = super(StockPutawayRule, self).filtered(func) if res or not self.env.context.get("filter_putaway_rule"): return res product = func.__closure__[0].cell_contents diff --git a/stock_putaway_product_template/readme/CONTRIBUTORS.rst b/stock_putaway_product_template/readme/CONTRIBUTORS.rst index ae30e064e..c8a035ba5 100644 --- a/stock_putaway_product_template/readme/CONTRIBUTORS.rst +++ b/stock_putaway_product_template/readme/CONTRIBUTORS.rst @@ -5,3 +5,4 @@ * `Tecnativa `_: * Sergio Teruel + * Víctor Martínez diff --git a/stock_putaway_product_template/readme/DESCRIPTION.rst b/stock_putaway_product_template/readme/DESCRIPTION.rst index d4507868e..99ae80c30 100644 --- a/stock_putaway_product_template/readme/DESCRIPTION.rst +++ b/stock_putaway_product_template/readme/DESCRIPTION.rst @@ -1 +1 @@ -This module adds an easy way to modify product-specific putaway strategies from the product view for a better UX. +This module add product template in putaway strategies from the product view to not need defined putaway strategies for all variants. diff --git a/stock_putaway_product_template/readme/USAGE.rst b/stock_putaway_product_template/readme/USAGE.rst index 7657200db..1723ea641 100644 --- a/stock_putaway_product_template/readme/USAGE.rst +++ b/stock_putaway_product_template/readme/USAGE.rst @@ -1,3 +1,4 @@ -* In Settings, set "Storage Locations" to True +* In Inventory Settings, set "Storage Locations" to True * User should be in "Manage push and pull inventory flows" -* Open the form view of a product template or a product and use the fields located under the "Inventory" tab +* Inside a product go to "Putaway rules" +* It's possible to define record to template diff --git a/stock_putaway_product_template/static/description/index.html b/stock_putaway_product_template/static/description/index.html index 8e00f4ce5..44c9d4a33 100644 --- a/stock_putaway_product_template/static/description/index.html +++ b/stock_putaway_product_template/static/description/index.html @@ -367,7 +367,7 @@ ul.auto-toc { !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

    Beta License: AGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runbot

    +

    Beta License: AGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runbot

    This module adds an easy way to modify product-specific putaway strategies from the product view for a better UX.

    Table of contents

    @@ -395,7 +395,7 @@ ul.auto-toc {

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -feedback.

    +feedback.

    Do not contact contributors directly about support or help with technical issues.

    @@ -428,7 +428,7 @@ mission is to support the collaborative development of Odoo features and promote its widespread use.

    Current maintainers:

    kevinkhao sebastienbeau

    -

    This module is part of the OCA/stock-logistics-warehouse project on GitHub.

    +

    This module is part of the OCA/stock-logistics-warehouse project on GitHub.

    You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

    diff --git a/stock_putaway_product_template/tests/__init__.py b/stock_putaway_product_template/tests/__init__.py index a5b56cbc2..a00cffade 100644 --- a/stock_putaway_product_template/tests/__init__.py +++ b/stock_putaway_product_template/tests/__init__.py @@ -1,3 +1,3 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from . import test_product_putaway +from . import test_stock_putaway_rule diff --git a/stock_putaway_product_template/tests/test_product_putaway.py b/stock_putaway_product_template/tests/test_product_putaway.py deleted file mode 100644 index f4de9f10f..000000000 --- a/stock_putaway_product_template/tests/test_product_putaway.py +++ /dev/null @@ -1,102 +0,0 @@ -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo.tests.common import TransactionCase - - -class TestProductPutaway(TransactionCase): - def setUp(self): - super().setUp() - self.putawayObj = self.env["product.putaway"] - self.putawayLineObj = self.env["stock.fixed.putaway.strat"] - ProductTemplate = self.env["product.template"] - ProductAttribute = self.env["product.attribute"] - ProductAttributeValue = self.env["product.attribute.value"] - TemplateAttributeLine = self.env["product.template.attribute.line"] - ref = self.env.ref - self.product_tmpl_chair = ref("product.product_product_11_product_template") - self.product_product_chair = ref("product.product_product_11") - self.category_services = ref("product.product_category_3") - self.putaway_line_1 = ref("stock_putaway_product_form.putaway_strat_1_line_1") - self.putaway_line_2 = ref("stock_putaway_product_form.putaway_strat_1_line_2") - self.putaway_line_3 = ref("stock_putaway_product_form.putaway_strat_2_line_1") - self.putaway_line_4 = ref("stock_putaway_product_form.putaway_strat_2_line_2") - - # Add a product with variants - self.template = ProductTemplate.create( - {"name": "Product test", "type": "consu"} - ) - self.size_attribute = ProductAttribute.create( - {"name": "Test size", "sequence": 1} - ) - self.size_m = ProductAttributeValue.create( - {"name": "Size M", "attribute_id": self.size_attribute.id, "sequence": 1} - ) - self.size_l = ProductAttributeValue.create( - {"name": "Size L", "attribute_id": self.size_attribute.id, "sequence": 2} - ) - self.template_attribute_lines = TemplateAttributeLine.create( - { - "product_tmpl_id": self.template.id, - "attribute_id": self.size_attribute.id, - "value_ids": [(6, 0, [self.size_m.id, self.size_l.id])], - } - ) - self.template.create_variant_ids() - - def test_tmpl_has_putaways_from_products(self): - self.assertIn( - self.putaway_line_1, self.product_tmpl_chair.product_tmpl_putaway_ids, - ) - self.putaway_line_1.product_id = self.env["product.product"] - self.assertNotIn( - self.putaway_line_1, self.product_tmpl_chair.product_tmpl_putaway_ids, - ) - - def test_tmpl_has_putaways_from_category_simple(self): - self.assertIn( - self.putaway_line_2, self.product_tmpl_chair.product_putaway_categ_ids, - ) - self.product_tmpl_chair.categ_id = self.category_services - self.assertNotIn( - self.putaway_line_2, self.product_tmpl_chair.product_putaway_categ_ids, - ) - - def test_tmpl_has_putaways_from_category_parent(self): - # chair is under category: all/saleable/office - self.assertIn( - self.putaway_line_3, self.product_tmpl_chair.product_putaway_categ_ids, - ) - self.assertNotIn( - self.putaway_line_4, self.product_tmpl_chair.product_putaway_categ_ids, - ) - - def test_apply_putaway(self): - # Create one strategy line for product template and other with a - # specific variant - location = self.env.ref("stock.stock_location_shop0") - location1 = location.copy( - {"name": "Location test 1", "location_id": location.id} - ) - location2 = location.copy( - {"name": "Location test 2", "location_id": location.id} - ) - variant1 = self.template.product_variant_ids[0] - variant2 = self.template.product_variant_ids[1] - putaway = self.putawayObj.create({"name": "Putaway for test"}) - val_list = [ - { - "putaway_id": putaway.id, - "product_tmpl_id": self.template.id, - "fixed_location_id": location1.id, - }, - { - "putaway_id": putaway.id, - "product_id": variant2.id, - "fixed_location_id": location2.id, - }, - ] - self.putawayLineObj.create(val_list) - location_applied = putaway._get_putaway_rule(variant1).fixed_location_id - self.assertEqual(location_applied, location1) - location_applied = putaway._get_putaway_rule(variant2).fixed_location_id - self.assertEqual(location_applied, location2) diff --git a/stock_putaway_product_template/tests/test_stock_putaway_rule.py b/stock_putaway_product_template/tests/test_stock_putaway_rule.py new file mode 100644 index 000000000..1887db464 --- /dev/null +++ b/stock_putaway_product_template/tests/test_stock_putaway_rule.py @@ -0,0 +1,110 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# Copyright 2020 Tecnativa - Sergio Teruel +# Copyright 2020-2021 Víctor Martínez - Tecnativa + +from odoo.tests import common + + +class TestStockPutawayRule(common.SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.putawayRuleObj = cls.env["stock.putaway.rule"] + ProductTemplate = cls.env["product.template"] + ProductAttribute = cls.env["product.attribute"] + ProductAttributeValue = cls.env["product.attribute.value"] + TemplateAttributeLine = cls.env["product.template.attribute.line"] + # Add a product with variants + cls.template = ProductTemplate.create({"name": "Product test", "type": "consu"}) + cls.size_attribute = ProductAttribute.create( + {"name": "Test size", "sequence": 1} + ) + cls.size_m = ProductAttributeValue.create( + {"name": "Size M", "attribute_id": cls.size_attribute.id, "sequence": 1} + ) + cls.size_l = ProductAttributeValue.create( + {"name": "Size L", "attribute_id": cls.size_attribute.id, "sequence": 2} + ) + cls.size_xl = ProductAttributeValue.create( + {"name": "Size XL", "attribute_id": cls.size_attribute.id, "sequence": 3} + ) + cls.template_attribute_lines = TemplateAttributeLine.create( + { + "product_tmpl_id": cls.template.id, + "attribute_id": cls.size_attribute.id, + "value_ids": [(6, 0, [cls.size_m.id, cls.size_l.id, cls.size_xl.id])], + } + ) + cls.template._create_variant_ids() + cls.view_id = cls.env.ref("stock.stock_putaway_list").id + + def _stock_putaway_rule_product(self, location, product): + rule = self.putawayRuleObj.create( + { + "company_id": location.company_id.id, + "product_id": product.id, + "location_in_id": location.id, + "location_out_id": location.id, + } + ) + self.assertEqual(rule.location_in_id, location) + self.assertEqual(rule.product_tmpl_id, product.product_tmpl_id) + self.assertEqual(rule.product_id, product) + return rule + + def _get_product_rules(self, product): + return self.putawayRuleObj.search( + product.action_view_related_putaway_rules()["domain"] + ) + + def test_apply_putaway(self): + # Create one strategy line for product template and other with a + # specific variant + location = self.env.ref("stock.stock_location_shop0") + location1 = location.copy( + {"name": "Location test 1", "location_id": location.id} + ) + location2 = location.copy( + {"name": "Location test 2", "location_id": location.id} + ) + # Create rule according to product_tmpl_id + rule_product = self.putawayRuleObj.create( + { + "company_id": location1.company_id.id, + "product_tmpl_id": self.template.id, + "location_in_id": location1.id, + "location_out_id": location1.id, + } + ) + self.assertEqual(rule_product.location_in_id, location1) + self.assertEqual(rule_product.product_tmpl_id, self.template) + self.assertEqual(rule_product.product_id.id, False) + # Create rules related to variants and diferente locations + variant1 = self.template.product_variant_ids[0] + variant2 = self.template.product_variant_ids[1] + variant3 = self.template.product_variant_ids[2] + self._stock_putaway_rule_product(location1, variant1) + self._stock_putaway_rule_product(location2, variant2) + # Create rule according to category + rule_category = self.putawayRuleObj.create( + { + "company_id": location1.company_id.id, + "category_id": self.template.categ_id.id, + "location_in_id": location1.id, + "location_out_id": location1.id, + } + ) + self.assertEqual(rule_category.category_id, self.template.categ_id) + self.assertEqual(rule_category.location_in_id, location1) + self.assertEqual(rule_category.product_tmpl_id.id, False) + self.assertEqual(rule_category.product_id.id, False) + # Check rules related + self.assertEqual(len(self._get_product_rules(self.template)), 4) + self.assertEqual(len(self._get_product_rules(variant1)), 2) + self.assertEqual(len(self._get_product_rules(variant2)), 2) + self.assertEqual(len(self._get_product_rules(variant3)), 1) + # Check _get_putaway_strategy + locations = location + location.child_ids + self.assertEqual(locations._get_putaway_strategy(variant1), location1) + self.assertEqual(locations._get_putaway_strategy(variant2), location2) + self.assertEqual(locations._get_putaway_strategy(variant3), location1) diff --git a/stock_putaway_product_template/views/product.xml b/stock_putaway_product_template/views/product.xml deleted file mode 100644 index 1102606d2..000000000 --- a/stock_putaway_product_template/views/product.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - product.template.product.form - product.template - - - - -
    - - - -

    - The rules defined per product will be applied before the rules defined per product category. -

    Keep empty product field to apply strategy to all variants.
    -

    -
    - - - - - - - -
    - - - - - - - - - -
    -
    -
    -
    - - product.product.form.putaway - product.product - - - - - - - - - - - - - - - -
    diff --git a/stock_putaway_product_template/views/stock_putaway_rule_views.xml b/stock_putaway_product_template/views/stock_putaway_rule_views.xml new file mode 100644 index 000000000..7cf651f98 --- /dev/null +++ b/stock_putaway_product_template/views/stock_putaway_rule_views.xml @@ -0,0 +1,31 @@ + + + + + Add product_tmpl_id field + stock.putaway.rule + + + + False + {'readonly': [('category_id', '!=', False)], 'required': [('category_id', '=', False),('product_tmpl_id', '=', False)]} + + + False + {'readonly': ['|', ('product_id', '!=', False), ('product_tmpl_id', '!=', False)], 'required': [('product_id', '=', False),('product_tmpl_id', '=', False)]} + + + + + + +