fix: move keyword search filter to outer query to fix outerjoin bypass bug in material list

This commit is contained in:
DXC
2026-03-19 10:42:40 +08:00
parent de887136a3
commit 6596ce2458

View File

@ -176,47 +176,6 @@ class MaterialBaseService:
.outerjoin(semi_sub, MaterialBase.id == semi_sub.c.base_id) \
.outerjoin(prod_sub, MaterialBase.id == prod_sub.c.base_id)
# 关键词精确搜索(需要在子查询层完成)
if filters:
search_field = filters.get('searchField', 'all')
keyword = filters.get('keyword')
if keyword:
kw = f"%{keyword}%"
if search_field == 'name':
inner_sub = inner_sub.filter(MaterialBase.name.ilike(kw))
elif search_field == 'common_name':
inner_sub = inner_sub.filter(MaterialBase.common_name.ilike(kw))
elif search_field == 'spec':
inner_sub = inner_sub.filter(MaterialBase.spec_model.ilike(kw))
else:
inner_sub = inner_sub.filter(or_(
MaterialBase.name.ilike(kw),
MaterialBase.common_name.ilike(kw),
MaterialBase.spec_model.ilike(kw)
))
company = filters.get('company')
if company is not None and company != '':
inner_sub = inner_sub.filter(MaterialBase.company_name.ilike(company.strip()))
category = filters.get('category')
if category is not None and category != '':
inner_sub = inner_sub.filter(MaterialBase.category.ilike(category.strip()))
type_val = filters.get('type')
if type_val is not None and type_val != '':
inner_sub = inner_sub.filter(MaterialBase.material_type.ilike(type_val.strip()))
if filters.get('isEnabled') is not None:
val_str = str(filters['isEnabled']).lower()
is_active = val_str in ['1', 'true', 'yes', 't']
inner_sub = inner_sub.filter(MaterialBase.is_enabled == is_active)
# 库存状态筛选 (has_stock) - 使用子查询列
has_stock = filters.get('has_stock')
if has_stock and str(has_stock).lower() in ['true', '1', 'yes']:
inner_sub = inner_sub.filter(total_inv > 0)
# 将内层子查询具体化
inner_sub = inner_sub.subquery()
@ -231,6 +190,47 @@ class MaterialBaseService:
).outerjoin(inner_sub, MaterialBase.id == inner_sub.c.base_id) \
.outerjoin(MaterialWarningSetting, MaterialBase.id == MaterialWarningSetting.base_id)
# 【修复】关键词搜索必须在主查询上过滤,不能在 inner_sub 上(因为使用了 Outer Join
if filters:
search_field = filters.get('searchField', 'all')
keyword = filters.get('keyword')
if keyword:
kw = f"%{keyword}%"
if search_field == 'name':
query = query.filter(MaterialBase.name.ilike(kw))
elif search_field == 'common_name':
query = query.filter(MaterialBase.common_name.ilike(kw))
elif search_field == 'spec':
query = query.filter(MaterialBase.spec_model.ilike(kw))
else:
query = query.filter(or_(
MaterialBase.name.ilike(kw),
MaterialBase.common_name.ilike(kw),
MaterialBase.spec_model.ilike(kw)
))
company = filters.get('company')
if company is not None and company != '':
query = query.filter(MaterialBase.company_name.ilike(company.strip()))
category = filters.get('category')
if category is not None and category != '':
query = query.filter(MaterialBase.category.ilike(category.strip()))
type_val = filters.get('type')
if type_val is not None and type_val != '':
query = query.filter(MaterialBase.material_type.ilike(type_val.strip()))
if filters.get('isEnabled') is not None:
val_str = str(filters['isEnabled']).lower()
is_active = val_str in ['1', 'true', 'yes', 't']
query = query.filter(MaterialBase.is_enabled == is_active)
# 库存状态筛选 (has_stock) - 使用子查询列
has_stock = filters.get('has_stock')
if has_stock and str(has_stock).lower() in ['true', '1', 'yes']:
query = query.filter(inner_sub.c.total_inv > 0)
# ============================================================
# 【修复3】高级筛选统一使用 WHERE (filter)
# 聚合字段同样是子查询列,直接用 filter 过滤即可