Files
KCGL/inventory-backend/app/api/v1/common/search.py

100 lines
3.7 KiB
Python

# inventory-backend/app/api/v1/common/search.py
from flask import jsonify, request
from . import common_bp
from app.models import MaterialBase
from app.models.inbound.buy import StockBuy
from app.models.bom import BomTable
from app.extensions import db
@common_bp.route('/global-search', methods=['GET'])
def global_search():
"""
全局聚合搜索接口(多词 AND 模式,无数量限制)
入参: keyword (字符串,支持空格分词,多词必须同时匹配)
搜索范围: 基础物料、采购库、BOM配方
"""
keyword = request.args.get('keyword', request.args.get('q', '')).strip()
keywords = keyword.split()
if not keywords:
return jsonify({"code": 200, "data": []})
merged_list = []
# ── 1. 基础物料 (MaterialBase) ──────────────────────────
# 真实字段: name, common_name, spec_model, category
material_conditions = []
for kw in keywords:
kw_term = f'%{kw}%'
material_conditions.append(
db.or_(
MaterialBase.name.ilike(kw_term),
MaterialBase.common_name.ilike(kw_term),
MaterialBase.spec_model.ilike(kw_term),
MaterialBase.category.ilike(kw_term)
)
)
bases = MaterialBase.query.filter(db.and_(*material_conditions)).all()
for b in bases:
merged_list.append({
"id": b.id,
"type": "material",
"title": b.name,
"subtitle": b.spec_model or b.common_name or '无规格型号',
"badge": "基础物料",
"extra": {"category": b.category or ''}
})
# ── 2. 采购库 (StockBuy) ─────────────────────────────────
# 真实字段: barcode, sku (通过 join 搜索关联的 MaterialBase.name)
stock_conditions = []
for kw in keywords:
kw_term = f'%{kw}%'
stock_conditions.append(
db.or_(
MaterialBase.name.ilike(kw_term),
StockBuy.barcode.ilike(kw_term),
StockBuy.sku.ilike(kw_term)
)
)
stocks = StockBuy.query.join(MaterialBase, StockBuy.base_id == MaterialBase.id).filter(
db.and_(*stock_conditions)
).all()
for s in stocks:
merged_list.append({
"id": s.base_id,
"stock_id": s.id,
"type": "stock_buy",
"title": s.base.name if s.base else '未知物料',
"subtitle": f"条码: {s.barcode or ''} | 库存: {s.stock_quantity}",
"badge": "采购库",
"extra": {"barcode": s.barcode or '', "status": s.status or ''}
})
# ── 3. BOM 配方 (BomTable) ──────────────────────────────
# 真实字段: bom_no, version
bom_conditions = []
for kw in keywords:
kw_term = f'%{kw}%'
bom_conditions.append(
db.or_(
BomTable.bom_no.ilike(kw_term),
BomTable.version.ilike(kw_term)
)
)
boms = BomTable.query.filter(db.and_(*bom_conditions)).all()
for bom in boms:
parent_name = bom.parent.name if bom.parent else ''
merged_list.append({
"id": bom.id,
"bom_no": bom.bom_no,
"type": "bom",
"title": f"{bom.bom_no} ({bom.version})",
"subtitle": f"父件: {parent_name}" if parent_name else f"版本: {bom.version}",
"badge": "配方BOM",
"extra": {"version": bom.version, "parent_id": bom.parent_id}
})
return jsonify({"code": 200, "data": merged_list})