stock_restrict_source_location/models/stock_location.py

77 lines
3.9 KiB
Python

import logging
from odoo import api, fields, models, _
from odoo.osv import expression
_logger = logging.getLogger(__name__)
class StockLocation(models.Model):
_inherit = 'stock.location'
@api.model
def _get_allowed_locations_for_mo(self, mo_id=None, picking_type_id=None):
"""
Public helper for JS to fetch allowed locations for a given MO or Picking Type.
"""
allowed_ids = []
source_name = "None"
# 1. MO Lookup (Direct Database Query)
if mo_id:
mo = self.env['mrp.production'].sudo().browse(mo_id)
if mo.exists() and mo.allowed_source_location_ids:
allowed_ids = mo.allowed_source_location_ids.ids
source_name = f"MO {mo.name}"
# 2. Picking Type Fallback
if not allowed_ids and picking_type_id:
pt = self.env['stock.picking.type'].sudo().browse(picking_type_id)
if pt.exists():
if pt.default_location_src_ids:
allowed_ids = pt.default_location_src_ids.ids
source_name = f"PT {pt.display_name}"
elif pt.default_location_src_id:
allowed_ids = [pt.default_location_src_id.id]
source_name = f"PT {pt.display_name} (M21)"
if allowed_ids:
_logger.info(f"DEBUG_RESTRICT: Identified {len(allowed_ids)} Allowed Locations for {source_name}: {allowed_ids}")
return allowed_ids
return []
class StockLot(models.Model):
_inherit = 'stock.lot'
@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):
# We KEEP the Lot search override as it is necessary for the lot dropdown selection.
# This only affects the searching of lots and has no side-effects on Quant creation.
ctx = self.env.context
if not ctx.get('skip_location_restriction') and ctx.get('uid'):
mo_id = (ctx.get('active_mo_id') or ctx.get('default_production_id') or ctx.get('production_id'))
allowed_ids = self.env['stock.location']._get_allowed_locations_for_mo(mo_id=mo_id, picking_type_id=ctx.get('default_picking_type_id'))
if allowed_ids:
quant_domain = [('location_id', 'child_of', allowed_ids), ('quantity', '>', 0), ('lot_id', '!=', False)]
if ctx.get('default_product_id'):
quant_domain.append(('product_id', '=', ctx.get('default_product_id')))
quants = self.env['stock.quant'].with_context(skip_location_restriction=True).sudo().search(quant_domain)
args = expression.AND([args or [], [('id', 'in', quants.mapped('lot_id').ids)]])
return super().name_search(name, args=args, operator=operator, limit=limit)
@api.model
def web_search_read(self, domain, specification, offset=0, limit=None, order=None, count_limit=None):
# We KEEP the Lot search override for the search catalogs as well.
ctx = self.env.context
if not ctx.get('skip_location_restriction') and ctx.get('uid'):
mo_id = (ctx.get('active_mo_id') or ctx.get('default_production_id') or ctx.get('production_id'))
allowed_ids = self.env['stock.location']._get_allowed_locations_for_mo(mo_id=mo_id, picking_type_id=ctx.get('default_picking_type_id'))
if allowed_ids:
quant_domain = [('location_id', 'child_of', allowed_ids), ('quantity', '>', 0), ('lot_id', '!=', False)]
if ctx.get('default_product_id'):
quant_domain.append(('product_id', '=', ctx.get('default_product_id')))
quants = self.env['stock.quant'].with_context(skip_location_restriction=True).sudo().search(quant_domain)
domain = expression.AND([domain, [('id', 'in', quants.mapped('lot_id').ids)]])
return super().web_search_read(domain, specification, offset=offset, limit=limit, order=order, count_limit=count_limit)