[IMP] stock_putaway_product_form: Allow to define rules by product template

This commit is contained in:
Sergio Teruel
2020-04-12 12:21:09 +02:00
committed by Víctor Martínez
parent 63b1e519a7
commit 3550437ec3
7 changed files with 138 additions and 12 deletions

View File

@@ -2,3 +2,4 @@
from . import models
from . import tests
from .hooks import post_init_hook

View File

@@ -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",
}

View File

@@ -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
"""
)

View File

@@ -1,6 +1,18 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# Copyright 2020 Sergio Teruel - Tecnativa <sergio.teruel@tecnativa.com>
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))

View File

@@ -1,3 +1,7 @@
* Akretion <https://www.akretion.com>
* `Akretion <https://www.akretion.com>`_:
* Kevin Khao <kevin.khao@akretion.com>
* `Tecnativa <https://www.tecnativa.com>`_:
* Sergio Teruel

View File

@@ -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)

View File

@@ -9,20 +9,18 @@
<xpath expr="//page[@name='inventory']" position="inside">
<div name="putaway" groups="stock.group_adv_location" string="Putaway strategies">
<field name="product_variant_ids" invisible="1"/>
<field name="product_variant_id" invisible="1"/>
<group name="putaway_products" string="Put Away Strategies by products"
attrs="{'invisible': [('is_product_variant', '=', True)]}">
<group>
<p class="oe_grey">
The rules defined per product will be applied before the rules defined per product category.
<div>Keep empty product field to apply strategy to all variants.</div>
</p>
</group>
<field name="product_tmpl_putaway_ids"
nolabel="1">
<field name="product_tmpl_putaway_ids" nolabel="1">
<tree editable="top">
<field name="product_id" domain="[('product_tmpl_id', '=', parent.id)]"
options="{'no_create': 1}" required="True"/>
<field name="putaway_id" options="{'no_create': 1}"/>
<field name="product_id" domain="[('product_tmpl_id', '=', parent.id)]"/>
<field name="putaway_id"/>
<field name="fixed_location_id"/>
</tree>
</field>
@@ -53,7 +51,7 @@
attrs="{'invisible': [('is_product_variant', '=', False)]}">
<field name="product_product_putaway_ids" groups="stock.group_adv_location" nolabel="1">
<tree editable="bottom">
<field name="putaway_id" options="{'no_create': 1}"/>
<field name="putaway_id"/>
<field name="fixed_location_id"/>
</tree>
</field>