修改采购件对于两个搜索框的bug修复

This commit is contained in:
dxc
2026-02-11 13:39:02 +08:00
parent 5532c87684
commit 5f3ceef3fd
4 changed files with 233 additions and 110 deletions

View File

@ -1,4 +1,3 @@
# app/api/v1/inbound/buy.py
from flask import Blueprint, request, jsonify
from app.services.inbound.buy_service import BuyInboundService
import traceback
@ -7,14 +6,10 @@ inbound_buy_bp = Blueprint('stock_buy', __name__)
# ------------------------------------------------------------------
# 0. 基础物料搜索 (已修改:支持 page 参数)
# 0. 基础物料搜索
# ------------------------------------------------------------------
@inbound_buy_bp.route('/search-base', methods=['GET'])
def search_base():
"""
供前端下拉框远程搜索使用,支持分页
Query Param: keyword (名称或规格), page (默认1)
"""
try:
keyword = request.args.get('keyword', '')
page = request.args.get('page', 1, type=int)
@ -35,7 +30,7 @@ def search_base():
# ------------------------------------------------------------------
# 1. 获取列表
# 1. 获取列表 (修改:接收 category 和 material_type)
# ------------------------------------------------------------------
@inbound_buy_bp.route('/list', methods=['GET'])
def get_list():
@ -44,11 +39,15 @@ def get_list():
limit = request.args.get('pageSize', 15, type=int)
keyword = request.args.get('keyword', '')
# 获取状态列表参数,前端传参格式: statuses=在库,借库
# 新增筛选参数
category = request.args.get('category', '')
material_type = request.args.get('material_type', '')
# 状态参数处理
statuses_str = request.args.get('statuses', '')
statuses = statuses_str.split(',') if statuses_str else []
result = BuyInboundService.get_list(page, limit, keyword, statuses)
result = BuyInboundService.get_list(page, limit, keyword, statuses, category, material_type)
return jsonify({"code": 200, "msg": "success", "data": result})
except Exception as e:
traceback.print_exc()
@ -103,7 +102,19 @@ def delete_buy(id):
# ------------------------------------------------------------------
# 5. 获取关联的出库历史 (如果有)
# 5. [新增] 获取筛选下拉选项 (修复404的关键)
# ------------------------------------------------------------------
@inbound_buy_bp.route('/options', methods=['GET'])
def get_options():
try:
data = BuyInboundService.get_filter_options()
return jsonify({"code": 200, "msg": "success", "data": data})
except Exception as e:
return jsonify({"code": 500, "msg": str(e)}), 500
# ------------------------------------------------------------------
# 6. 获取关联的出库历史 (如果有)
# ------------------------------------------------------------------
@inbound_buy_bp.route('/<int:id>/history', methods=['GET'])
def get_history(id):
@ -112,7 +123,7 @@ def get_history(id):
# ------------------------------------------------------------------
# 6. 供应商建议
# 7. 供应商建议
# ------------------------------------------------------------------
@inbound_buy_bp.route('/suggestions/suppliers', methods=['GET'])
def get_supplier_suggestions():
@ -124,7 +135,7 @@ def get_supplier_suggestions():
# ------------------------------------------------------------------
# 7. 采购人建议 (全局)
# 8. 采购人建议 (全局)
# ------------------------------------------------------------------
@inbound_buy_bp.route('/suggestions/users', methods=['GET'])
def get_user_suggestions():
@ -134,7 +145,7 @@ def get_user_suggestions():
# ------------------------------------------------------------------
# 8. 链接建议
# 9. 链接建议
# ------------------------------------------------------------------
@inbound_buy_bp.route('/suggestions/links', methods=['GET'])
def get_link_suggestions():
@ -147,7 +158,7 @@ def get_link_suggestions():
# ------------------------------------------------------------------
# 9. [新增] 库位建议
# 10. 库位建议
# ------------------------------------------------------------------
@inbound_buy_bp.route('/suggestions/locations', methods=['GET'])
def get_location_suggestions():

View File

