diff --git a/stock_secondary_unit/__manifest__.py b/stock_secondary_unit/__manifest__.py
index 2be2e08a7..2271b25a1 100644
--- a/stock_secondary_unit/__manifest__.py
+++ b/stock_secondary_unit/__manifest__.py
@@ -3,7 +3,7 @@
{
"name": "Stock Secondary Unit",
"summary": "Get product quantities in a secondary unit",
- "version": "13.0.1.1.1",
+ "version": "13.0.2.0.0",
"development_status": "Production/Stable",
"category": "stock",
"website": "https://github.com/OCA/stock-logistics-warehouse",
diff --git a/stock_secondary_unit/i18n/es.po b/stock_secondary_unit/i18n/es.po
index 8d6d0a8b3..2acd50bdd 100644
--- a/stock_secondary_unit/i18n/es.po
+++ b/stock_secondary_unit/i18n/es.po
@@ -24,19 +24,26 @@ msgstr ""
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_product_secondary_unit__display_name
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__display_name
msgid "Display Name"
msgstr "Mostrar Nombre"
+#. module: stock_secondary_unit
+#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move_line__qty_done
+msgid "Done"
+msgstr ""
+
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_product_secondary_unit__id
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__id
msgid "ID"
msgstr "ID"
+#. module: stock_secondary_unit
+#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move__product_uom_qty
+msgid "Initial Demand"
+msgstr ""
+
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_product_secondary_unit____last_update
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin____last_update
msgid "Last Modified on"
msgstr "Última modificación en"
@@ -62,28 +69,12 @@ msgstr "Plantilla de producto"
msgid "Quantity On Hand (2Unit)"
msgstr "Cantidad a mano (2Ud.)"
-#. module: stock_secondary_unit
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move__secondary_uom_id
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move_line__secondary_uom_id
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__secondary_uom_id
-#, fuzzy
-msgid "Second unit"
-msgstr "Unidad Secundaria"
-
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_product_product__stock_secondary_uom_id
#: model:ir.model.fields,field_description:stock_secondary_unit.field_product_template__stock_secondary_uom_id
msgid "Second unit for inventory"
msgstr "Segunda unidad de medida para inventario"
-#. module: stock_secondary_unit
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move__secondary_uom_qty
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move_line__secondary_uom_qty
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__secondary_uom_qty
-#, fuzzy
-msgid "Secondary Qty"
-msgstr "Unidad Secundaria"
-
#. module: stock_secondary_unit
#: model_terms:ir.ui.view,arch_db:stock_secondary_unit.view_template_property_form
msgid "Secondary unit"
@@ -101,10 +92,27 @@ msgid "Stock Product Secondary Unit"
msgstr "Unidad Secundaria"
#. module: stock_secondary_unit
-#: model:ir.model,name:stock_secondary_unit.model_stock_secondary_unit_mixin
+#: model:ir.model.fields,help:stock_secondary_unit.field_stock_move__product_uom_qty
+msgid ""
+"This is the quantity of products from an inventory point of view. For moves "
+"in the state 'done', this is the quantity of products that were actually "
+"moved. For other moves, this is the quantity of product that is planned to "
+"be moved. Lowering this quantity does not generate a backorder. Changing "
+"this quantity on assigned moves affects the product reservation, and should "
+"be done with care."
+msgstr ""
+
#, fuzzy
-msgid "Stock Secondary Unit Mixin"
-msgstr "Unidad Secundaria"
+#~ msgid "Second unit"
+#~ msgstr "Unidad Secundaria"
+
+#, fuzzy
+#~ msgid "Secondary Qty"
+#~ msgstr "Unidad Secundaria"
+
+#, fuzzy
+#~ msgid "Stock Secondary Unit Mixin"
+#~ msgstr "Unidad Secundaria"
#~ msgid "On Hand (2unit)"
#~ msgstr "A mano (2Ud.)"
diff --git a/stock_secondary_unit/i18n/stock_secondary_unit.pot b/stock_secondary_unit/i18n/stock_secondary_unit.pot
index af04cff9f..dd55f8e0d 100644
--- a/stock_secondary_unit/i18n/stock_secondary_unit.pot
+++ b/stock_secondary_unit/i18n/stock_secondary_unit.pot
@@ -20,19 +20,26 @@ msgstr ""
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_product_secondary_unit__display_name
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__display_name
msgid "Display Name"
msgstr ""
+#. module: stock_secondary_unit
+#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move_line__qty_done
+msgid "Done"
+msgstr ""
+
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_product_secondary_unit__id
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__id
msgid "ID"
msgstr ""
+#. module: stock_secondary_unit
+#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move__product_uom_qty
+msgid "Initial Demand"
+msgstr ""
+
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_product_secondary_unit____last_update
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin____last_update
msgid "Last Modified on"
msgstr ""
@@ -58,26 +65,12 @@ msgstr ""
msgid "Quantity On Hand (2Unit)"
msgstr ""
-#. module: stock_secondary_unit
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move__secondary_uom_id
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move_line__secondary_uom_id
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__secondary_uom_id
-msgid "Second unit"
-msgstr ""
-
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_product_product__stock_secondary_uom_id
#: model:ir.model.fields,field_description:stock_secondary_unit.field_product_template__stock_secondary_uom_id
msgid "Second unit for inventory"
msgstr ""
-#. module: stock_secondary_unit
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move__secondary_uom_qty
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move_line__secondary_uom_qty
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__secondary_uom_qty
-msgid "Secondary Qty"
-msgstr ""
-
#. module: stock_secondary_unit
#: model_terms:ir.ui.view,arch_db:stock_secondary_unit.view_template_property_form
msgid "Secondary unit"
@@ -94,6 +87,12 @@ msgid "Stock Product Secondary Unit"
msgstr ""
#. module: stock_secondary_unit
-#: model:ir.model,name:stock_secondary_unit.model_stock_secondary_unit_mixin
-msgid "Stock Secondary Unit Mixin"
+#: model:ir.model.fields,help:stock_secondary_unit.field_stock_move__product_uom_qty
+msgid ""
+"This is the quantity of products from an inventory point of view. For moves "
+"in the state 'done', this is the quantity of products that were actually "
+"moved. For other moves, this is the quantity of product that is planned to "
+"be moved. Lowering this quantity does not generate a backorder. Changing "
+"this quantity on assigned moves affects the product reservation, and should "
+"be done with care."
msgstr ""
diff --git a/stock_secondary_unit/i18n/zh_CN.po b/stock_secondary_unit/i18n/zh_CN.po
index d326116ef..47986d9e0 100644
--- a/stock_secondary_unit/i18n/zh_CN.po
+++ b/stock_secondary_unit/i18n/zh_CN.po
@@ -1,6 +1,6 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
-# * stock_secondary_unit
+# * stock_secondary_unit
#
msgid ""
msgstr ""
@@ -23,19 +23,26 @@ msgstr " 辅助单位数量"
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_product_secondary_unit__display_name
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__display_name
msgid "Display Name"
msgstr "显示名称"
+#. module: stock_secondary_unit
+#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move_line__qty_done
+msgid "Done"
+msgstr ""
+
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_product_secondary_unit__id
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__id
msgid "ID"
msgstr "ID"
+#. module: stock_secondary_unit
+#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move__product_uom_qty
+msgid "Initial Demand"
+msgstr ""
+
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_product_secondary_unit____last_update
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin____last_update
msgid "Last Modified on"
msgstr "最后修改时间"
@@ -61,26 +68,12 @@ msgstr "产品模板"
msgid "Quantity On Hand (2Unit)"
msgstr "在手数量(辅助单位)"
-#. module: stock_secondary_unit
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move__secondary_uom_id
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move_line__secondary_uom_id
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__secondary_uom_id
-msgid "Second unit"
-msgstr "辅助单位"
-
#. module: stock_secondary_unit
#: model:ir.model.fields,field_description:stock_secondary_unit.field_product_product__stock_secondary_uom_id
#: model:ir.model.fields,field_description:stock_secondary_unit.field_product_template__stock_secondary_uom_id
msgid "Second unit for inventory"
msgstr "库存辅助单位"
-#. module: stock_secondary_unit
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move__secondary_uom_qty
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_move_line__secondary_uom_qty
-#: model:ir.model.fields,field_description:stock_secondary_unit.field_stock_secondary_unit_mixin__secondary_uom_qty
-msgid "Secondary Qty"
-msgstr "辅助单位数量"
-
#. module: stock_secondary_unit
#: model_terms:ir.ui.view,arch_db:stock_secondary_unit.view_template_property_form
msgid "Secondary unit"
@@ -97,6 +90,21 @@ msgid "Stock Product Secondary Unit"
msgstr "库存产品辅助单位"
#. module: stock_secondary_unit
-#: model:ir.model,name:stock_secondary_unit.model_stock_secondary_unit_mixin
-msgid "Stock Secondary Unit Mixin"
-msgstr "库存辅助单位混合类"
+#: model:ir.model.fields,help:stock_secondary_unit.field_stock_move__product_uom_qty
+msgid ""
+"This is the quantity of products from an inventory point of view. For moves "
+"in the state 'done', this is the quantity of products that were actually "
+"moved. For other moves, this is the quantity of product that is planned to "
+"be moved. Lowering this quantity does not generate a backorder. Changing "
+"this quantity on assigned moves affects the product reservation, and should "
+"be done with care."
+msgstr ""
+
+#~ msgid "Second unit"
+#~ msgstr "辅助单位"
+
+#~ msgid "Secondary Qty"
+#~ msgstr "辅助单位数量"
+
+#~ msgid "Stock Secondary Unit Mixin"
+#~ msgstr "库存辅助单位混合类"
diff --git a/stock_secondary_unit/models/stock_move.py b/stock_secondary_unit/models/stock_move.py
index 49821a399..22c1580e1 100644
--- a/stock_secondary_unit/models/stock_move.py
+++ b/stock_secondary_unit/models/stock_move.py
@@ -4,31 +4,45 @@ from odoo import api, fields, models
from odoo.tools.float_utils import float_round
-class StockSecondaryUnitMixin(models.AbstractModel):
- _name = "stock.secondary.unit.mixin"
- _description = "Stock Secondary Unit Mixin"
-
- secondary_uom_id = fields.Many2one(
- comodel_name="product.secondary.unit", string="Second unit"
- )
- secondary_uom_qty = fields.Float(
- string="Secondary Qty", digits="Product Unit of Measure"
- )
-
-
class StockMove(models.Model):
- _inherit = ["stock.move", "stock.secondary.unit.mixin"]
+ _inherit = ["stock.move", "product.secondary.unit.mixin"]
_name = "stock.move"
+ _secondary_unit_fields = {
+ "qty_field": "product_uom_qty",
+ "uom_field": "product_uom",
+ }
+
+ product_uom_qty = fields.Float(
+ store=True, readonly=False, compute="_compute_product_uom_qty", copy=True
+ )
+
+ @api.depends("secondary_uom_qty", "secondary_uom_id")
+ def _compute_product_uom_qty(self):
+ self._compute_helper_target_field_qty()
+
+ @api.onchange("product_uom")
+ def onchange_product_uom_for_secondary(self):
+ self._onchange_helper_product_uom_for_secondary()
def _merge_moves_fields(self):
res = super()._merge_moves_fields()
- res["secondary_uom_qty"] = self[-1:].secondary_uom_qty
+ res["secondary_uom_qty"] = sum(self.mapped("secondary_uom_qty"))
return res
+ @api.model
+ def _prepare_merge_moves_distinct_fields(self):
+ """Don't merge moves with distinct secondary units"""
+ distinct_fields = super()._prepare_merge_moves_distinct_fields()
+ distinct_fields += ["secondary_uom_id"]
+ return distinct_fields
+
class StockMoveLine(models.Model):
- _inherit = ["stock.move.line", "stock.secondary.unit.mixin"]
+ _inherit = ["stock.move.line", "product.secondary.unit.mixin"]
_name = "stock.move.line"
+ _secondary_unit_fields = {"qty_field": "qty_done", "uom_field": "product_uom_id"}
+
+ qty_done = fields.Float(store=True, readonly=False, compute="_compute_qty_done")
@api.model
def create(self, vals):
@@ -45,3 +59,7 @@ class StockMoveLine(models.Model):
{"secondary_uom_qty": qty, "secondary_uom_id": move.secondary_uom_id.id}
)
return super().create(vals)
+
+ @api.depends("secondary_uom_id", "secondary_uom_qty")
+ def _compute_qty_done(self):
+ self._compute_helper_target_field_qty()
diff --git a/stock_secondary_unit/tests/test_stock_secondary_unit.py b/stock_secondary_unit/tests/test_stock_secondary_unit.py
index 5059a43b3..404c2bbbc 100644
--- a/stock_secondary_unit/tests/test_stock_secondary_unit.py
+++ b/stock_secondary_unit/tests/test_stock_secondary_unit.py
@@ -1,17 +1,24 @@
# Copyright 2018 Tecnativa - Sergio Teruel
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-from odoo.tests import SavepointCase
+from odoo.tests import Form, SavepointCase, tagged
+@tagged("-at_install", "post_install")
class TestProductSecondaryUnit(SavepointCase):
- at_install = False
- post_install = True
-
@classmethod
def setUpClass(cls):
super().setUpClass()
+ # Active multiple units of measure security group for user
+ cls.env.user.groups_id = [(4, cls.env.ref("uom.group_uom").id)]
+ cls.StockPicking = cls.env["stock.picking"]
cls.warehouse = cls.env.ref("stock.warehouse0")
+ cls.location_supplier = cls.env.ref("stock.stock_location_suppliers")
+ cls.location_stock = cls.env.ref("stock.stock_location_stock")
+ cls.picking_type_in = cls.env.ref("stock.picking_type_in")
+ cls.picking_type_out = cls.env.ref("stock.picking_type_out")
+
cls.product_uom_kg = cls.env.ref("uom.product_uom_kgm")
+ cls.product_uom_ton = cls.env.ref("uom.product_uom_ton")
cls.product_uom_unit = cls.env.ref("uom.product_uom_unit")
ProductAttribute = cls.env["product.attribute"]
ProductAttributeValue = cls.env["product.attribute.value"]
@@ -34,7 +41,7 @@ class TestProductSecondaryUnit(SavepointCase):
0,
{
"code": "A",
- "name": "unit-700",
+ "name": "unit-500",
"uom_id": cls.product_uom_unit.id,
"factor": 0.5,
},
@@ -49,6 +56,16 @@ class TestProductSecondaryUnit(SavepointCase):
"factor": 0.9,
},
),
+ (
+ 0,
+ 0,
+ {
+ "code": "C",
+ "name": "box 10",
+ "uom_id": cls.product_uom_unit.id,
+ "factor": 10,
+ },
+ ),
],
"attribute_line_ids": [
(
@@ -97,22 +114,19 @@ class TestProductSecondaryUnit(SavepointCase):
def test_03_stock_picking_secondary_unit(self):
StockPicking = self.env["stock.picking"]
product1 = self.product_template.product_variant_ids[0]
- location = self.env.ref("stock.stock_location_suppliers")
- location_dest = self.env.ref("stock.stock_location_stock")
- picking_type = self.env.ref("stock.picking_type_in")
move_vals = {
"product_id": product1.id,
"name": product1.display_name,
"secondary_uom_id": product1.secondary_uom_ids[0].id,
"product_uom": product1.uom_id.id,
"product_uom_qty": 10.0,
- "location_id": location.id,
- "location_dest_id": location_dest.id,
+ "location_id": self.location_supplier.id,
+ "location_dest_id": self.location_stock.id,
}
do_vals = {
- "location_id": location.id,
- "location_dest_id": location_dest.id,
- "picking_type_id": picking_type.id,
+ "location_id": self.location_supplier.id,
+ "location_dest_id": self.location_stock.id,
+ "picking_type_id": self.picking_type_in.id,
"move_ids_without_package": [
(0, None, move_vals),
(0, None, move_vals),
@@ -130,3 +144,83 @@ class TestProductSecondaryUnit(SavepointCase):
)
self.assertEquals(uom_qty, 20.0)
self.assertEquals(secondary_uom_qty, 40.0)
+
+ def test_picking_secondary_unit(self):
+ product = self.product_template.product_variant_ids[0]
+ with Form(
+ self.StockPicking.with_context(
+ planned_picking=True, default_picking_type_id=self.picking_type_out.id,
+ )
+ ) as picking_form:
+ with picking_form.move_ids_without_package.new() as move:
+ move.product_id = product
+ move.secondary_uom_qty = 1
+ move.secondary_uom_id = product.secondary_uom_ids[0]
+ self.assertEqual(move.product_uom_qty, 0.5)
+ move.secondary_uom_qty = 2
+ self.assertEqual(move.product_uom_qty, 1)
+ move.secondary_uom_id = product.secondary_uom_ids[1]
+ self.assertEqual(move.product_uom_qty, 1.8)
+ move.product_uom_qty = 5
+ self.assertAlmostEqual(move.secondary_uom_qty, 5.56, 2)
+ # Change uom from stock move line
+ move.secondary_uom_qty = 1
+ move.secondary_uom_id = product.secondary_uom_ids[2]
+ self.assertEqual(move.product_uom_qty, 10)
+ move.product_uom = self.product_uom_ton
+ self.assertAlmostEqual(move.secondary_uom_qty, 1000, 2)
+
+ picking = picking_form.save()
+ picking.action_confirm()
+ with Form(picking) as picking_form:
+ # Test detail operations
+ with picking_form.move_line_ids_without_package.new() as move:
+ move.product_id = product
+ move.secondary_uom_qty = 1
+ move.secondary_uom_id = product.secondary_uom_ids[0]
+ self.assertEqual(move.qty_done, 0.5)
+ move.secondary_uom_qty = 2
+ self.assertEqual(move.qty_done, 1)
+ move.secondary_uom_id = product.secondary_uom_ids[1]
+ self.assertEqual(move.qty_done, 1.8)
+ move.qty_done = 5
+ self.assertAlmostEqual(move.secondary_uom_qty, 5.56, 2)
+
+ def test_secondary_unit_merge_move_diff_uom(self):
+ product = self.product_template.product_variant_ids[0]
+ with Form(
+ self.StockPicking.with_context(
+ planned_picking=True, default_picking_type_id=self.picking_type_out.id,
+ )
+ ) as picking_form:
+ with picking_form.move_ids_without_package.new() as move:
+ move.product_id = product
+ move.secondary_uom_qty = 1
+ move.secondary_uom_id = product.secondary_uom_ids[0]
+ with picking_form.move_ids_without_package.new() as move:
+ move.product_id = product
+ move.secondary_uom_qty = 1
+ move.secondary_uom_id = product.secondary_uom_ids[1]
+ picking = picking_form.save()
+ picking.action_confirm()
+ self.assertEquals(len(picking.move_lines), 2)
+
+ def test_secondary_unit_merge_move_same_uom(self):
+ product = self.product_template.product_variant_ids[0]
+ with Form(
+ self.StockPicking.with_context(
+ planned_picking=True, default_picking_type_id=self.picking_type_out.id,
+ )
+ ) as picking_form:
+ with picking_form.move_ids_without_package.new() as move:
+ move.product_id = product
+ move.secondary_uom_qty = 1
+ move.secondary_uom_id = product.secondary_uom_ids[0]
+ with picking_form.move_ids_without_package.new() as move:
+ move.product_id = product
+ move.secondary_uom_qty = 1
+ move.secondary_uom_id = product.secondary_uom_ids[0]
+ picking = picking_form.save()
+ picking.action_confirm()
+ self.assertEquals(len(picking.move_lines), 1)
+ self.assertEquals(picking.move_lines.secondary_uom_qty, 2)
diff --git a/stock_secondary_unit/views/stock_picking_views.xml b/stock_secondary_unit/views/stock_picking_views.xml
index 0b913b24b..a712c5775 100644
--- a/stock_secondary_unit/views/stock_picking_views.xml
+++ b/stock_secondary_unit/views/stock_picking_views.xml
@@ -12,11 +12,15 @@
expr="//field[@name='move_ids_without_package']/tree/field[@name='product_uom_qty']"
position="before"
>
-
+