Files
Odoo-18.0-20251222/sale_procurement_group_by_line/model/sale.py
tocmo0nlord adbe430761
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled
Initial commit: Odoo 18.0-20251222 extra-addons
2026-03-13 20:43:25 +00:00

119 lines
4.7 KiB
Python
Executable File

# Copyright 2013-2014 Camptocamp SA - Guewen Baconnier
# © 2016-20 ForgeFlow S.L. (https://www.forgeflow.com)
# © 2016 Serpent Consulting Services Pvt. Ltd.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
from odoo.tools.float_utils import float_compare
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
procurement_group_id = fields.Many2one(
"procurement.group", "Procurement group", copy=False
)
def _get_procurement_group(self):
super()._get_procurement_group()
return self.procurement_group_id or False
def _get_procurement_group_key(self):
"""Return a key with priority to be used to regroup lines in multiple
procurement groups
"""
return 8, self.order_id.id
def _action_launch_stock_rule(self, previous_product_uom_qty=False):
"""
Launch procurement group run method.
"""
if self._context.get("skip_procurement"):
return True
precision = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
)
procurements = []
groups = {}
if not previous_product_uom_qty:
previous_product_uom_qty = {}
for line in self:
line = line.with_company(line.company_id)
if (
line.state != "sale"
or line.order_id.locked
or line.product_id.type != "consu"
):
continue
qty = line._get_qty_procurement(previous_product_uom_qty) or 0.0
if (
float_compare(qty, line.product_uom_qty, precision_digits=precision)
== 0
):
continue
group_id = line._get_procurement_group()
# Group the sales order lines with same procurement group
# according to the group key
for order_line in line.order_id.order_line:
g_id = order_line.procurement_group_id or False
if g_id:
groups[order_line._get_procurement_group_key()] = g_id
if not group_id:
group_id = groups.get(line._get_procurement_group_key())
if not group_id:
vals = line._prepare_procurement_group_vals()
group_id = self.env["procurement.group"].create(vals)
else:
# In case the procurement group is already created and the
# order was cancelled, we need to update certain values
# of the group.
updated_vals = {}
if group_id.partner_id != line.order_id.partner_shipping_id:
updated_vals.update(
{"partner_id": line.order_id.partner_shipping_id.id}
)
if group_id.move_type != line.order_id.picking_policy:
updated_vals.update({"move_type": line.order_id.picking_policy})
if updated_vals:
group_id.write(updated_vals)
line.procurement_group_id = group_id
values = line._prepare_procurement_values(group_id=group_id)
product_qty = line.product_uom_qty - qty
line_uom = line.product_uom
quant_uom = line.product_id.uom_id
origin = (
f"{line.order_id.name} - {line.order_id.client_order_ref}"
if line.order_id.client_order_ref
else line.order_id.name
)
product_qty, procurement_uom = line_uom._adjust_uom_quantities(
product_qty, quant_uom
)
procurements += line._create_procurements(
product_qty, procurement_uom, origin, values
)
# We store the procured quantity in the UoM of the line to avoid
# duplicated procurements, specially for dropshipping and kits.
previous_product_uom_qty[line.id] = line.product_uom_qty
if procurements:
self.env["procurement.group"].run(procurements)
# This next block is currently needed only because the scheduler trigger is done
# by picking confirmation rather than stock.move confirmation
orders = self.mapped("order_id")
for order in orders:
pickings_to_confirm = order.picking_ids.filtered(
lambda p: p.state not in ["cancel", "done"]
)
if pickings_to_confirm:
# Trigger the Scheduler for Pickings
pickings_to_confirm.action_confirm()
return super(
SaleOrderLine, self.with_context(sale_group_by_line=True)
)._action_launch_stock_rule(previous_product_uom_qty=previous_product_uom_qty)