mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[MIG] stock_move_packaging_qty: migrate to 16.0
- Code and DB migrations to use upstream field `product_packaging_id`, introduced in https://github.com/odoo/odoo/pull/68654. - Test class moved to `post_install`, to let it pass if `sale_stock` is installed too. - Satisfy new linters. @moduon MT-3694
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
{
|
||||
"name": "Stock Packaging Qty",
|
||||
"summary": "Add packaging fields in the stock moves",
|
||||
"version": "13.0.1.1.1",
|
||||
"version": "16.0.1.0.0",
|
||||
"author": "ForgeFlow, Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/stock-logistics-warehouse",
|
||||
"category": "Warehouse",
|
||||
@@ -11,4 +11,5 @@
|
||||
"data": ["views/stock_picking_form_view.xml", "views/stock_move_tree_view.xml"],
|
||||
"license": "LGPL-3",
|
||||
"installable": True,
|
||||
"maintainers": ["yajo"],
|
||||
}
|
||||
|
||||
20
stock_move_packaging_qty/migrations/15.0.0/pre-migrate.py
Normal file
20
stock_move_packaging_qty/migrations/15.0.0/pre-migrate.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Copyright 2023 Moduon Team S.L. <info@moduon.team>
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
from openupgradelib import openupgrade
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
"""Use upstream column.
|
||||
|
||||
In https://github.com/odoo/odoo/pull/68654, upstream added product_packaging_id.
|
||||
That feature is removed from this module and migrated there.
|
||||
"""
|
||||
if openupgrade.column_exists(cr, "stock_move", "product_packaging"):
|
||||
openupgrade.rename_columns(
|
||||
cr,
|
||||
{
|
||||
"stock_move": [
|
||||
("product_packaging", "product_packaging_id"),
|
||||
],
|
||||
},
|
||||
)
|
||||
@@ -8,28 +8,21 @@ from odoo.exceptions import UserError
|
||||
class StockPicking(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
product_packaging = fields.Many2one(
|
||||
comodel_name="product.packaging",
|
||||
string="Package",
|
||||
default=False,
|
||||
check_company=True,
|
||||
)
|
||||
product_packaging_qty = fields.Float(
|
||||
string="Package quantity",
|
||||
compute="_compute_product_packaging_qty",
|
||||
inverse="_inverse_product_packaging_qty",
|
||||
digits="Product Unit of Measure",
|
||||
)
|
||||
|
||||
@api.depends(
|
||||
"product_qty", "product_uom", "product_packaging", "product_packaging.qty"
|
||||
"product_qty", "product_uom", "product_packaging_id", "product_packaging_id.qty"
|
||||
)
|
||||
def _compute_product_packaging_qty(self):
|
||||
for move in self:
|
||||
if (
|
||||
not move.product_packaging
|
||||
not move.product_packaging_id
|
||||
or move.product_qty == 0
|
||||
or move.product_packaging.qty == 0
|
||||
or move.product_packaging_id.qty == 0
|
||||
):
|
||||
move.product_packaging_qty = 0
|
||||
continue
|
||||
@@ -40,60 +33,58 @@ class StockPicking(models.Model):
|
||||
)
|
||||
else:
|
||||
product_qty = move.product_uom_qty
|
||||
move.product_packaging_qty = product_qty / move.product_packaging.qty
|
||||
move.product_packaging_qty = product_qty / move.product_packaging_id.qty
|
||||
|
||||
def _prepare_product_packaging_qty_values(self):
|
||||
return {
|
||||
"product_uom_qty": self.product_packaging.qty * self.product_packaging_qty,
|
||||
"product_uom": self.product_packaging.product_uom_id.id,
|
||||
"product_uom_qty": self.product_packaging_id.qty
|
||||
* self.product_packaging_qty,
|
||||
"product_uom": self.product_packaging_id.product_uom_id.id,
|
||||
}
|
||||
|
||||
def _inverse_product_packaging_qty(self):
|
||||
for move in self:
|
||||
if move.product_packaging_qty and not move.product_packaging:
|
||||
if move.product_packaging_qty and not move.product_packaging_id:
|
||||
raise UserError(
|
||||
_(
|
||||
"You must define a package before setting a quantity "
|
||||
"of said package."
|
||||
)
|
||||
)
|
||||
if move.product_packaging and move.product_packaging.qty == 0:
|
||||
if move.product_packaging_id and move.product_packaging_id.qty == 0:
|
||||
raise UserError(
|
||||
_("Please select a packaging with a quantity bigger than 0")
|
||||
)
|
||||
if move.product_packaging and move.product_packaging_qty:
|
||||
if move.product_packaging_id and move.product_packaging_qty:
|
||||
move.write(move._prepare_product_packaging_qty_values())
|
||||
|
||||
@api.onchange("product_packaging")
|
||||
@api.onchange("product_packaging_id")
|
||||
def _onchange_product_packaging(self):
|
||||
if self.product_packaging:
|
||||
if self.product_packaging_id:
|
||||
self.update(
|
||||
{
|
||||
"product_packaging_qty": 1,
|
||||
"product_uom_qty": self.product_packaging.qty,
|
||||
"product_uom_qty": self.product_packaging_id.qty,
|
||||
"product_uom": self.product_id.uom_id,
|
||||
}
|
||||
)
|
||||
else:
|
||||
self.update({"product_packaging_qty": 0})
|
||||
if self.product_packaging:
|
||||
if self.product_packaging_id:
|
||||
return self._check_package()
|
||||
|
||||
@api.onchange("product_packaging_qty")
|
||||
def _onchange_product_packaging_qty(self):
|
||||
if self.product_packaging_qty and self.product_packaging:
|
||||
if self.product_packaging_qty and self.product_packaging_id:
|
||||
self.update(self._prepare_product_packaging_qty_values())
|
||||
|
||||
@api.onchange("product_uom_qty", "product_uom")
|
||||
def onchange_quantity(self):
|
||||
res = super().onchange_quantity()
|
||||
if not res:
|
||||
res = self._check_package()
|
||||
return res
|
||||
def _onchange_product_uom_check_package(self):
|
||||
return self._check_package()
|
||||
|
||||
def _check_package(self):
|
||||
default_uom = self.product_id.uom_id
|
||||
pack = self.product_packaging
|
||||
pack = self.product_packaging_id
|
||||
qty = self.product_qty
|
||||
q = default_uom._compute_quantity(pack.qty, self.product_uom)
|
||||
if qty and q and round(qty % q, 2):
|
||||
@@ -102,9 +93,15 @@ class StockPicking(models.Model):
|
||||
"warning": {
|
||||
"title": _("Warning"),
|
||||
"message": _(
|
||||
"This product is packaged by %.2f %s. You should use %.2f %s."
|
||||
"This product is packaged by %(old_qty).2f %(old_uom)s. "
|
||||
"You should use %(new_qty).2f %(new_uom)s."
|
||||
)
|
||||
% (pack.qty, default_uom.name, newqty, self.product_uom.name),
|
||||
% {
|
||||
"old_qty": pack.qty,
|
||||
"old_uom": default_uom.name,
|
||||
"new_qty": newqty,
|
||||
"new_uom": self.product_uom.name,
|
||||
},
|
||||
},
|
||||
}
|
||||
return {}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
* Mateu Griful <mateu.griful@forgeflow.com>
|
||||
* Lois Rilo <lois.rilo@forgeflow.com>
|
||||
* Jairo Llopis (`Moduon <https://www.moduon.team/>`__)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# Copyright 2021 ForgeFlow S.L. (https://www.forgeflow.com)
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo.tests import SavepointCase
|
||||
from odoo.tests import Form, TransactionCase, tagged
|
||||
|
||||
|
||||
class TestStockMovePackagingQty(SavepointCase):
|
||||
@tagged("post_install", "-at_install")
|
||||
class TestStockMovePackagingQty(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
@@ -38,9 +39,22 @@ class TestStockMovePackagingQty(SavepointCase):
|
||||
"price_unit": 10.0,
|
||||
}
|
||||
)
|
||||
move.write({"product_packaging": self.packaging.id})
|
||||
move.write({"product_packaging_id": self.packaging.id})
|
||||
move._onchange_product_packaging()
|
||||
self.assertEqual(move.product_uom_qty, 5.0)
|
||||
self.assertEqual(move.product_packaging_qty, 1.0)
|
||||
move.write({"product_packaging_qty": 3.0})
|
||||
self.assertEqual(move.product_uom_qty, 15.0)
|
||||
|
||||
def test_product_uom_qty_change(self):
|
||||
picking_f = Form(self.env["stock.picking"])
|
||||
picking_f.partner_id = self.partner
|
||||
picking_f.picking_type_id = self.env.ref("stock.picking_type_out")
|
||||
with picking_f.move_ids_without_package.new() as move_f:
|
||||
move_f.product_id = self.product
|
||||
self.assertEqual(move_f.product_uom_qty, 1)
|
||||
self.assertEqual(move_f.product_packaging_qty, 0)
|
||||
self.assertFalse(move_f.product_packaging_id)
|
||||
move_f.product_packaging_id = self.packaging
|
||||
self.assertEqual(move_f.product_uom_qty, 5)
|
||||
self.assertEqual(move_f.product_packaging_qty, 1)
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="view_move_extra_tree" model="ir.ui.view">
|
||||
<field name="name">view.move.extra.tree</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_move_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_id" position="after">
|
||||
<field name="product_packaging" />
|
||||
<field name="product_packaging_qty" />
|
||||
</field>
|
||||
<data>
|
||||
<record id="view_move_extra_tree" model="ir.ui.view">
|
||||
<field name="name">view.move.extra.tree</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="inherit_id" ref="stock.view_move_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_packaging_id" position="after">
|
||||
<field name="product_packaging_qty" />
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="stock_picking_view_form_packaging" model="ir.ui.view">
|
||||
<field name="name">stock.picking.form</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath
|
||||
expr="//field[@name='move_ids_without_package']/tree/field[@name='product_uom_qty']"
|
||||
position="before"
|
||||
>
|
||||
<field name="product_packaging" />
|
||||
<field name="product_packaging_qty" />
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
<data>
|
||||
<record id="stock_picking_view_form_packaging" model="ir.ui.view">
|
||||
<field name="name">stock.picking.form</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath
|
||||
expr="//field[@name='move_ids_without_package']/tree/field[@name='product_packaging_id']"
|
||||
position="after"
|
||||
>
|
||||
<field name="product_packaging_qty" />
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
Reference in New Issue
Block a user