Initial commit: Odoo 18.0-20251222 extra-addons
This commit is contained in:
6
sale_stock_line_customer_ref/models/__init__.py
Executable file
6
sale_stock_line_customer_ref/models/__init__.py
Executable file
@@ -0,0 +1,6 @@
|
||||
from . import sale_order_line
|
||||
from . import stock_move
|
||||
from . import stock_move_line
|
||||
from . import stock_package_level
|
||||
from . import stock_picking
|
||||
from . import stock_quant_package
|
||||
15
sale_stock_line_customer_ref/models/sale_order_line.py
Executable file
15
sale_stock_line_customer_ref/models/sale_order_line.py
Executable file
@@ -0,0 +1,15 @@
|
||||
# Copyright 2022 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class SaleOrderLine(models.Model):
|
||||
_inherit = "sale.order.line"
|
||||
|
||||
customer_ref = fields.Char(string="Customer Ref.")
|
||||
|
||||
def _prepare_procurement_values(self, group_id=False):
|
||||
values = super()._prepare_procurement_values(group_id)
|
||||
values["customer_ref"] = self.customer_ref
|
||||
return values
|
||||
62
sale_stock_line_customer_ref/models/stock_move.py
Executable file
62
sale_stock_line_customer_ref/models/stock_move.py
Executable file
@@ -0,0 +1,62 @@
|
||||
# Copyright 2022 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
customer_ref_sale_line_id = fields.Many2one(
|
||||
comodel_name="sale.order.line",
|
||||
compute="_compute_customer_ref_sale_line_id",
|
||||
string="Sale Line With Customer Ref.",
|
||||
store=True,
|
||||
index=True,
|
||||
)
|
||||
customer_ref = fields.Char(compute="_compute_customer_ref", store=True)
|
||||
|
||||
@api.depends("sale_line_id.customer_ref", "move_dest_ids.sale_line_id")
|
||||
def _compute_customer_ref_sale_line_id(self):
|
||||
for move in self:
|
||||
sale_line = move._get_customer_ref_sale_line()
|
||||
move.customer_ref_sale_line_id = sale_line
|
||||
|
||||
@api.depends("customer_ref_sale_line_id.customer_ref")
|
||||
def _compute_customer_ref(self):
|
||||
for move in self:
|
||||
move.customer_ref = move.customer_ref_sale_line_id.customer_ref
|
||||
|
||||
def _get_customer_ref_sale_line(self):
|
||||
"""Return the SO line with a customer ref. from the ship move."""
|
||||
self.ensure_one()
|
||||
if self.sale_line_id.customer_ref:
|
||||
return self.sale_line_id
|
||||
if not self.move_dest_ids:
|
||||
return self.sale_line_id.browse()
|
||||
# Search in the destination moves recursively until we find a SO line
|
||||
moves_dest = self.move_dest_ids
|
||||
move_seen_ids = set(moves_dest.ids)
|
||||
while moves_dest:
|
||||
for move_dest in moves_dest:
|
||||
# As soon as the SO line has a customer reference, we break.
|
||||
# That means for pick+pack moves we return the first SO line found.
|
||||
if move_dest.sale_line_id.customer_ref:
|
||||
return move_dest.sale_line_id
|
||||
# Guard to avoid infinite loop. This should not happen.
|
||||
recursion_move_ids = move_seen_ids & set(moves_dest.move_dest_ids.ids)
|
||||
if recursion_move_ids:
|
||||
break
|
||||
moves_dest = moves_dest.move_dest_ids
|
||||
move_seen_ids |= set(moves_dest.ids)
|
||||
return self.sale_line_id.browse()
|
||||
|
||||
@api.model
|
||||
def _prepare_merge_moves_distinct_fields(self):
|
||||
distinct_fields = super()._prepare_merge_moves_distinct_fields()
|
||||
# While ship moves can't be merged together as they are coming from
|
||||
# different SO lines ('sale_line_id' is part of the merge-key in
|
||||
# 'sale_stock'), we allow only the merge of chained moves like
|
||||
# pick+pack based on the customer reference.
|
||||
distinct_fields.append("customer_ref")
|
||||
return distinct_fields
|
||||
48
sale_stock_line_customer_ref/models/stock_move_line.py
Executable file
48
sale_stock_line_customer_ref/models/stock_move_line.py
Executable file
@@ -0,0 +1,48 @@
|
||||
# Copyright 2022 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class StockMoveLine(models.Model):
|
||||
_inherit = "stock.move.line"
|
||||
|
||||
customer_ref = fields.Char(related="move_id.customer_ref")
|
||||
|
||||
def write(self, vals):
|
||||
# Overridden to update related result packages
|
||||
with self.update_related_packages(vals):
|
||||
res = super().write(vals)
|
||||
return res
|
||||
|
||||
@contextmanager
|
||||
def update_related_packages(self, vals):
|
||||
"""Keep packages in sync."""
|
||||
# FIXME: is not granted that all the lines involved
|
||||
# by the pkg will be updated here.
|
||||
# We should look for all lines linked to the same picking and update them all.
|
||||
result_package_updated = "result_package_id" in vals
|
||||
if result_package_updated:
|
||||
old_packages = self.result_package_id
|
||||
yield
|
||||
if result_package_updated:
|
||||
self._update_related_packages(old_packages)
|
||||
|
||||
def _update_related_packages(self, old_packages):
|
||||
# Remove Customer Ref. from packages that are used anymore
|
||||
new_package = self.result_package_id
|
||||
(old_packages - new_package).write(self._update_related_old_pkg_vals())
|
||||
# Collect all Customer Ref. from lines and store them in the package
|
||||
new_package.write(self._update_related_new_pkg_vals())
|
||||
|
||||
def _update_related_old_pkg_vals(self):
|
||||
return {"customer_ref": False}
|
||||
|
||||
def _update_related_new_pkg_vals(self):
|
||||
return {
|
||||
"customer_ref": ", ".join(
|
||||
sorted({x.customer_ref for x in self if x.customer_ref})
|
||||
)
|
||||
}
|
||||
21
sale_stock_line_customer_ref/models/stock_package_level.py
Executable file
21
sale_stock_line_customer_ref/models/stock_package_level.py
Executable file
@@ -0,0 +1,21 @@
|
||||
# Copyright 2022 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockPackageLevel(models.Model):
|
||||
_inherit = "stock.package_level"
|
||||
|
||||
has_customer_ref = fields.Boolean(
|
||||
compute="_compute_has_customer_ref",
|
||||
help="Technical field to display 'Customer Ref' column in a package level.",
|
||||
)
|
||||
|
||||
@api.depends("move_ids.customer_ref")
|
||||
def _compute_has_customer_ref(self):
|
||||
for pl in self:
|
||||
# Break on the first move or line having a customer ref
|
||||
pl.has_customer_ref = next(
|
||||
(move for move in pl.move_ids if move.customer_ref), False
|
||||
) or next((line for line in pl.move_line_ids if line.customer_ref), False)
|
||||
33
sale_stock_line_customer_ref/models/stock_picking.py
Executable file
33
sale_stock_line_customer_ref/models/stock_picking.py
Executable file
@@ -0,0 +1,33 @@
|
||||
# Copyright 2022 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockPicking(models.Model):
|
||||
_inherit = "stock.picking"
|
||||
|
||||
has_customer_ref = fields.Boolean(
|
||||
compute="_compute_has_customer_ref",
|
||||
help="Technical field to display 'Customer Ref' column on moves.",
|
||||
)
|
||||
|
||||
@api.depends("move_ids.customer_ref")
|
||||
def _compute_has_customer_ref(self):
|
||||
for picking in self:
|
||||
# Break on the first move having a customer ref
|
||||
picking.has_customer_ref = next(
|
||||
(
|
||||
move
|
||||
for move in picking.move_ids_without_package
|
||||
if move.customer_ref
|
||||
),
|
||||
False,
|
||||
)
|
||||
|
||||
def action_detailed_operations(self):
|
||||
res = super().action_detailed_operations()
|
||||
ctx = dict(res.get("context", {}))
|
||||
ctx["has_customer_ref"] = self.has_customer_ref
|
||||
res["context"] = ctx
|
||||
return res
|
||||
13
sale_stock_line_customer_ref/models/stock_quant_package.py
Executable file
13
sale_stock_line_customer_ref/models/stock_quant_package.py
Executable file
@@ -0,0 +1,13 @@
|
||||
# Copyright 2022 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class StockQuantPackage(models.Model):
|
||||
_inherit = "stock.quant.package"
|
||||
|
||||
customer_ref = fields.Char(
|
||||
string="Customer Ref.",
|
||||
help="Customer reference coming from the sale order line.",
|
||||
)
|
||||
Reference in New Issue
Block a user