"""物料选择器 — 读 MOM material_base,按成品/半成品 category 手风琴分组""" from fastapi import APIRouter, Query, HTTPException, status from pydantic import BaseModel from app.core.mom_database import MomSessionLocal from sqlalchemy import text router = APIRouter(prefix="/materials", tags=["物料选择"]) # 只展示成品 / 半成品(category 字段区分,如 IRIS/成品/… / IRIS/半成品/…) TYPE_FILTER = "category ILIKE '%成品%' OR category ILIKE '%半成品%'" # ============================================================ # 响应模型 # ============================================================ class MaterialGroup(BaseModel): category: str count: int class MaterialItem(BaseModel): id: int name: str spec: str category: str type: str unit: str is_enabled: bool # ============================================================ # 端点 # ============================================================ @router.get("/groups", response_model=list[MaterialGroup]) def get_material_groups( keyword: str = Query("", description="搜索(按名称/规格)"), ): """ 按 category 分组汇总,前端渲染手风琴外层。 只返回成品/半成品分类。 """ db = MomSessionLocal() try: if keyword.strip(): sql = text( f""" SELECT category, COUNT(*) AS count FROM material_base WHERE is_enabled = TRUE AND ({TYPE_FILTER}) AND (name ILIKE :kw OR spec_model ILIKE :kw) GROUP BY category ORDER BY category """ ) result = db.execute(sql, {"kw": f"%{keyword.strip()}%"}) else: sql = text( f""" SELECT category, COUNT(*) AS count FROM material_base WHERE is_enabled = TRUE AND ({TYPE_FILTER}) GROUP BY category ORDER BY category """ ) result = db.execute(sql) rows = result.fetchall() return [MaterialGroup(category=row.category, count=row.count) for row in rows] except Exception as e: raise HTTPException( status_code=status.HTTP_502_BAD_GATEWAY, detail=f"MOM material_base 查询失败: {str(e)}", ) finally: db.close() @router.get("/items", response_model=list[MaterialItem]) def get_material_items( category: str = Query(..., description="物料分类"), keyword: str = Query("", description="分组内搜索"), limit: int = Query(500, ge=1, le=9999), ): """ 获取指定 category 下的物料条目,前端展开手风琴时懒加载。 """ db = MomSessionLocal() try: if keyword.strip(): sql = text( f""" SELECT id, name, spec_model AS spec, category, material_type AS type, COALESCE(unit, '') AS unit, is_enabled FROM material_base WHERE is_enabled = TRUE AND ({TYPE_FILTER}) AND category = :cat AND (name ILIKE :kw OR spec_model ILIKE :kw) ORDER BY name LIMIT :lim """ ) result = db.execute( sql, {"cat": category, "kw": f"%{keyword.strip()}%", "lim": limit} ) else: sql = text( f""" SELECT id, name, spec_model AS spec, category, material_type AS type, COALESCE(unit, '') AS unit, is_enabled FROM material_base WHERE is_enabled = TRUE AND ({TYPE_FILTER}) AND category = :cat ORDER BY name LIMIT :lim """ ) result = db.execute(sql, {"cat": category, "lim": limit}) rows = result.fetchall() return [ MaterialItem( id=row.id, name=row.name, spec=row.spec, category=row.category, type=row.type, unit=row.unit, is_enabled=row.is_enabled, ) for row in rows ] except Exception as e: raise HTTPException( status_code=status.HTTP_502_BAD_GATEWAY, detail=f"MOM material_base 查询失败: {str(e)}", ) finally: db.close()