| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- """环境检测 — 检测项维护 + 登记管理 API"""
- from datetime import datetime, time
- from typing import List, Optional
- from fastapi import APIRouter, Depends, Query
- from pydantic import BaseModel, ConfigDict, Field
- from sqlalchemy.orm import Session
- from app.core.data_scope import apply_data_scope
- from app.core.database import get_db
- from app.core.menu_guard import require_admin_or_super_admin, require_menu_code
- from app.core.response import error_response, success_response
- from app.core.utils import parse_datetime
- from app.crud import env_detect_item as item_svc
- from app.crud import env_detect_record as record_svc
- from app.crud.collection_protocol import total_pages
- from app.models.models import BizEnvDetectItem, BizEnvDetectRecord, SysUser
- router = APIRouter(prefix="/web/admin", tags=["环境检测"])
- def _get_tenant_no(db: Session, user: dict) -> str:
- user_id = user.get("user_id")
- if not user_id:
- raise PermissionError("用户身份信息缺失,无法确定租户")
- sys_user = db.query(SysUser).filter(SysUser.id == user_id).first()
- if not sys_user or not sys_user.tenant_no:
- raise PermissionError("用户租户信息缺失")
- return sys_user.tenant_no
- def _get_current_user_id(user: dict) -> str:
- user_id = user.get("user_id")
- if not user_id:
- raise PermissionError("用户身份信息缺失")
- return str(user_id)
- def _page_payload(items: list, total: int, page: int, page_size: int) -> dict:
- return {
- "list": items,
- "total": total,
- "page": page,
- "pageSize": page_size,
- "totalPages": total_pages(total, page_size),
- }
- # ---------- 环境检测项 ----------
- class EnvDetectItemBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- item_code: str = Field(..., alias="itemCode")
- item_name: str = Field(..., alias="itemName")
- status: str = Field("1", alias="status")
- order_num: Optional[int] = Field(None, alias="orderNum")
- remark: Optional[str] = None
- class EnvDetectItemUpdateBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- item_code: Optional[str] = Field(None, alias="itemCode")
- item_name: Optional[str] = Field(None, alias="itemName")
- status: Optional[str] = None
- order_num: Optional[int] = Field(None, alias="orderNum")
- remark: Optional[str] = None
- @router.get("/env-detect-items")
- async def list_env_detect_items(
- page: int = Query(1, ge=1),
- pageSize: int = Query(10, ge=1, le=100),
- keyword: Optional[str] = None,
- status: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:envDetectItem:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- query = db.query(BizEnvDetectItem).filter(
- BizEnvDetectItem.del_flag == 0,
- BizEnvDetectItem.tenant_no == tenant_no,
- )
- kw = (keyword or "").strip()
- if kw:
- from sqlalchemy import or_
- like = f"%{kw}%"
- query = query.filter(
- or_(
- BizEnvDetectItem.item_code.like(like),
- BizEnvDetectItem.item_name.like(like),
- )
- )
- if status:
- query = query.filter(BizEnvDetectItem.status == status)
- query = apply_data_scope(query, BizEnvDetectItem, user, db, tenant_no)
- total = query.count()
- items = (
- query.order_by(BizEnvDetectItem.create_time.desc())
- .offset((page - 1) * pageSize)
- .limit(pageSize)
- .all()
- )
- result_list = [item_svc._row_to_dict(r) for r in items]
- return success_response(_page_payload(result_list, total, page, pageSize))
- except PermissionError as e:
- return error_response(403, str(e))
- except Exception as e:
- return error_response(400, str(e))
- @router.get("/env-detect-items/active")
- async def list_active_env_detect_items(
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:envDetectRecord:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- items = item_svc.list_active_env_detect_items(db, tenant_no)
- return success_response(items)
- except PermissionError as e:
- return error_response(403, str(e))
- except Exception as e:
- return error_response(400, str(e))
- @router.get("/env-detect-items/{row_id}")
- async def get_env_detect_item(
- row_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:envDetectItem:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = item_svc.get_env_detect_item(db, row_id, tenant_no=tenant_no)
- if not obj:
- return error_response(404, "检测项不存在")
- return success_response(item_svc._row_to_dict(obj))
- except PermissionError as e:
- return error_response(403, str(e))
- except Exception as e:
- return error_response(400, str(e))
- @router.post("/env-detect-items")
- async def create_env_detect_item(
- body: EnvDetectItemBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_admin_or_super_admin),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- user_id = _get_current_user_id(user)
- sys_user = db.query(SysUser).filter(SysUser.id == user_id).first()
- dept_id = (sys_user.dept_id or "") if sys_user else ""
- obj = item_svc.create_env_detect_item(
- db,
- item_code=body.item_code,
- item_name=body.item_name,
- status=body.status,
- tenant_no=tenant_no,
- order_num=body.order_num,
- remark=body.remark,
- user_id=user_id,
- create_dept_id=dept_id,
- )
- return success_response(item_svc._row_to_dict(obj))
- except PermissionError as e:
- return error_response(403, str(e))
- except ValueError as e:
- return error_response(400, str(e))
- except Exception as e:
- return error_response(400, str(e))
- @router.put("/env-detect-items/{row_id}")
- async def update_env_detect_item(
- row_id: str,
- body: EnvDetectItemUpdateBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_admin_or_super_admin),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- user_id = _get_current_user_id(user)
- obj = item_svc.update_env_detect_item(
- db,
- row_id,
- item_code=body.item_code,
- item_name=body.item_name,
- status=body.status,
- order_num=body.order_num,
- remark=body.remark,
- user_id=user_id,
- tenant_no=tenant_no,
- )
- return success_response(item_svc._row_to_dict(obj))
- except PermissionError as e:
- return error_response(403, str(e))
- except ValueError as e:
- return error_response(400, str(e))
- except Exception as e:
- return error_response(400, str(e))
- @router.delete("/env-detect-items/{row_id}")
- async def delete_env_detect_item(
- row_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_admin_or_super_admin),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- item_svc.soft_delete_env_detect_item(db, row_id, tenant_no=tenant_no)
- return success_response(None)
- except PermissionError as e:
- return error_response(403, str(e))
- except ValueError as e:
- return error_response(400, str(e))
- except Exception as e:
- return error_response(400, str(e))
- # ---------- 环境检测登记 ----------
- def _parse_detect_date(value: Optional[str]) -> Optional[datetime]:
- s = (value or "").strip()
- if not s:
- return None
- dt = parse_datetime(s)
- if not dt and len(s) >= 10:
- dt = parse_datetime(f"{s[:10]} 00:00:00")
- return dt
- def _parse_detect_date_bound(value: Optional[str], *, end_of_day: bool = False) -> Optional[datetime]:
- dt = _parse_detect_date(value)
- if not dt:
- return None
- s = (value or "").strip()
- if end_of_day and " " not in s:
- return datetime.combine(dt.date(), time(23, 59, 59))
- return dt
- class EnvDetectRecordBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- detect_time: str = Field(..., alias="detectTime")
- result_time: Optional[str] = Field(None, alias="resultTime")
- inspector_ids: List[str] = Field(..., alias="inspectorIds")
- env_detect_item_id: str = Field(..., alias="envDetectItemId")
- result_desc: str = Field(..., alias="resultDesc")
- attachment_urls: Optional[str] = Field(None, alias="attachmentUrls")
- remark: Optional[str] = None
- class EnvDetectRecordUpdateBody(BaseModel):
- model_config = ConfigDict(populate_by_name=True)
- detect_time: Optional[str] = Field(None, alias="detectTime")
- result_time: Optional[str] = Field(None, alias="resultTime")
- inspector_ids: Optional[List[str]] = Field(None, alias="inspectorIds")
- env_detect_item_id: Optional[str] = Field(None, alias="envDetectItemId")
- result_desc: Optional[str] = Field(None, alias="resultDesc")
- attachment_urls: Optional[str] = Field(None, alias="attachmentUrls")
- remark: Optional[str] = None
- @router.get("/env-detect-records")
- async def list_env_detect_records(
- page: int = Query(1, ge=1),
- pageSize: int = Query(10, ge=1, le=100),
- keyword: Optional[str] = None,
- envDetectItemId: Optional[str] = None,
- inspectorId: Optional[str] = None,
- detectTimeStart: Optional[str] = None,
- detectTimeEnd: Optional[str] = None,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:envDetectRecord:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- query = db.query(BizEnvDetectRecord).filter(
- BizEnvDetectRecord.del_flag == 0,
- BizEnvDetectRecord.tenant_no == tenant_no,
- )
- kw = (keyword or "").strip()
- if kw:
- from sqlalchemy import or_
- like = f"%{kw}%"
- query = query.filter(
- or_(
- BizEnvDetectRecord.record_no.like(like),
- BizEnvDetectRecord.inspector_names.like(like),
- BizEnvDetectRecord.result_desc.like(like),
- )
- )
- item_id = (envDetectItemId or "").strip()
- if item_id:
- query = query.filter(BizEnvDetectRecord.env_detect_item_id == item_id)
- insp_id = (inspectorId or "").strip()
- if insp_id:
- from sqlalchemy import func
- query = query.filter(func.find_in_set(insp_id, BizEnvDetectRecord.inspector_ids) > 0)
- dt_start = _parse_detect_date_bound(detectTimeStart, end_of_day=False)
- dt_end = _parse_detect_date_bound(detectTimeEnd, end_of_day=True)
- if dt_start:
- query = query.filter(BizEnvDetectRecord.detect_time >= dt_start)
- if dt_end:
- query = query.filter(BizEnvDetectRecord.detect_time <= dt_end)
- query = apply_data_scope(query, BizEnvDetectRecord, user, db, tenant_no)
- total = query.count()
- items = (
- query.order_by(BizEnvDetectRecord.create_time.desc())
- .offset((page - 1) * pageSize)
- .limit(pageSize)
- .all()
- )
- result_list = [record_svc._row_to_dict(r) for r in items]
- return success_response(_page_payload(result_list, total, page, pageSize))
- except PermissionError as e:
- return error_response(403, str(e))
- except Exception as e:
- return error_response(400, str(e))
- @router.get("/env-detect-records/{row_id}")
- async def get_env_detect_record(
- row_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_menu_code("biz:envDetectRecord:list")),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- obj = record_svc.get_env_detect_record(db, row_id, tenant_no=tenant_no)
- if not obj:
- return error_response(404, "登记记录不存在")
- return success_response(record_svc._row_to_dict(obj))
- except PermissionError as e:
- return error_response(403, str(e))
- except Exception as e:
- return error_response(400, str(e))
- @router.post("/env-detect-records")
- async def create_env_detect_record(
- body: EnvDetectRecordBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_admin_or_super_admin),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- user_id = _get_current_user_id(user)
- sys_user = db.query(SysUser).filter(SysUser.id == user_id).first()
- dept_id = (sys_user.dept_id or "") if sys_user else ""
- detect_time = _parse_detect_date(body.detect_time)
- if not detect_time:
- return error_response(400, "检测日期格式无效")
- result_time = None
- if body.result_time:
- result_time = _parse_detect_date(body.result_time)
- if not result_time:
- return error_response(400, "结果日期格式无效")
- obj = record_svc.create_env_detect_record(
- db,
- detect_time=detect_time,
- result_time=result_time,
- inspector_ids=body.inspector_ids,
- env_detect_item_id=body.env_detect_item_id,
- result_desc=body.result_desc,
- attachment_urls=body.attachment_urls,
- tenant_no=tenant_no,
- remark=body.remark,
- user_id=user_id,
- create_dept_id=dept_id,
- )
- return success_response(record_svc._row_to_dict(obj))
- except PermissionError as e:
- return error_response(403, str(e))
- except ValueError as e:
- return error_response(400, str(e))
- except Exception as e:
- return error_response(400, str(e))
- @router.put("/env-detect-records/{row_id}")
- async def update_env_detect_record(
- row_id: str,
- body: EnvDetectRecordUpdateBody,
- db: Session = Depends(get_db),
- user: dict = Depends(require_admin_or_super_admin),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- user_id = _get_current_user_id(user)
- detect_time = _parse_detect_date(body.detect_time) if body.detect_time else None
- if body.detect_time and not detect_time:
- return error_response(400, "检测日期格式无效")
- update_result_time = "result_time" in body.model_fields_set
- result_time = None
- if update_result_time and body.result_time:
- result_time = _parse_detect_date(body.result_time)
- if not result_time:
- return error_response(400, "结果日期格式无效")
- obj = record_svc.update_env_detect_record(
- db,
- row_id,
- detect_time=detect_time,
- result_time=result_time,
- update_result_time=update_result_time,
- inspector_ids=body.inspector_ids,
- env_detect_item_id=body.env_detect_item_id,
- result_desc=body.result_desc,
- attachment_urls=body.attachment_urls,
- remark=body.remark,
- user_id=user_id,
- tenant_no=tenant_no,
- )
- return success_response(record_svc._row_to_dict(obj))
- except PermissionError as e:
- return error_response(403, str(e))
- except ValueError as e:
- return error_response(400, str(e))
- except Exception as e:
- return error_response(400, str(e))
- @router.delete("/env-detect-records/{row_id}")
- async def delete_env_detect_record(
- row_id: str,
- db: Session = Depends(get_db),
- user: dict = Depends(require_admin_or_super_admin),
- ):
- try:
- tenant_no = _get_tenant_no(db, user)
- record_svc.soft_delete_env_detect_record(db, row_id, tenant_no=tenant_no)
- return success_response(None)
- except PermissionError as e:
- return error_response(403, str(e))
- except ValueError as e:
- return error_response(400, str(e))
- except Exception as e:
- return error_response(400, str(e))
|