diff --git a/inventory-backend/app/services/inbound/base_service.py b/inventory-backend/app/services/inbound/base_service.py index de220e8..2551fc4 100644 --- a/inventory-backend/app/services/inbound/base_service.py +++ b/inventory-backend/app/services/inbound/base_service.py @@ -175,47 +175,6 @@ class MaterialBaseService: ).outerjoin(buy_sub, MaterialBase.id == buy_sub.c.base_id) \ .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 过滤即可