Merge PR #2013 into 16.0

Signed-off-by yajo
This commit is contained in:
OCA-git-bot
2024-05-02 10:41:37 +00:00
7 changed files with 224 additions and 31 deletions

View File

@@ -7,7 +7,7 @@ Stock Packaging Qty
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f762cbab1bc1e42ef6e66f92bbd7557223f9c6faa21797ac22edb0e40fedad71
!! source digest: sha256:07cdace5e7277b3685db9d74679a278ea321ae54914c9c32bc9be33a179b7947
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
@@ -85,10 +85,13 @@ promote its widespread use.
.. |maintainer-yajo| image:: https://github.com/yajo.png?size=40px
:target: https://github.com/yajo
:alt: yajo
.. |maintainer-EmilioPascual| image:: https://github.com/EmilioPascual.png?size=40px
:target: https://github.com/EmilioPascual
:alt: EmilioPascual
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-yajo|
|maintainer-yajo| |maintainer-EmilioPascual|
This module is part of the `OCA/stock-logistics-warehouse <https://github.com/OCA/stock-logistics-warehouse/tree/16.0/stock_move_packaging_qty>`_ project on GitHub.

View File

@@ -16,5 +16,5 @@
],
"license": "LGPL-3",
"installable": True,
"maintainers": ["yajo"],
"maintainers": ["yajo", "EmilioPascual"],
}

View File

@@ -2,7 +2,7 @@
# Copyright 2021 ForgeFlow, S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
from odoo import _, api, exceptions, fields, models
from odoo.tools import float_compare
from odoo.tools import float_compare, float_round
class StockMove(models.Model):
@@ -111,12 +111,7 @@ class StockMove(models.Model):
if not line.product_packaging_id:
line.product_packaging_qty_done = 0
continue
line.product_packaging_qty_done = (
line.product_packaging_id._check_qty(
line.qty_done, line.product_uom_id, "DOWN"
)
/ line.product_packaging_id.qty
)
line.product_packaging_qty_done = line.product_packaging_qty_reserved
return result
def _clear_quantities_to_zero(self):
@@ -127,3 +122,63 @@ class StockMove(models.Model):
continue
line.product_packaging_qty_done = 0
return result
def _action_assign(self, force_qty=False):
"""Set the packaging qty reserved when assigning."""
res = super()._action_assign(force_qty=force_qty)
moves_to_assign = self
move_lines_origin = self.env["stock.move.line"].read_group(
[
("move_id", "in", moves_to_assign.mapped("move_orig_ids").ids),
(
"move_id.state",
"not in",
("draft", "waiting", "confirmed", "cancel"),
),
("move_id.product_packaging_id", "!=", False),
],
["qty_done", "product_packaging_qty_done"],
["move_id", "location_dest_id", "lot_id", "result_package_id", "owner_id"],
lazy=False,
)
move_lines_origin_dict = {
(
ml.get("location_dest_id")[0] if ml.get("location_dest_id") else False,
ml.get("lot_id")[0] if ml.get("lot_id") else False,
ml.get("result_package_id")[0]
if ml.get("result_package_id")
else False,
ml.get("owner_id")[0] if ml.get("owner_id") else False,
): {
"qty_done": ml.get("qty_done"),
"product_packaging_qty_done": ml.get("product_packaging_qty_done"),
}
for ml in move_lines_origin
}
for line in moves_to_assign.move_line_ids.filtered("product_packaging_id"):
found_move_lines_origin = move_lines_origin_dict.get(
(
line.location_id.id,
line.lot_id.id,
line.package_id.id,
line.owner_id.id,
),
{},
)
if found_move_lines_origin and found_move_lines_origin.get(
"qty_done"
) == round(
line.reserved_uom_qty,
self.env["decimal.precision"].precision_get("Product Unit of Measure"),
):
line.product_packaging_qty_reserved = found_move_lines_origin.get(
"product_packaging_qty_done"
)
elif not line.product_packaging_id.qty:
continue
else:
line.product_packaging_qty_reserved = float_round(
line.reserved_qty / line.product_packaging_id.qty,
precision_rounding=line.product_packaging_id.product_uom_id.rounding,
)
return res

View File

@@ -1,7 +1,6 @@
# Copyright 2024 Moduon Team S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
from odoo import api, fields, models
from odoo.tools import float_round
from odoo import fields, models
class StockMoveLine(models.Model):
@@ -13,26 +12,12 @@ class StockMoveLine(models.Model):
product_packaging_qty_reserved = fields.Float(
string="Reserved Pkg. Qty.",
help="Product packaging quantity reserved.",
compute="_compute_product_packaging_qty_reserved",
store=True,
)
product_packaging_qty_done = fields.Float(
string="Done Pkg. Qty.",
help="Product packaging quantity done.",
)
@api.depends("product_packaging_id", "reserved_qty")
def _compute_product_packaging_qty_reserved(self):
"""Get the quantity done in product packaging."""
self.product_packaging_qty_reserved = False
for line in self:
if not line.product_packaging_id.qty:
continue
line.product_packaging_qty_reserved = float_round(
line.reserved_qty / line.product_packaging_id.qty,
precision_rounding=line.product_packaging_id.product_uom_id.rounding,
)
def _get_aggregated_properties(self, move_line=False, move=False):
"""Aggregate by product packaging too."""
result = super()._get_aggregated_properties(move_line, move)

View File

