From 94ff7cecdc1a063a0ece6178d9b1a553d990b488 Mon Sep 17 00:00:00 2001 From: dxc Date: Tue, 10 Feb 2026 13:51:19 +0800 Subject: [PATCH] feat: add backend autocomplete for suppliers and users in inbound Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) --- inventory-backend/app/api/v1/inbound/buy.py | 24 +++++++++- .../app/api/v1/inbound/product.py | 12 ++++- inventory-backend/app/api/v1/inbound/semi.py | 12 ++++- .../app/api/v1/inbound/service.py | 24 ++++++++++ .../app/services/inbound/buy_service.py | 44 ++++++++++++++++++- .../app/services/inbound/product_service.py | 28 +++++++++++- .../app/services/inbound/semi_service.py | 28 +++++++++++- .../app/services/inbound/service_service.py | 44 ++++++++++++++++++- 8 files changed, 209 insertions(+), 7 deletions(-) diff --git a/inventory-backend/app/api/v1/inbound/buy.py b/inventory-backend/app/api/v1/inbound/buy.py index 948d998..5a2d354 100644 --- a/inventory-backend/app/api/v1/inbound/buy.py +++ b/inventory-backend/app/api/v1/inbound/buy.py @@ -110,4 +110,26 @@ def get_history(id): }) except Exception as e: traceback.print_exc() - return jsonify({"code": 500, "msg": str(e)}), 500 \ No newline at end of file + return jsonify({"code": 500, "msg": str(e)}), 500 + + +# ------------------------------------------------------------------ +# 6. 供应商建议 +# ------------------------------------------------------------------ +@inbound_buy_bp.route('/suggestions/suppliers', methods=['GET']) +def get_supplier_suggestions(): + base_id = request.args.get('base_id', type=int) + if not base_id: + return jsonify({"code": 400, "msg": "base_id required"}), 400 + data = BuyInboundService.get_history_suppliers(base_id) + return jsonify({"code": 200, "msg": "success", "data": data}) + + +# ------------------------------------------------------------------ +# 7. 系统用户建议 +# ------------------------------------------------------------------ +@inbound_buy_bp.route('/suggestions/users', methods=['GET']) +def get_user_suggestions(): + keyword = request.args.get('keyword', '') + data = BuyInboundService.search_system_users(keyword) + return jsonify({"code": 200, "msg": "success", "data": data}) diff --git a/inventory-backend/app/api/v1/inbound/product.py b/inventory-backend/app/api/v1/inbound/product.py index ffae290..091479b 100644 --- a/inventory-backend/app/api/v1/inbound/product.py +++ b/inventory-backend/app/api/v1/inbound/product.py @@ -103,4 +103,14 @@ def get_history(id): return jsonify({"code": 200, "msg": "success", "data": data}) except Exception as e: traceback.print_exc() - return jsonify({"code": 500, "msg": str(e)}), 500 \ No newline at end of file + return jsonify({"code": 500, "msg": str(e)}), 500 + + +# ------------------------------------------------------------------ +# 6. 系统用户建议 +# ------------------------------------------------------------------ +@inbound_product_bp.route('/suggestions/users', methods=['GET']) +def get_user_suggestions(): + keyword = request.args.get('keyword', '') + data = ProductInboundService.search_system_users(keyword) + return jsonify({"code": 200, "msg": "success", "data": data}) diff --git a/inventory-backend/app/api/v1/inbound/semi.py b/inventory-backend/app/api/v1/inbound/semi.py index 9875eb6..1fb2f89 100644 --- a/inventory-backend/app/api/v1/inbound/semi.py +++ b/inventory-backend/app/api/v1/inbound/semi.py @@ -117,4 +117,14 @@ def get_history(id): }) except Exception as e: traceback.print_exc() - return jsonify({"code": 500, "msg": str(e)}), 500 \ No newline at end of file + return jsonify({"code": 500, "msg": str(e)}), 500 + + +# ------------------------------------------------------------------ +# 6. 系统用户建议 +# ------------------------------------------------------------------ +@inbound_semi_bp.route('/suggestions/users', methods=['GET']) +def get_user_suggestions(): + keyword = request.args.get('keyword', '') + data = SemiInboundService.search_system_users(keyword) + return jsonify({"code": 200, "msg": "success", "data": data}) diff --git a/inventory-backend/app/api/v1/inbound/service.py b/inventory-backend/app/api/v1/inbound/service.py index 7ce3034..43df132 100644 --- a/inventory-backend/app/api/v1/inbound/service.py +++ b/inventory-backend/app/api/v1/inbound/service.py @@ -138,3 +138,27 @@ def delete_service(service_id): except Exception as e: current_app.logger.error(f'删除服务权益失败: {str(e)}') return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500 + + +# ------------------------------------------------------------------ +# 供应商建议 +# ------------------------------------------------------------------ +@inbound_bp.route('/service/suggestions/providers', methods=['GET']) +@jwt_required() +def get_provider_suggestions(): + base_id = request.args.get('base_id', type=int) + if not base_id: + return jsonify({'code': 400, 'msg': 'base_id required'}), 400 + data = ServiceService.get_history_providers(base_id) + return jsonify({'code': 200, 'msg': 'success', 'data': data}) + + +# ------------------------------------------------------------------ +# 系统用户建议 +# ------------------------------------------------------------------ +@inbound_bp.route('/service/suggestions/users', methods=['GET']) +@jwt_required() +def get_user_suggestions(): + keyword = request.args.get('keyword', '') + data = ServiceService.search_system_users(keyword) + return jsonify({'code': 200, 'msg': 'success', 'data': data}) diff --git a/inventory-backend/app/services/inbound/buy_service.py b/inventory-backend/app/services/inbound/buy_service.py index 95fd5fb..deab6a1 100644 --- a/inventory-backend/app/services/inbound/buy_service.py +++ b/inventory-backend/app/services/inbound/buy_service.py @@ -351,4 +351,46 @@ class BuyInboundService: return {"total": pagination.total, "items": items} except Exception as e: traceback.print_exc() - return {"total": 0, "items": []} \ No newline at end of file + return {"total": 0, "items": []} + + # ============================================================ + # 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) + ).distinct().order_by(StockBuy.supplier_name) + suppliers = [row[0] for row in query.all()] + return suppliers + except Exception: + return [] + + # ============================================================ + # 7. 系统用户搜索 + # ============================================================ + @staticmethod + def search_system_users(keyword): + """搜索系统用户(活跃状态)""" + from app.models.system import SysUser + try: + query = SysUser.query.filter(SysUser.status == 'active') + if keyword: + kw = f'%{keyword}%' + query = query.filter(db.or_( + SysUser.username.ilike(kw), + SysUser.email.ilike(kw) + )) + query = query.order_by(SysUser.username) + users = [] + for u in query.limit(20).all(): + users.append({ + 'value': u.username, + 'email': u.email + }) + return users + except Exception: + return [] diff --git a/inventory-backend/app/services/inbound/product_service.py b/inventory-backend/app/services/inbound/product_service.py index cd76cb6..ec4b160 100644 --- a/inventory-backend/app/services/inbound/product_service.py +++ b/inventory-backend/app/services/inbound/product_service.py @@ -350,4 +350,30 @@ class ProductInboundService: return {"total": pagination.total, "items": items} except: traceback.print_exc() - return {"total": 0, "items": []} \ No newline at end of file + return {"total": 0, "items": []} + + # ============================================================ + # 7. 系统用户搜索 + # ============================================================ + @staticmethod + def search_system_users(keyword): + """搜索系统用户(活跃状态)""" + from app.models.system import SysUser + try: + query = SysUser.query.filter(SysUser.status == 'active') + if keyword: + kw = f'%{keyword}%' + query = query.filter(db.or_( + SysUser.username.ilike(kw), + SysUser.email.ilike(kw) + )) + query = query.order_by(SysUser.username) + users = [] + for u in query.limit(20).all(): + users.append({ + 'value': u.username, + 'email': u.email + }) + return users + except Exception: + return [] diff --git a/inventory-backend/app/services/inbound/semi_service.py b/inventory-backend/app/services/inbound/semi_service.py index ee7ecc3..fb49896 100644 --- a/inventory-backend/app/services/inbound/semi_service.py +++ b/inventory-backend/app/services/inbound/semi_service.py @@ -452,4 +452,30 @@ class SemiInboundService: except Exception as e: print(f"List Error: {e}") traceback.print_exc() - return {"total": 0, "items": []} \ No newline at end of file + return {"total": 0, "items": []} + + # ============================================================ + # 7. 系统用户搜索 + # ============================================================ + @staticmethod + def search_system_users(keyword): + """搜索系统用户(活跃状态)""" + from app.models.system import SysUser + try: + query = SysUser.query.filter(SysUser.status == 'active') + if keyword: + kw = f'%{keyword}%' + query = query.filter(db.or_( + SysUser.username.ilike(kw), + SysUser.email.ilike(kw) + )) + query = query.order_by(SysUser.username) + users = [] + for u in query.limit(20).all(): + users.append({ + 'value': u.username, + 'email': u.email + }) + return users + except Exception: + return [] diff --git a/inventory-backend/app/services/inbound/service_service.py b/inventory-backend/app/services/inbound/service_service.py index 1fa97e6..8ffe865 100644 --- a/inventory-backend/app/services/inbound/service_service.py +++ b/inventory-backend/app/services/inbound/service_service.py @@ -161,4 +161,46 @@ class ServiceService: 'total': total, 'page': page, 'per_page': per_page - } \ No newline at end of file + } + + # ============================================================ + # 供应商历史查询 + # ============================================================ + @classmethod + def get_history_providers(cls, base_id): + """返回该物料关联的服务商列表(去重)""" + try: + query = db.session.query(StockService.provider_name).filter( + StockService.base_id == base_id, + StockService.provider_name.isnot(None) + ).distinct().order_by(StockService.provider_name) + providers = [row[0] for row in query.all()] + return providers + except Exception: + return [] + + # ============================================================ + # 系统用户搜索 + # ============================================================ + @classmethod + def search_system_users(cls, keyword): + """搜索系统用户(活跃状态)""" + from app.models.system import SysUser + try: + query = SysUser.query.filter(SysUser.status == 'active') + if keyword: + kw = f'%{keyword}%' + query = query.filter(db.or_( + SysUser.username.ilike(kw), + SysUser.email.ilike(kw) + )) + query = query.order_by(SysUser.username) + users = [] + for u in query.limit(20).all(): + users.append({ + 'value': u.username, + 'email': u.email + }) + return users + except Exception: + return []