Files
zkxw/backend/app/api/lab_sample_process.py
T
zlwuandCursor acb81cadd5 feat(qc): 新增实验室样本处理数据台账(4 Tab + 补录 + 导出)
在质检管理下增加按来源×样本类型展示的台账页,聚合接收/生产/质检参数,
补录按实验室入库编码关联,支持 Excel 导出与中文时间格式。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-12 12:11:57 +08:00

139 lines
4.7 KiB
Python

"""实验室样本处理数据台账 API"""
from typing import Any, Dict, Optional
from fastapi import APIRouter, Depends, Query
from pydantic import BaseModel, ConfigDict, Field
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.core.menu_guard import require_menu_code
from app.core.response import error_response, success_response
from app.crud import lab_sample_process as svc
from app.models.models import SysUser
from app.services import lab_sample_process as ledger
router = APIRouter(prefix="/web/admin", tags=["质检管理"])
LIST_MENU = "biz:labSampleProcess:list"
SUPPLEMENT_MENU = "biz:labSampleProcess:supplement"
def _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 _user_id(user: dict) -> str:
uid = user.get("user_id")
if not uid:
raise PermissionError("用户身份信息缺失")
return str(uid)
def _dept_id(user: dict) -> str:
return str(user.get("dept_id") or user.get("create_dept_id") or "")
class SupplementBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
lab_storage_code: str = Field(..., alias="labStorageCode")
reception_source: str = Field(..., alias="receptionSource")
sample_type_name: str = Field(..., alias="sampleTypeName")
payload: Dict[str, Any] = Field(default_factory=dict)
remark: Optional[str] = None
@router.get("/lab-sample-process/list")
def list_lab_sample_process(
tabKey: str = Query(..., description="cell_hsc|donation_hsc|cell_msc|donation_msc"),
page: int = Query(1, ge=1),
pageSize: int = Query(10, ge=1, le=200),
labStorageCode: Optional[str] = Query(None),
motherName: Optional[str] = Query(None),
createTimeStart: Optional[str] = Query(None),
createTimeEnd: Optional[str] = Query(None),
db: Session = Depends(get_db),
user=Depends(require_menu_code(LIST_MENU)),
):
try:
tenant_no = _tenant_no(db, user)
items, total = svc.list_ledger(
db,
tab_key=tabKey,
page=page,
page_size=pageSize,
tenant_no=tenant_no,
lab_storage_code=labStorageCode,
mother_name=motherName,
create_time_start=createTimeStart,
create_time_end=createTimeEnd,
user_info=user,
)
return success_response(
data={
"list": items,
"total": total,
"page": page,
"pageSize": pageSize,
"tabKey": tabKey,
"tabMeta": ledger.TAB_META.get(tabKey),
"supplementKeys": ledger.SUPPLEMENT_KEYS.get(tabKey, []),
}
)
except PermissionError as e:
return error_response(str(e), code=403)
except ValueError as e:
return error_response(str(e))
except Exception as e:
return error_response(f"查询失败:{e}")
@router.get("/lab-sample-process/supplement")
def get_supplement(
labStorageCode: str = Query(...),
db: Session = Depends(get_db),
user=Depends(require_menu_code(LIST_MENU)),
):
try:
tenant_no = _tenant_no(db, user)
data = svc.get_supplement(db, tenant_no=tenant_no, lab_storage_code=labStorageCode)
return success_response(data=data or {"labStorageCode": labStorageCode, "payload": {}})
except PermissionError as e:
return error_response(str(e), code=403)
except Exception as e:
return error_response(f"查询补录失败:{e}")
@router.put("/lab-sample-process/supplement")
def save_supplement(
body: SupplementBody,
db: Session = Depends(get_db),
user=Depends(require_menu_code(SUPPLEMENT_MENU)),
):
try:
tenant_no = _tenant_no(db, user)
data = svc.upsert_supplement(
db,
tenant_no=tenant_no,
user_id=_user_id(user),
dept_id=_dept_id(user),
lab_storage_code=body.lab_storage_code,
reception_source=body.reception_source,
sample_type_name=body.sample_type_name,
payload=body.payload or {},
remark=body.remark,
)
return success_response(data=data, message="补录已保存")
except PermissionError as e:
return error_response(str(e), code=403)
except ValueError as e:
return error_response(str(e))
except Exception as e:
return error_response(f"保存补录失败:{e}")