146 lines
4.4 KiB
Python
146 lines
4.4 KiB
Python
"""物料选择器 — 读 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=["物料选择"])
|
||
|
||
# 全量展示全部物料类别
|
||
TYPE_FILTER = "1=1"
|
||
|
||
|
||
# ============================================================
|
||
# 响应模型
|
||
# ============================================================
|
||
|
||
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()
|