mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
185 lines
7.2 KiB
Python
185 lines
7.2 KiB
Python
# Copyright 2020 Camptocamp SA
|
|
# 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, float_round
|
|
|
|
|
|
class StockMove(models.Model):
|
|
_inherit = "stock.move"
|
|
|
|
product_packaging_qty = fields.Float(
|
|
string="Pkgs. Demand",
|
|
compute="_compute_product_packaging_qty",
|
|
inverse="_inverse_product_packaging_qty",
|
|
help="Amount of product packagings demanded.",
|
|
)
|
|
product_packaging_qty_done = fields.Float(
|
|
string="Pkgs. Done",
|
|
compute="_compute_product_packaging_qty_done",
|
|
inverse="_inverse_product_packaging_qty_done",
|
|
help="Amount of product packagings done.",
|
|
)
|
|
|
|
@api.depends(
|
|
"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_id
|
|
or move.product_qty == 0
|
|
or move.product_packaging_id.qty == 0
|
|
):
|
|
move.product_packaging_qty = 0
|
|
continue
|
|
# Consider uom
|
|
move.product_packaging_qty = (
|
|
move.product_uom_qty / move._get_single_package_uom_qty()
|
|
)
|
|
|
|
@api.depends(
|
|
"move_line_ids.product_packaging_qty_done",
|
|
"move_line_nosuggest_ids.product_packaging_qty_done",
|
|
)
|
|
def _compute_product_packaging_qty_done(self):
|
|
"""Get the sum of done packaging qtys from move lines."""
|
|
for move in self:
|
|
lines = move._get_move_lines()
|
|
move.product_packaging_qty_done = sum(
|
|
lines.mapped("product_packaging_qty_done")
|
|
)
|
|
|
|
@api.onchange("product_packaging_qty")
|
|
def _inverse_product_packaging_qty(self):
|
|
"""Store the quantity in the product's UoM.
|
|
|
|
This inverse is also an onchange because otherwise changes are not
|
|
reflected live.
|
|
"""
|
|
for move in self:
|
|
if move.product_packaging_id and move.product_packaging_qty:
|
|
uom_factor = move._get_single_package_uom_qty()
|
|
move.product_uom_qty = move.product_packaging_qty * uom_factor
|
|
|
|
def _inverse_product_packaging_qty_done(self):
|
|
"""Store the done packaging dqty in the move line if there's just one."""
|
|
for move in self:
|
|
lines = move._get_move_lines()
|
|
# Setting 0 done pkgs with no lines? Nothing to do
|
|
if not lines and not move.product_packaging_qty_done:
|
|
continue
|
|
if len(lines) != 1:
|
|
raise exceptions.UserError(
|
|
_(
|
|
"There are %d move lines involved. "
|
|
"Please set their product packaging done qty directly.",
|
|
len(lines),
|
|
)
|
|
)
|
|
lines.product_packaging_qty_done = move.product_packaging_qty_done
|
|
|
|
@api.onchange("product_packaging_id")
|
|
def _onchange_product_packaging(self):
|
|
"""Add a default qty if the packaging has an invalid value."""
|
|
if not self.product_packaging_id:
|
|
self.product_packaging_qty = 0
|
|
return
|
|
self.product_uom_qty = (
|
|
self.product_packaging_id._check_qty(self.product_uom_qty, self.product_uom)
|
|
or self._get_single_package_uom_qty()
|
|
)
|
|
|
|
def _get_single_package_uom_qty(self):
|
|
"""Return the quantity of a single package in the move's UoM."""
|
|
self.ensure_one()
|
|
if not self.product_packaging_id:
|
|
return 0
|
|
return self.product_packaging_id.product_uom_id._compute_quantity(
|
|
self.product_packaging_id.qty, self.product_uom
|
|
)
|
|
|
|
def _set_quantities_to_reservation(self):
|
|
"""Add packaging qtys when clicking on "Set Quantities"."""
|
|
result = super()._set_quantities_to_reservation()
|
|
digits = self.env["stock.move.line"].fields_get(["qty_done"], ["digits"])[
|
|
"qty_done"
|
|
]["digits"][1]
|
|
for line in self.move_line_ids:
|
|
if float_compare(line.qty_done, line.reserved_uom_qty, digits):
|
|
continue
|
|
if not line.product_packaging_id:
|
|
line.product_packaging_qty_done = 0
|
|
continue
|
|
line.product_packaging_qty_done = line.product_packaging_qty_reserved
|
|
return result
|
|
|
|
def _clear_quantities_to_zero(self):
|
|
"""Clear packaging qtys when clicking on "Clear Quantities"."""
|
|
result = super()._clear_quantities_to_zero()
|
|
for line in self.move_line_ids:
|
|
if line.qty_done:
|
|
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
|