@ -10,7 +10,7 @@ import json
class BuyInboundService:
# ============================================================
# 0. 辅助:唯一性校验 (保持不变)
# 0. 辅助:唯一性校验
# ============================================================
@staticmethod
def _check_unique(base_id, serial_number, batch_number, exclude_id=None):
@ -34,34 +34,24 @@ class BuyInboundService:
raise ValueError(f"该物料已存在批号【{batch_number}】,请勿重复录入,可直接在该批次下追加库存。")
# ============================================================
# 1. 基础物料搜索 (修复:逻辑优先级 & 模糊匹配)
# 1. 基础物料搜索
# ============================================================
@staticmethod
def search_base_material(keyword, page=1, limit=50):
try:
# 1. 基础查询:只查询启用的
query = MaterialBase.query.filter(MaterialBase.is_enabled == True)
if keyword:
k = keyword.strip()
k_str = f'%{k}%'
# [核心修复] 使用 and_ 确保逻辑优先级正确
# 生成 SQL 类似: WHERE is_enabled = true AND (name LIKE %k% OR spec LIKE %k% ...)
query = query.filter(and_(
or_(
MaterialBase.name.ilike(k_str), # ilike 忽略大小写
MaterialBase.spec_model.ilike(k_str),
MaterialBase.pinyin.ilike(k_str),
# 如果需要支持 ID 搜索,取消下面注释
# func.cast(MaterialBase.id, String).ilike(k_str)
MaterialBase.name.ilike(k_str),
MaterialBase.spec_model.ilike(k_str)
)
))
# 2. 排序ID 倒序
query = query.order_by(MaterialBase.id.desc())
# 3. 分页
pagination = query.paginate(page=page, per_page=limit, error_out=False)
items = []
@ -90,7 +80,7 @@ class BuyInboundService:
return {"items": [], "total": 0, "page": 1, "has_next": False}
# ============================================================
# 2. 新增入库逻辑 (保持不变)
# 2. 新增入库逻辑
# ============================================================
@staticmethod
def handle_inbound(data):
@ -157,7 +147,7 @@ class BuyInboundService:
raise e
# ============================================================
# 3. 更新入库 (保持不变)
# 3. 更新入库
# ============================================================
@staticmethod
def update_inbound(stock_id, data):
@ -197,7 +187,7 @@ class BuyInboundService:
raise e
# ============================================================
# 4. 删除 (保持不变)
# 4. 删除
# ============================================================
@staticmethod
def delete_inbound(stock_id):
@ -212,21 +202,37 @@ class BuyInboundService:
raise e
# ============================================================
# 5. 获取列表 (保持不变)
# 5. 获取列表
# ============================================================
@staticmethod
def get_list(page, limit, keyword=None, statuses=None):
def get_list(page, limit, keyword=None, statuses=None, category=None, material_type=None):
try:
query = db.session.query(StockBuy).outerjoin(MaterialBase, StockBuy.base_id == MaterialBase.id)
# 1. 通用关键词搜索
if keyword:
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)]
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), # 规格
]
query = query.filter(or_(*conditions))
# 2. 类别独立搜索
if category and category.strip():
query = query.filter(MaterialBase.category == category.strip()) # 下拉框通常是精确匹配
# 3. 类型独立搜索
if material_type and material_type.strip():
query = query.filter(MaterialBase.material_type == material_type.strip()) # 精确匹配
# 4. 状态筛选
if not statuses: statuses = ['在库', '借库']
if '已出库' in statuses:
query = query.filter(StockBuy.status.in_(statuses))
@ -259,7 +265,31 @@ class BuyInboundService:
traceback.print_exc()
return {"total": 0, "items": []}
# 6-9 建议类接口保持不变 (略以节省篇幅,原样保留即可)
# ============================================================
# 6. [新增] 获取筛选选项(类别、类型)
# ============================================================
@staticmethod
def get_filter_options():
try:
# 获取所有非空的类别
categories = db.session.query(MaterialBase.category) \
.filter(MaterialBase.category != None, MaterialBase.category != '') \
.distinct().all()
# 获取所有非空的类型
types = db.session.query(MaterialBase.material_type) \
.filter(MaterialBase.material_type != None, MaterialBase.material_type != '') \
.distinct().all()
return {
"categories": [r[0] for r in categories],
"types": [r[0] for r in types]
}
except Exception:
traceback.print_exc()
return {"categories": [], "types": []}
# 7-10 建议类接口保持不变
@staticmethod
def get_history_suppliers(base_id):
return [r[0] for r in db.session.query(StockBuy.supplier_name).filter(StockBuy.base_id == base_id,