From 4382fd6fc797216dffa4a26c892db438337c9696 Mon Sep 17 00:00:00 2001 From: BernatPForgeFlow Date: Wed, 23 Aug 2023 16:49:03 +0200 Subject: [PATCH] [IMP] stock_buffer_route: Do not consider other locations Buy routes Considering all buy routes should not be the default behaviour. If this is needed should be in a customized module. --- ddmrp/models/stock_buffer.py | 10 +++-- stock_buffer_route/models/__init__.py | 2 + stock_buffer_route/models/mrp_production.py | 42 +++++++++++++++++++++ stock_buffer_route/models/purchase_order.py | 38 +++++++++++++++++++ stock_buffer_route/models/stock_buffer.py | 4 +- 5 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 stock_buffer_route/models/mrp_production.py create mode 100644 stock_buffer_route/models/purchase_order.py diff --git a/ddmrp/models/stock_buffer.py b/ddmrp/models/stock_buffer.py index d71cfa45a..ed480cac8 100644 --- a/ddmrp/models/stock_buffer.py +++ b/ddmrp/models/stock_buffer.py @@ -1667,12 +1667,14 @@ def _calc_incoming_dlt_qty(self): rec.incoming_outside_dlt_qty = sum(outside_dlt_moves.mapped("product_qty")) if rec.item_type == "purchased": cut_date = rec._get_incoming_supply_date_limit() - # FIXME: filter using order_id.state while - # https://github.com/odoo/odoo/pull/58966 is not merged. - # Can be changed in v14. + pols = rec.purchase_line_ids.filtered( + lambda l: l.date_planned <= fields.Datetime.to_datetime(cut_date) + and l.state in ("draft", "sent") + ) + rec.rfq_incoming_dlt_qty = sum(pols.mapped("product_qty")) pols = rec.purchase_line_ids.filtered( lambda l: l.date_planned > fields.Datetime.to_datetime(cut_date) - and l.order_id.state in ("draft", "sent") + and l.state in ("draft", "sent") ) rec.rfq_outside_dlt_qty = sum(pols.mapped("product_qty")) else: diff --git a/stock_buffer_route/models/__init__.py b/stock_buffer_route/models/__init__.py index 46f971b6d..943138d91 100644 --- a/stock_buffer_route/models/__init__.py +++ b/stock_buffer_route/models/__init__.py @@ -1 +1,3 @@ +from . import mrp_production +from . import purchase_order from . import stock_buffer diff --git a/stock_buffer_route/models/mrp_production.py b/stock_buffer_route/models/mrp_production.py new file mode 100644 index 000000000..193551284 --- /dev/null +++ b/stock_buffer_route/models/mrp_production.py @@ -0,0 +1,42 @@ +# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import models + + +class MrpProduction(models.Model): + _inherit = "mrp.production" + + def _get_domain_buffer_link_alternative(self, warehouse_level=False): + self.ensure_one() + if not warehouse_level: + locations = self.env["stock.location"].search( + [("id", "child_of", [self.location_dest_id.id])] + ) + return [ + ("product_id", "=", self.product_id.id), + ("company_id", "=", self.company_id.id), + ("item_type_alternative", "=", "manufactured"), + ("location_id", "in", locations.ids), + ] + else: + return [ + ("product_id", "=", self.product_id.id), + ("company_id", "=", self.company_id.id), + ("item_type_alternative", "=", "manufactured"), + ("warehouse_id", "=", self.picking_type_id.warehouse_id.id), + ] + + def _find_buffer_link(self): + res = super()._find_buffer_link() + buffer_model = self.env["stock.buffer"] + for rec in self.filtered(lambda r: not r.buffer_id): + domain = rec._get_domain_buffer_link_alternative() + buffer = buffer_model.search(domain, limit=1) + if not buffer: + domain = rec._get_domain_buffer_link_alternative(warehouse_level=True) + buffer = buffer_model.search(domain, limit=1) + rec.buffer_id = buffer + if buffer: + rec._calc_execution_priority() + return res diff --git a/stock_buffer_route/models/purchase_order.py b/stock_buffer_route/models/purchase_order.py new file mode 100644 index 000000000..f9bef2465 --- /dev/null +++ b/stock_buffer_route/models/purchase_order.py @@ -0,0 +1,38 @@ +# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import models + + +class PurchaseOrderLine(models.Model): + _inherit = "purchase.order.line" + + def _get_domain_buffer_link_alternative(self): + self.ensure_one() + if not self.product_id: + # Return impossible domain -> no buffer. + return [(0, "=", 1)] + return [ + ("product_id", "=", self.product_id.id), + ("company_id", "=", self.order_id.company_id.id), + ("item_type_alternative", "=", "purchased"), + ("warehouse_id", "=", self.order_id.picking_type_id.warehouse_id.id), + ] + + def _find_buffer_link(self): + res = super()._find_buffer_link() + buffer_model = self.env["stock.buffer"] + move_model = self.env["stock.move"] + for rec in self.filtered(lambda r: not r.buffer_ids): + mto_move = move_model.search( + [("created_purchase_line_id", "=", rec.id)], limit=1 + ) + if mto_move: + # MTO lines are not accounted in MTS stock buffers. + continue + domain = rec._get_domain_buffer_link_alternative() + buffer = buffer_model.search(domain, limit=1) + if buffer: + rec.buffer_ids = buffer + rec._calc_execution_priority() + return res diff --git a/stock_buffer_route/models/stock_buffer.py b/stock_buffer_route/models/stock_buffer.py index 2b3dcbc66..1f63d6acf 100644 --- a/stock_buffer_route/models/stock_buffer.py +++ b/stock_buffer_route/models/stock_buffer.py @@ -21,6 +21,7 @@ class StockBuffer(models.Model): "stock.location.route", string="Allowed routes", compute="_compute_route_ids", + store=True, ) route_id = fields.Many2one( "stock.location.route", @@ -40,7 +41,7 @@ class StockBuffer(models.Model): help="Alternative Decoupled Lead Time (days)", ) - @api.depends("product_id", "warehouse_id", "warehouse_id.route_ids", "location_id") + @api.depends("product_id", "location_id", "product_id.route_ids") def _compute_route_ids(self): route_obj = self.env["stock.location.route"] for record in self: @@ -145,7 +146,6 @@ def _get_location_routes_of_parents(self, routes, parents): ) & parents ) - or any(rule.action == "buy" for rule in route.rule_ids) ) def get_parents(self):