refactor: rename location restriction helper to public method for RPC access and improve error handling logic
This commit is contained in:
parent
3c2955fb13
commit
c505807aa5
@ -8,9 +8,10 @@ class StockLocation(models.Model):
|
|||||||
_inherit = 'stock.location'
|
_inherit = 'stock.location'
|
||||||
|
|
||||||
@api.model
|
@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 = []
|
allowed_ids = []
|
||||||
source_name = "None"
|
source_name = "None"
|
||||||
@ -34,7 +35,8 @@ class StockLocation(models.Model):
|
|||||||
source_name = f"PT {pt.display_name} (M21)"
|
source_name = f"PT {pt.display_name} (M21)"
|
||||||
|
|
||||||
if allowed_ids:
|
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 allowed_ids
|
||||||
|
|
||||||
return []
|
return []
|
||||||
@ -45,11 +47,10 @@ class StockLot(models.Model):
|
|||||||
@api.model
|
@api.model
|
||||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
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.
|
# 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
|
ctx = self.env.context
|
||||||
if not ctx.get('skip_location_restriction') and ctx.get('uid'):
|
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'))
|
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:
|
if allowed_ids:
|
||||||
quant_domain = [('location_id', 'child_of', allowed_ids), ('quantity', '>', 0), ('lot_id', '!=', False)]
|
quant_domain = [('location_id', 'child_of', allowed_ids), ('quantity', '>', 0), ('lot_id', '!=', False)]
|
||||||
if ctx.get('default_product_id'):
|
if ctx.get('default_product_id'):
|
||||||
@ -65,7 +66,7 @@ class StockLot(models.Model):
|
|||||||
ctx = self.env.context
|
ctx = self.env.context
|
||||||
if not ctx.get('skip_location_restriction') and ctx.get('uid'):
|
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'))
|
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:
|
if allowed_ids:
|
||||||
quant_domain = [('location_id', 'child_of', allowed_ids), ('quantity', '>', 0), ('lot_id', '!=', False)]
|
quant_domain = [('location_id', 'child_of', allowed_ids), ('quantity', '>', 0), ('lot_id', '!=', False)]
|
||||||
if ctx.get('default_product_id'):
|
if ctx.get('default_product_id'):
|
||||||
|
|||||||
@ -12,7 +12,7 @@ patch(SMLX2ManyField.prototype, {
|
|||||||
return super.onAdd({ context, editable });
|
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)
|
// 1. Sync Dirty Data (Internal Odoo Logic)
|
||||||
await this.updateDirtyQuantsData();
|
await this.updateDirtyQuantsData();
|
||||||
@ -22,22 +22,23 @@ patch(SMLX2ManyField.prototype, {
|
|||||||
this.props.context.default_production_id ||
|
this.props.context.default_production_id ||
|
||||||
this.props.record.data.raw_material_production_id?.[0]);
|
this.props.record.data.raw_material_production_id?.[0]);
|
||||||
|
|
||||||
// 3. FETCH Allowed Locations via RPC (The Pure JS Strategy)
|
// 3. FETCH Allowed Locations via PUBLIC RPC (Attempt 18)
|
||||||
// This ensures the browser has the FULL list of IDs from the database before searching.
|
|
||||||
let allowedIds = [];
|
let allowedIds = [];
|
||||||
try {
|
try {
|
||||||
allowedIds = await this.orm.call(
|
allowedIds = await this.orm.call(
|
||||||
"stock.location",
|
"stock.location",
|
||||||
"_get_allowed_locations_for_mo",
|
"get_allowed_locations_for_mo", // Public name (no underscore)
|
||||||
[],
|
[],
|
||||||
{
|
{
|
||||||
mo_id: mo_id,
|
mo_id: mo_id,
|
||||||
picking_type_id: this.props.context.default_picking_type_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) {
|
} 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
|
// 4. Prepare Context
|
||||||
@ -54,7 +55,8 @@ patch(SMLX2ManyField.prototype, {
|
|||||||
const title = _t("Add line: %s", productName);
|
const title = _t("Add line: %s", productName);
|
||||||
|
|
||||||
// 5. Construct Domain (The JS-Only Filter)
|
// 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 = [
|
let domain = [
|
||||||
["product_id", "=", this.props.record.data.product_id.id],
|
["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();
|
domain = Domain.and([domain, [["id", "not in", fullyUsed]]]).toList();
|
||||||
}
|
}
|
||||||
if (notFullyUsed.length) {
|
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();
|
domain = Domain.or([domain, [["id", "in", notFullyUsed]]]).toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user