@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
@@ -366,7 +367,7 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f762cbab1bc1e42ef6e66f92bbd7557223f9c6faa21797ac22edb0e40fedad71
!! source digest: sha256:07cdace5e7277b3685db9d74679a278ea321ae54914c9c32bc9be33a179b7947
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-warehouse/tree/16.0/stock_move_packaging_qty"><img alt="OCA/stock-logistics-warehouse" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-warehouse-16-0/stock-logistics-warehouse-16-0-stock_move_packaging_qty"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-warehouse&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>Add packaging fields in the stock moves, their lines and their reports.</p>
@@ -424,8 +425,8 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/yajo"><img alt="yajo" src="https://github.com/yajo.png?size=40px" /></a></p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainers</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/yajo"><img alt="yajo" src="https://github.com/yajo.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/EmilioPascual"><img alt="EmilioPascual" src="https://github.com/EmilioPascual.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/16.0/stock_move_packaging_qty">OCA/stock-logistics-warehouse</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>

View File

@@ -33,6 +33,9 @@ class TestStockMovePackagingQty(TransactionCase):
)
cls.customer_location = cls.env.ref("stock.stock_location_customers")
cls.supplier_location = cls.env.ref("stock.stock_location_suppliers")
cls.picking_type_out = cls.env.ref("stock.picking_type_out")
cls.pack_location = cls.env.ref("stock.location_pack_zone")
cls.stock_location = cls.env.ref("stock.stock_location_stock")
def test_product_packaging_qty(self):
move = self.env["stock.move"].create(
@@ -57,7 +60,7 @@ class TestStockMovePackagingQty(TransactionCase):
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")
picking_f.picking_type_id = self.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)
@@ -83,3 +86,142 @@ class TestStockMovePackagingQty(TransactionCase):
],
)
picking.button_validate()
def test_product_packaging_qty_reserved(self):
"""Test that the product packaging quantity reserved is correctly set."""
product_a = self.env["product.product"].create(
{"name": "Product A", "type": "product"}
)
packaging_product_a = self.env["product.packaging"].create(
{"name": "Test packaging", "product_id": product_a.id, "qty": 5.0}
)
self.pack_location.active = True
MoveObj = self.env["stock.move"]
picking_client = self.env["stock.picking"].create(
{
"location_id": self.pack_location.id,
"location_dest_id": self.customer_location.id,
"picking_type_id": self.picking_type_out.id,
}
)
dest = MoveObj.create(
{
"name": product_a.name,
"product_id": product_a.id,
"product_uom_qty": 10,
"product_uom": product_a.uom_id.id,
"picking_id": picking_client.id,
"location_id": self.pack_location.id,
"location_dest_id": self.customer_location.id,
"state": "waiting",
"procure_method": "make_to_order",
"product_packaging_id": packaging_product_a.id,
}
)
picking_pick = self.env["stock.picking"].create(
{
"location_id": self.stock_location.id,
"location_dest_id": self.pack_location.id,
"picking_type_id": self.picking_type_out.id,
}
)
MoveObj.create(
{
"name": product_a.name,
"product_id": product_a.id,
"product_uom_qty": 10,
"product_uom": product_a.uom_id.id,
"picking_id": picking_pick.id,
"location_id": self.stock_location.id,
"location_dest_id": self.pack_location.id,
"move_dest_ids": [(4, dest.id)],
"state": "confirmed",
"product_packaging_id": packaging_product_a.id,
}
)
self.env["stock.quant"]._update_available_quantity(
product_a, self.stock_location, 10
)
picking_pick.action_assign()
self.assertRecordValues(
picking_pick.move_ids_without_package,
[
{
"product_id": product_a.id,
"product_packaging_id": packaging_product_a.id,
"product_packaging_qty": 2,
"product_uom_qty": 10,
"quantity_done": 0,
"product_packaging_qty_done": 0,
}
],
)
self.assertRecordValues(
picking_pick.move_line_ids_without_package,
[
{
"product_id": product_a.id,
"product_packaging_id": packaging_product_a.id,
"reserved_uom_qty": 10,
"product_packaging_qty_reserved": 2,
"qty_done": 0,
"product_packaging_qty_done": 0,
}
],
)
picking_pick.action_set_quantities_to_reservation()
self.assertRecordValues(
picking_pick.move_ids_without_package,
[
{
"product_id": product_a.id,
"product_packaging_id": packaging_product_a.id,
"product_packaging_qty": 2,
"product_uom_qty": 10,
"quantity_done": 10,
"product_packaging_qty_done": 2,
}
],
)
picking_pick._action_done()
picking_client.action_assign()
self.assertRecordValues(
picking_client.move_ids_without_package,
[
{
"product_id": product_a.id,
"product_packaging_id": packaging_product_a.id,
"product_packaging_qty": 2,
"product_uom_qty": 10,
"quantity_done": 0,
"product_packaging_qty_done": 0,
}
],
)
self.assertRecordValues(
picking_client.move_line_ids_without_package,
[
{
"product_id": product_a.id,
"product_packaging_id": packaging_product_a.id,
"reserved_uom_qty": 10,
"product_packaging_qty_reserved": 2,
"qty_done": 0,
"product_packaging_qty_done": 0,
}
],
)
picking_pick.action_set_quantities_to_reservation()
self.assertRecordValues(
picking_pick.move_ids_without_package,
[
{
"product_id": product_a.id,
"product_packaging_id": packaging_product_a.id,
"product_packaging_qty": 2,
"product_uom_qty": 10,
"quantity_done": 10,
"product_packaging_qty_done": 2,
}
],
)

View File

@@ -7,6 +7,13 @@
<field name="model">stock.move.line</field>
<field name="inherit_id" ref="stock.view_stock_move_line_operation_tree" />
<field name="arch" type="xml">
<field name="reserved_uom_qty" position="before">
<field
name="product_packaging_qty_reserved"
attrs="{'invisible': [('product_packaging_id', '=', False)]}"
groups="product.group_stock_packaging"
/>
</field>
<field name="qty_done" position="before">
<field name="product_packaging_id" invisible="1" />
<field