chore: fork from IRIS track 供 LICA 部门独立运行

- 复制来源: /home/yueli/track @ 192c8ee (feature/ai-audit-update)
- 组织隔离目标: LICA
- 端口规划: 前端 8030 / 后端 8031 / 数据库 8032
- 已排除 deploy.sh、deploy_full.sh、docker-compose.prod.yml(IRIS 生产发布脚本)
- 已排除工作区未提交改动,取干净的 192c8ee 状态
This commit is contained in:
2026-09-21 15:56:52 +08:00
commit 3286a11bc7
212 changed files with 44060 additions and 0 deletions

View File

@ -0,0 +1,133 @@
"""物料选择器 — 读 MOM material_base按成品/半成品 category 手风琴分组"""
from fastapi import APIRouter, Query, HTTPException, status, Depends
from pydantic import BaseModel
from app.core.mom_database import MomSessionLocal
from app.services.auth_service import get_current_user
from sqlalchemy import text
router = APIRouter(prefix="/materials", tags=["物料选择"])
# ============================================================
# 响应模型
# ============================================================
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="搜索(按名称/规格)"),
current_user: dict = Depends(get_current_user),
):
"""
按 category 分组汇总,前端渲染手风琴外层。
只返回成品/半成品分类。
"""
db = MomSessionLocal()
try:
if keyword.strip():
sql = text("""
SELECT category, COUNT(*) AS count
FROM material_base
WHERE is_enabled = TRUE
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("""
SELECT category, COUNT(*) AS count
FROM material_base
WHERE is_enabled = TRUE
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),
current_user: dict = Depends(get_current_user),
):
"""
获取指定 category 下的物料条目,前端展开手风琴时懒加载。
"""
db = MomSessionLocal()
try:
if keyword.strip():
sql = text("""
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 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("""
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 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()