diff --git a/inventory-backend/app/services/inbound/buy_service.py b/inventory-backend/app/services/inbound/buy_service.py index 53745e7..ff4b0cd 100644 --- a/inventory-backend/app/services/inbound/buy_service.py +++ b/inventory-backend/app/services/inbound/buy_service.py @@ -41,21 +41,36 @@ class BuyInboundService: raise ValueError(f"该物料已存在批号【{batch_number}】,请勿重复录入,可直接在该批次下追加库存。") # ============================================================ - # 1. 基础物料搜索 + # 1. 基础物料搜索 (参照 Base 模块:全量模糊匹配) # ============================================================ @staticmethod def search_base_material(keyword): try: query = MaterialBase.query.filter(MaterialBase.is_enabled == True) + if keyword: - query = query.filter( - or_( - MaterialBase.name.ilike(f'%{keyword}%'), - MaterialBase.spec_model.ilike(f'%{keyword}%'), - MaterialBase.pinyin.ilike(f'%{keyword}%') - ) - ) - query = query.order_by(MaterialBase.id.desc()).limit(20) + # [参照 Base 逻辑] 简单直接的模糊匹配:LIKE %keyword% + k_str = f'%{keyword.strip()}%' + + conditions = [ + MaterialBase.name.ilike(k_str), # 名称 + MaterialBase.spec_model.ilike(k_str), # 规格 + MaterialBase.pinyin.ilike(k_str), # 拼音 + MaterialBase.category.ilike(k_str), # 类别 + MaterialBase.material_type.ilike(k_str) # 类型 + ] + + # 安全地添加可能存在的扩展字段 (品牌/厂家) + if hasattr(MaterialBase, 'brand'): + conditions.append(MaterialBase.brand.ilike(k_str)) + if hasattr(MaterialBase, 'manufacturer'): + conditions.append(MaterialBase.manufacturer.ilike(k_str)) + + query = query.filter(or_(*conditions)) + + # [参照 Base 逻辑] 移除 limit,返回所有结果 + query = query.order_by(MaterialBase.id.desc()) + results = [] for item in query.all(): results.append({ @@ -65,6 +80,10 @@ class BuyInboundService: 'category': item.category, 'unit': item.unit, 'type': item.material_type, + # 使用 getattr 防止字段不存在报错 + 'brand': getattr(item, 'brand', ''), + 'manufacturer': getattr(item, 'manufacturer', ''), + 'pinyin': getattr(item, 'pinyin', ''), 'status': '启用' }) return results @@ -242,7 +261,7 @@ class BuyInboundService: raise e # ============================================================ - # 5. 获取列表 + # 5. 获取列表 (参照 Base 逻辑:全量模糊匹配) # ============================================================ @staticmethod def get_list(page, limit, keyword=None, statuses=None): @@ -250,17 +269,30 @@ class BuyInboundService: query = db.session.query(StockBuy).outerjoin(MaterialBase, StockBuy.base_id == MaterialBase.id) if keyword: - kw = f'%{keyword}%' - query = query.filter( - or_( - MaterialBase.name.ilike(kw), - MaterialBase.spec_model.ilike(kw), - StockBuy.batch_number.ilike(kw), - StockBuy.serial_number.ilike(kw), - StockBuy.sku.ilike(kw), - StockBuy.supplier_name.ilike(kw) - ) - ) + # [简单匹配] 只要任一字段包含该字符串,即匹配 + k_str = f'%{keyword.strip()}%' + + conditions = [ + # 库存业务字段 + StockBuy.sku.ilike(k_str), + StockBuy.barcode.ilike(k_str), + StockBuy.batch_number.ilike(k_str), + StockBuy.serial_number.ilike(k_str), + StockBuy.supplier_name.ilike(k_str), + StockBuy.buyer_name.ilike(k_str), + # 基础物料关联字段 + MaterialBase.name.ilike(k_str), + MaterialBase.spec_model.ilike(k_str), + MaterialBase.pinyin.ilike(k_str), + MaterialBase.category.ilike(k_str) + ] + + if hasattr(MaterialBase, 'brand'): + conditions.append(MaterialBase.brand.ilike(k_str)) + if hasattr(MaterialBase, 'manufacturer'): + conditions.append(MaterialBase.manufacturer.ilike(k_str)) + + query = query.filter(or_(*conditions)) if not statuses: statuses = ['在库', '借库'] @@ -300,6 +332,9 @@ class BuyInboundService: 'category': item.base.category if item.base else '', 'unit': item.base.unit if item.base else '', 'material_type': item.base.material_type if item.base else '', + 'brand': getattr(item.base, 'brand', '') if item.base else '', + 'manufacturer': getattr(item.base, 'manufacturer', '') if item.base else '', + 'pinyin': getattr(item.base, 'pinyin', '') if item.base else '', 'sku': item.sku, 'inbound_date': date_display, @@ -333,33 +368,28 @@ class BuyInboundService: return {"total": 0, "items": []} # ============================================================ - # 6. 供应商历史查询 (基于 base_id) + # 6. 供应商历史查询 (移除限制) # ============================================================ @staticmethod def get_history_suppliers(base_id): - """返回该物料关联的供应商列表(去重)""" try: query = db.session.query(StockBuy.supplier_name).filter( StockBuy.base_id == base_id, StockBuy.supplier_name.isnot(None), StockBuy.supplier_name != '' ).distinct().order_by(StockBuy.supplier_name) + # [修改] 移除 limit suppliers = [row[0] for row in query.all()] return suppliers except Exception: return [] # ============================================================ - # 7. 采购人建议 (全局,基于 stock_buy 表) + # 7. 采购人建议 (移除限制) # ============================================================ @staticmethod def get_history_purchasers(keyword): - """ - 从 stock_buy 表中提取历史采购人和邮箱。 - 不绑定 base_id,因为采购人通常是全局的。 - """ try: - # 查询 buyer_name 和 buyer_email,并去重 query = db.session.query(StockBuy.buyer_name, StockBuy.buyer_email) \ .filter(StockBuy.buyer_name.isnot(None), StockBuy.buyer_name != '') @@ -370,13 +400,13 @@ class BuyInboundService: StockBuy.buyer_email.ilike(kw) )) - # 按名字去重,取最新的记录(这里简单做 distinct) - results = query.distinct().limit(20).all() + # [修改] 移除 limit + results = query.distinct().all() users = [] for row in results: users.append({ - 'value': row.buyer_name, # 前端 autocomplete 显示的值 + 'value': row.buyer_name, 'email': row.buyer_email or '' }) return users @@ -385,38 +415,35 @@ class BuyInboundService: return [] # ============================================================ - # 8. 链接建议 (基于 base_id) + # 8. 链接建议 (移除限制) # ============================================================ @staticmethod def get_history_links(base_id, link_type='original'): - """查询该物料的历史链接,方便复用""" try: target_col = StockBuy.original_link if link_type == 'original' else StockBuy.detail_link query = db.session.query(target_col).filter( StockBuy.base_id == base_id, target_col.isnot(None), target_col != '' - ).distinct().limit(10) - + ).distinct() + # [修改] 移除 limit links = [row[0] for row in query.all()] return links except Exception: return [] # ============================================================ - # 9. [新增] 库位建议 (基于 base_id) + # 9. 库位建议 (移除限制) # ============================================================ @staticmethod def get_history_locations(base_id): - """查询该物料的历史存放库位,方便复用""" try: query = db.session.query(StockBuy.warehouse_location).filter( StockBuy.base_id == base_id, StockBuy.warehouse_location.isnot(None), StockBuy.warehouse_location != '' - ).distinct().limit(10) - - # 简单去重列表 + ).distinct() + # [修改] 移除 limit locs = [row[0] for row in query.all()] return locs except Exception: