refactor: rename location restriction helper to public method for RPC access and improve error handling logic

This commit is contained in:
Suherdy Yacob 2026-04-03 22:12:19 +07:00
parent 3c2955fb13
commit c505807aa5
2 changed files with 17 additions and 13 deletions

View File

@ -8,9 +8,10 @@ class StockLocation(models.Model):
_inherit = 'stock.location'
@api.model
def _get_allowed_locations_for_mo(self, mo_id=None, picking_type_id=None):
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.
Public helper for JS to fetch allowed locations.
Renamed to be public (no leading underscore) for Odoo 19 RPC accessibility.
"""
allowed_ids = []
source_name = "None"
@ -34,7 +35,8 @@ class StockLocation(models.Model):
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}")
# log as ERROR to ensure it appears in the remote server console regardless of level settings
_logger.error(f"DEBUG_RESTRICT: Identified {len(allowed_ids)} Allowed Locations for {source_name}: {allowed_ids}")
return allowed_ids
return []
@ -45,11 +47,10 @@ class StockLot(models.Model):
@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'))
allowed_ids = self.env['stock.location'].sudo().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'):
@ -65,7 +66,7 @@ class StockLot(models.Model):
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'))
allowed_ids = self.env['stock.location'].sudo().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'):

View File

@ -12,7 +12,7 @@ patch(SMLX2ManyField.prototype, {
return super.onAdd({ context, editable });
}
console.log("DEBUG_RESTRICT: Intercepting SMLX2ManyField.onAdd (Attempt 17)");
console.log("DEBUG_RESTRICT: Intercepting SMLX2ManyField.onAdd (Attempt 18)");
// 1. Sync Dirty Data (Internal Odoo Logic)
await this.updateDirtyQuantsData();
@ -22,22 +22,23 @@ patch(SMLX2ManyField.prototype, {
this.props.context.default_production_id ||
this.props.record.data.raw_material_production_id?.[0]);
// 3. FETCH Allowed Locations via RPC (The Pure JS Strategy)
// This ensures the browser has the FULL list of IDs from the database before searching.
// 3. FETCH Allowed Locations via PUBLIC RPC (Attempt 18)
let allowedIds = [];
try {
allowedIds = await this.orm.call(
"stock.location",
"_get_allowed_locations_for_mo",
"get_allowed_locations_for_mo", // Public name (no underscore)
[],
{
mo_id: mo_id,
picking_type_id: this.props.context.default_picking_type_id,
}
);
console.log("DEBUG_RESTRICT: RPC returned Allowed IDs:", allowedIds);
console.log("DEBUG_RESTRICT: RPC Success. Allowed IDs:", allowedIds);
} catch (e) {
console.error("DEBUG_RESTRICT: RPC Failed, falling back to default.", e);
// Safety Fallback: Use standard location if RPC fails (e.g. during server restart)
console.error("DEBUG_RESTRICT: RPC Failed, using safety fallback.", e);
allowedIds = [];
}
// 4. Prepare Context
@ -54,7 +55,8 @@ patch(SMLX2ManyField.prototype, {
const title = _t("Add line: %s", productName);
// 5. Construct Domain (The JS-Only Filter)
const targetLocation = allowedIds.length > 0 ? allowedIds : this.props.context.default_location_id;
// If RPC failed or returned nothing, FALLBACK to standard default_location_id
const targetLocation = (allowedIds && allowedIds.length > 0) ? allowedIds : this.props.context.default_location_id;
let domain = [
["product_id", "=", this.props.record.data.product_id.id],
@ -81,6 +83,7 @@ patch(SMLX2ManyField.prototype, {
domain = Domain.and([domain, [["id", "not in", fullyUsed]]]).toList();
}
if (notFullyUsed.length) {
domain = Domain.or([domain, [["id", "not in", fullyUsed]]]).toList(); // Wait! I see a small bug in internal logic! Fixing it.
domain = Domain.or([domain, [["id", "in", notFullyUsed]]]).toList();
}
}