Files
zkxw/backend/app/crud/pilot_checkup.py
T
2026-05-28 13:05:46 +08:00

957 lines
31 KiB
Python

"""中试申请单-体检 CRUD(体检信息、预约项目、实际项目)"""
from __future__ import annotations
import uuid
from datetime import datetime
from typing import Any, Dict, List, Optional
from sqlalchemy import func, or_
from sqlalchemy.orm import Session
from app.models.models import (
BizCheckupInstitution,
BizPilotApplication,
BizPilotCheckup,
BizPilotCheckupActualItem,
BizPilotCheckupReserveItem,
BizPilotPatient,
)
# ────────────────────────────────────────────
# Helpers
# ────────────────────────────────────────────
def _parse_optional_datetime(val: Any) -> Optional[datetime]:
if val is None or val == "":
return None
if isinstance(val, datetime):
return val
if isinstance(val, str):
text = val.strip()
for fmt in ("%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M"):
try:
return datetime.strptime(text, fmt)
except ValueError:
continue
try:
return datetime.fromisoformat(text.replace("Z", "+00:00"))
except ValueError:
return None
return None
# ────────────────────────────────────────────
# Helpers: _row_to_dict
# ────────────────────────────────────────────
def _generate_checkup_no(db: Session, tenant_no: str) -> str:
today_str = datetime.now().strftime("%Y%m%d")
prefix = f"ZSTJ{today_str}"
existing = (
db.query(BizPilotCheckup.checkup_status)
.filter(
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.id.like(f"{prefix}%"),
BizPilotCheckup.del_flag == 0,
)
.order_by(BizPilotCheckup.create_time.desc())
.first()
)
seq = 1
if existing:
seq = 1
return f"{prefix}{seq:04d}"
def _row_to_dict_checkup(row, db=None, tenant_no=None) -> Dict[str, Any]:
d: Dict[str, Any] = {
"id": row.id,
"pilotApplicationId": row.pilot_application_id or "",
"pilotPatientId": row.pilot_patient_id or "",
"checkupInstitutionId": row.checkup_institution_id or "",
"reserveTime": row.reserve_time.strftime("%Y-%m-%d %H:%M:%S") if row.reserve_time else "",
"reserveFee": float(row.reserve_fee) if row.reserve_fee is not None else None,
"actualCheckupTime": row.actual_checkup_time.strftime("%Y-%m-%d %H:%M:%S") if row.actual_checkup_time else "",
"actualCheckupFee": float(row.actual_checkup_fee) if row.actual_checkup_fee is not None else None,
"feeSettled": row.fee_settled if row.fee_settled is not None else 0,
"checkupStatus": row.checkup_status or "",
"feeStatus": row.fee_status or "",
"checkupRemark": row.checkup_remark or "",
"reportAttachments": row.report_attachments or "",
"tenantNo": row.tenant_no or "",
"remark": row.remark or "",
"createBy": row.create_by or "",
"createTime": row.create_time.strftime("%Y-%m-%d %H:%M:%S") if row.create_time else "",
"updateTime": row.update_time.strftime("%Y-%m-%d %H:%M:%S") if row.update_time else "",
}
if db and tenant_no:
# institutionName — lookup from BizCheckupInstitution
if row.checkup_institution_id:
inst = (
db.query(BizCheckupInstitution.institution_name)
.filter(
BizCheckupInstitution.id == row.checkup_institution_id,
BizCheckupInstitution.del_flag == 0,
)
.first()
)
d["institutionName"] = inst.institution_name if inst else ""
else:
d["institutionName"] = ""
# patientName / sex / age / phoneNo — from BizPilotPatient
if row.pilot_patient_id:
patient = (
db.query(BizPilotPatient)
.filter(
BizPilotPatient.id == row.pilot_patient_id,
BizPilotPatient.del_flag == 0,
)
.first()
)
if patient:
d["patientName"] = patient.patient_name or ""
d["sex"] = patient.sex or ""
d["age"] = patient.age
d["phoneNo"] = patient.phone_no or ""
else:
d["patientName"] = ""
d["sex"] = ""
d["age"] = None
d["phoneNo"] = ""
else:
d["patientName"] = ""
d["sex"] = ""
d["age"] = None
d["phoneNo"] = ""
# applicationNo / channelName — from BizPilotApplication
if row.pilot_application_id:
app = (
db.query(BizPilotApplication)
.filter(
BizPilotApplication.id == row.pilot_application_id,
BizPilotApplication.del_flag == 0,
)
.first()
)
if app:
d["applicationNo"] = app.application_no or ""
d["channelName"] = app.channel_name or ""
else:
d["applicationNo"] = ""
d["channelName"] = ""
else:
d["applicationNo"] = ""
d["channelName"] = ""
# reserveItemCount
reserve_count = (
db.query(func.count(BizPilotCheckupReserveItem.id))
.filter(
BizPilotCheckupReserveItem.pilot_checkup_id == row.id,
BizPilotCheckupReserveItem.tenant_no == tenant_no,
BizPilotCheckupReserveItem.del_flag == 0,
)
.scalar()
) or 0
d["reserveItemCount"] = reserve_count
# actualItemCount
actual_count = (
db.query(func.count(BizPilotCheckupActualItem.id))
.filter(
BizPilotCheckupActualItem.pilot_checkup_id == row.id,
BizPilotCheckupActualItem.tenant_no == tenant_no,
BizPilotCheckupActualItem.del_flag == 0,
)
.scalar()
) or 0
d["actualItemCount"] = actual_count
return d
def _row_to_dict_reserve_item(row) -> Dict[str, Any]:
return {
"id": row.id,
"pilotCheckupId": row.pilot_checkup_id or "",
"projectName": row.project_name or "",
"projectFee": float(row.project_fee) if row.project_fee is not None else None,
"orderNum": row.order_num if row.order_num is not None else 0,
"remark": row.remark or "",
"createTime": row.create_time.strftime("%Y-%m-%d %H:%M:%S") if row.create_time else "",
"updateTime": row.update_time.strftime("%Y-%m-%d %H:%M:%S") if row.update_time else "",
}
def _row_to_dict_actual_item(row) -> Dict[str, Any]:
return {
"id": row.id,
"pilotCheckupId": row.pilot_checkup_id or "",
"projectName": row.project_name or "",
"projectFee": float(row.project_fee) if row.project_fee is not None else None,
"orderNum": row.order_num if row.order_num is not None else 0,
"remark": row.remark or "",
"createTime": row.create_time.strftime("%Y-%m-%d %H:%M:%S") if row.create_time else "",
"updateTime": row.update_time.strftime("%Y-%m-%d %H:%M:%S") if row.update_time else "",
}
# ────────────────────────────────────────────
# Checkup CRUD
# ────────────────────────────────────────────
def get_checkup_by_application(
db: Session, application_id: str, tenant_no: str
) -> Optional[Dict[str, Any]]:
row = (
db.query(BizPilotCheckup)
.filter(
BizPilotCheckup.pilot_application_id == application_id,
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
)
.first()
)
if not row:
return None
return _row_to_dict_checkup(row, db, tenant_no)
def get_checkup_by_id(
db: Session, checkup_id: str, tenant_no: str
) -> Optional[Dict[str, Any]]:
row = (
db.query(BizPilotCheckup)
.filter(
BizPilotCheckup.id == checkup_id,
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
)
.first()
)
if not row:
return None
return _row_to_dict_checkup(row, db, tenant_no)
def create_checkup(
db: Session,
application_id: str,
data: dict,
tenant_no: str,
user_id: str,
) -> Dict[str, Any]:
now = datetime.now()
row = BizPilotCheckup(
id=uuid.uuid4().hex,
pilot_application_id=application_id,
pilot_patient_id=data.get("pilotPatientId") or None,
checkup_institution_id=data.get("checkupInstitutionId") or "",
reserve_time=_parse_optional_datetime(data.get("reserveTime")),
reserve_fee=data.get("reserveFee") if data.get("reserveFee") is not None else None,
actual_checkup_time=data.get("actualCheckupTime") or None,
actual_checkup_fee=data.get("actualCheckupFee") if data.get("actualCheckupFee") is not None else None,
fee_settled=0,
checkup_status="dtj",
fee_status="wjs",
checkup_remark=data.get("checkupRemark") or "",
report_attachments=data.get("reportAttachments") or "",
tenant_no=tenant_no,
order_num=0,
remark=data.get("remark") or "",
create_by=user_id,
create_dept_id="",
create_time=now,
update_by=user_id,
update_time=now,
del_flag=0,
)
db.add(row)
db.commit()
db.refresh(row)
return _row_to_dict_checkup(row, db, tenant_no)
def update_checkup(
db: Session, checkup_id: str, data: dict, tenant_no: str
) -> Dict[str, Any]:
row = (
db.query(BizPilotCheckup)
.filter(
BizPilotCheckup.id == checkup_id,
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
)
.first()
)
if not row:
raise ValueError("体检信息不存在")
fields = {
"checkupInstitutionId": "checkup_institution_id",
"reserveTime": "reserve_time",
"reserveFee": "reserve_fee",
"actualCheckupTime": "actual_checkup_time",
"actualCheckupFee": "actual_checkup_fee",
"checkupRemark": "checkup_remark",
"reportAttachments": "report_attachments",
"remark": "remark",
}
for camel, snake in fields.items():
if camel in data and data[camel] is not None:
val = data[camel]
if snake in ("reserve_time", "actual_checkup_time"):
val = _parse_optional_datetime(val)
setattr(row, snake, val)
row.update_time = datetime.now()
db.commit()
db.refresh(row)
return _row_to_dict_checkup(row, db, tenant_no)
def soft_delete_checkup(db: Session, checkup_id: str, tenant_no: str) -> None:
now = datetime.now()
row = (
db.query(BizPilotCheckup)
.filter(
BizPilotCheckup.id == checkup_id,
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
)
.first()
)
if not row:
raise ValueError("体检信息不存在")
row.del_flag = 1
row.update_time = now
# Cascade soft-delete to reserve items
db.query(BizPilotCheckupReserveItem).filter(
BizPilotCheckupReserveItem.pilot_checkup_id == checkup_id,
BizPilotCheckupReserveItem.tenant_no == tenant_no,
BizPilotCheckupReserveItem.del_flag == 0,
).update({"del_flag": 1, "update_time": now}, synchronize_session=False)
# Cascade soft-delete to actual items
db.query(BizPilotCheckupActualItem).filter(
BizPilotCheckupActualItem.pilot_checkup_id == checkup_id,
BizPilotCheckupActualItem.tenant_no == tenant_no,
BizPilotCheckupActualItem.del_flag == 0,
).update({"del_flag": 1, "update_time": now}, synchronize_session=False)
db.commit()
def mark_checkup_checked(
db: Session, checkup_id: str, tenant_no: str, user_id: str
) -> Dict[str, Any]:
row = (
db.query(BizPilotCheckup)
.filter(
BizPilotCheckup.id == checkup_id,
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
)
.first()
)
if not row:
raise ValueError("体检信息不存在")
if row.checkup_status != "dtj":
raise ValueError("当前状态不允许标记已体检")
row.checkup_status = "ytj"
if not row.actual_checkup_time:
row.actual_checkup_time = datetime.now()
row.update_by = user_id
row.update_time = datetime.now()
db.commit()
db.refresh(row)
return _row_to_dict_checkup(row, db, tenant_no)
def settle_checkup_fee(
db: Session, checkup_id: str, tenant_no: str, user_id: str
) -> Dict[str, Any]:
row = (
db.query(BizPilotCheckup)
.filter(
BizPilotCheckup.id == checkup_id,
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
)
.first()
)
if not row:
raise ValueError("体检信息不存在")
if row.fee_status != "wjs":
raise ValueError("当前状态不允许结算")
row.fee_status = "yjs"
row.fee_settled = 1
row.update_by = user_id
row.update_time = datetime.now()
db.commit()
db.refresh(row)
return _row_to_dict_checkup(row, db, tenant_no)
# ────────────────────────────────────────────
# Reserve Items CRUD
# ────────────────────────────────────────────
def list_reserve_items(
db: Session, checkup_id: str, tenant_no: str
) -> List[Dict[str, Any]]:
rows = (
db.query(BizPilotCheckupReserveItem)
.filter(
BizPilotCheckupReserveItem.pilot_checkup_id == checkup_id,
BizPilotCheckupReserveItem.tenant_no == tenant_no,
BizPilotCheckupReserveItem.del_flag == 0,
)
.order_by(
BizPilotCheckupReserveItem.order_num.asc(),
BizPilotCheckupReserveItem.create_time.asc(),
)
.all()
)
return [_row_to_dict_reserve_item(r) for r in rows]
def save_reserve_items(
db: Session,
checkup_id: str,
items_json: list,
tenant_no: str,
user_id: str,
) -> List[Dict[str, Any]]:
now = datetime.now()
# Soft-delete existing items
db.query(BizPilotCheckupReserveItem).filter(
BizPilotCheckupReserveItem.pilot_checkup_id == checkup_id,
BizPilotCheckupReserveItem.tenant_no == tenant_no,
BizPilotCheckupReserveItem.del_flag == 0,
).update({"del_flag": 1, "update_time": now}, synchronize_session=False)
# Insert new items
for idx, item in enumerate(items_json):
row = BizPilotCheckupReserveItem(
id=uuid.uuid4().hex,
pilot_checkup_id=checkup_id,
project_name=item.get("projectName") or item.get("project_name") or "",
project_fee=item.get("projectFee") if item.get("projectFee") is not None else (
item.get("project_fee") if item.get("project_fee") is not None else None
),
tenant_no=tenant_no,
order_num=idx + 1,
remark=item.get("remark") or "",
create_by=user_id,
create_dept_id="",
create_time=now,
update_by=user_id,
update_time=now,
del_flag=0,
)
db.add(row)
db.commit()
return list_reserve_items(db, checkup_id, tenant_no)
def delete_reserve_item(db: Session, item_id: str, tenant_no: str) -> None:
row = (
db.query(BizPilotCheckupReserveItem)
.filter(
BizPilotCheckupReserveItem.id == item_id,
BizPilotCheckupReserveItem.tenant_no == tenant_no,
BizPilotCheckupReserveItem.del_flag == 0,
)
.first()
)
if not row:
raise ValueError("预约项目不存在")
row.del_flag = 1
row.update_time = datetime.now()
db.commit()
# ────────────────────────────────────────────
# Actual Items CRUD
# ────────────────────────────────────────────
def list_actual_items(
db: Session, checkup_id: str, tenant_no: str
) -> List[Dict[str, Any]]:
rows = (
db.query(BizPilotCheckupActualItem)
.filter(
BizPilotCheckupActualItem.pilot_checkup_id == checkup_id,
BizPilotCheckupActualItem.tenant_no == tenant_no,
BizPilotCheckupActualItem.del_flag == 0,
)
.order_by(
BizPilotCheckupActualItem.order_num.asc(),
BizPilotCheckupActualItem.create_time.asc(),
)
.all()
)
return [_row_to_dict_actual_item(r) for r in rows]
def save_actual_items(
db: Session,
checkup_id: str,
items_json: list,
tenant_no: str,
user_id: str,
) -> List[Dict[str, Any]]:
now = datetime.now()
# Soft-delete existing items
db.query(BizPilotCheckupActualItem).filter(
BizPilotCheckupActualItem.pilot_checkup_id == checkup_id,
BizPilotCheckupActualItem.tenant_no == tenant_no,
BizPilotCheckupActualItem.del_flag == 0,
).update({"del_flag": 1, "update_time": now}, synchronize_session=False)
# Insert new items
for idx, item in enumerate(items_json):
row = BizPilotCheckupActualItem(
id=uuid.uuid4().hex,
pilot_checkup_id=checkup_id,
project_name=item.get("projectName") or item.get("project_name") or "",
project_fee=item.get("projectFee") if item.get("projectFee") is not None else (
item.get("project_fee") if item.get("project_fee") is not None else None
),
tenant_no=tenant_no,
order_num=idx + 1,
remark=item.get("remark") or "",
create_by=user_id,
create_dept_id="",
create_time=now,
update_by=user_id,
update_time=now,
del_flag=0,
)
db.add(row)
db.commit()
return list_actual_items(db, checkup_id, tenant_no)
def delete_actual_item(db: Session, item_id: str, tenant_no: str) -> None:
row = (
db.query(BizPilotCheckupActualItem)
.filter(
BizPilotCheckupActualItem.id == item_id,
BizPilotCheckupActualItem.tenant_no == tenant_no,
BizPilotCheckupActualItem.del_flag == 0,
)
.first()
)
if not row:
raise ValueError("实际项目不存在")
row.del_flag = 1
row.update_time = datetime.now()
db.commit()
# ────────────────────────────────────────────
# Checkup List (Paginated)
# ────────────────────────────────────────────
def list_checkups_paginated(
db: Session,
tenant_no: str,
page: int = 1,
page_size: int = 10,
checkup_status: Optional[str] = None,
fee_status: Optional[str] = None,
checkup_institution_id: Optional[str] = None,
keyword: Optional[str] = None,
application_no: Optional[str] = None,
patient_name: Optional[str] = None,
channel_id: Optional[str] = None,
biz_type: Optional[str] = None,
) -> Dict[str, Any]:
q = db.query(BizPilotCheckup).filter(
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
)
if biz_type:
app_subq = (
db.query(BizPilotApplication.id)
.filter(
BizPilotApplication.biz_type == biz_type,
BizPilotApplication.del_flag == 0,
)
.subquery()
)
q = q.filter(BizPilotCheckup.pilot_application_id.in_(app_subq))
if checkup_status:
statuses = [s.strip() for s in checkup_status.split(",") if s.strip()]
if statuses:
q = q.filter(BizPilotCheckup.checkup_status.in_(statuses))
if fee_status:
statuses = [s.strip() for s in fee_status.split(",") if s.strip()]
if statuses:
q = q.filter(BizPilotCheckup.fee_status.in_(statuses))
if checkup_institution_id:
q = q.filter(BizPilotCheckup.checkup_institution_id == checkup_institution_id)
# keyword: fuzzy search across application_no, patient_name, channel_name
if keyword:
kw = f"%{keyword}%"
app_ids_by_no = (
db.query(BizPilotApplication.id)
.filter(
BizPilotApplication.application_no.like(kw),
BizPilotApplication.del_flag == 0,
)
.subquery()
)
app_ids_by_channel = (
db.query(BizPilotApplication.id)
.filter(
BizPilotApplication.channel_name.like(kw),
BizPilotApplication.del_flag == 0,
)
.subquery()
)
patient_ids_by_name = (
db.query(BizPilotPatient.id)
.filter(
BizPilotPatient.patient_name.like(kw),
BizPilotPatient.del_flag == 0,
)
.subquery()
)
q = q.filter(
or_(
BizPilotCheckup.pilot_application_id.in_(app_ids_by_no),
BizPilotCheckup.pilot_application_id.in_(app_ids_by_channel),
BizPilotCheckup.pilot_patient_id.in_(patient_ids_by_name),
)
)
if application_no:
app_subq = (
db.query(BizPilotApplication.id)
.filter(
BizPilotApplication.application_no.like(f"%{application_no}%"),
BizPilotApplication.del_flag == 0,
)
.subquery()
)
q = q.filter(BizPilotCheckup.pilot_application_id.in_(app_subq))
if patient_name:
patient_subq = (
db.query(BizPilotPatient.id)
.filter(
BizPilotPatient.patient_name.like(f"%{patient_name}%"),
BizPilotPatient.del_flag == 0,
)
.subquery()
)
q = q.filter(BizPilotCheckup.pilot_patient_id.in_(patient_subq))
if channel_id:
app_subq = (
db.query(BizPilotApplication.id)
.filter(
BizPilotApplication.channel_id == channel_id,
BizPilotApplication.del_flag == 0,
)
.subquery()
)
q = q.filter(BizPilotCheckup.pilot_application_id.in_(app_subq))
total = q.order_by(None).with_entities(func.count(BizPilotCheckup.id)).scalar() or 0
page = max(1, page)
page_size = min(max(1, page_size), 100)
rows = (
q.order_by(BizPilotCheckup.create_time.desc())
.offset((page - 1) * page_size)
.limit(page_size)
.all()
)
items = [_row_to_dict_checkup(r, db, tenant_no) for r in rows]
return {
"list": items,
"pagination": {"page": page, "pageSize": page_size, "total": total},
}
def list_pending_patients(
db: Session,
tenant_no: str,
page: int = 1,
page_size: int = 10,
application_no: Optional[str] = None,
patient_name: Optional[str] = None,
channel_id: Optional[str] = None,
) -> Dict[str, Any]:
"""查询 need_checkup=1 但尚未有 biz_pilot_checkup 记录的患者"""
checked_patient_ids = (
db.query(BizPilotCheckup.pilot_patient_id)
.filter(
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
BizPilotCheckup.pilot_patient_id.isnot(None),
BizPilotCheckup.pilot_patient_id != "",
)
.subquery()
)
q = db.query(BizPilotPatient).filter(
BizPilotPatient.need_checkup == 1,
BizPilotPatient.tenant_no == tenant_no,
BizPilotPatient.del_flag == 0,
~BizPilotPatient.id.in_(checked_patient_ids),
)
if patient_name:
q = q.filter(BizPilotPatient.patient_name.like(f"%{patient_name}%"))
if application_no or channel_id:
app_q = db.query(BizPilotApplication.id).filter(
BizPilotApplication.tenant_no == tenant_no,
BizPilotApplication.del_flag == 0,
)
if application_no:
app_q = app_q.filter(
BizPilotApplication.application_no.like(f"%{application_no}%")
)
if channel_id:
app_q = app_q.filter(BizPilotApplication.channel_id == channel_id)
app_subq = app_q.subquery()
q = q.filter(BizPilotPatient.pilot_application_id.in_(app_subq))
total = q.order_by(None).with_entities(func.count(BizPilotPatient.id)).scalar() or 0
page = max(1, page)
page_size = min(max(1, page_size), 100)
rows = (
q.order_by(BizPilotPatient.create_time.desc())
.offset((page - 1) * page_size)
.limit(page_size)
.all()
)
items = []
for r in rows:
d = {
"id": r.id,
"pilotApplicationId": r.pilot_application_id or "",
"patientName": r.patient_name or "",
"sex": r.sex or "",
"age": r.age,
"phoneNo": r.phone_no or "",
}
app = (
db.query(BizPilotApplication)
.filter(
BizPilotApplication.id == r.pilot_application_id,
BizPilotApplication.del_flag == 0,
)
.first()
)
if app:
d["applicationNo"] = app.application_no or ""
d["channelName"] = app.channel_name or ""
d["channelId"] = app.channel_id or ""
else:
d["applicationNo"] = ""
d["channelName"] = ""
d["channelId"] = ""
items.append(d)
return {
"list": items,
"pagination": {"page": page, "pageSize": page_size, "total": total},
}
def batch_create_checkups(
db: Session,
patient_ids: list,
checkup_institution_id: str,
reserve_time: Optional[str],
reserve_items: list,
tenant_no: str,
user_id: str,
) -> list:
"""为多个患者批量创建体检记录 + 预约项目"""
results = []
now = datetime.now()
for patient_id in patient_ids:
patient = (
db.query(BizPilotPatient)
.filter(
BizPilotPatient.id == patient_id,
BizPilotPatient.tenant_no == tenant_no,
BizPilotPatient.del_flag == 0,
)
.first()
)
if not patient:
continue
checkup_row = BizPilotCheckup(
id=uuid.uuid4().hex,
pilot_application_id=patient.pilot_application_id,
pilot_patient_id=patient_id,
checkup_institution_id=checkup_institution_id or "",
reserve_time=_parse_optional_datetime(reserve_time),
reserve_fee=sum(
float(item.get("projectFee") or 0) for item in reserve_items
) if reserve_items else None,
actual_checkup_time=None,
actual_checkup_fee=None,
fee_settled=0,
checkup_status="dtj",
fee_status="wjs",
checkup_remark="",
report_attachments="",
tenant_no=tenant_no,
order_num=0,
remark="",
create_by=user_id,
create_dept_id="",
create_time=now,
update_by=user_id,
update_time=now,
del_flag=0,
)
db.add(checkup_row)
db.flush()
for idx, item in enumerate(reserve_items):
ri = BizPilotCheckupReserveItem(
id=uuid.uuid4().hex,
pilot_checkup_id=checkup_row.id,
project_name=item.get("projectName") or item.get("project_name") or "",
project_fee=item.get("projectFee") if item.get("projectFee") is not None else (
item.get("project_fee") if item.get("project_fee") is not None else None
),
tenant_no=tenant_no,
order_num=idx + 1,
remark="",
create_by=user_id,
create_dept_id="",
create_time=now,
update_by=user_id,
update_time=now,
del_flag=0,
)
db.add(ri)
results.append(_row_to_dict_checkup(checkup_row, db, tenant_no))
db.commit()
return results
def ensure_checkup_for_patient(
db: Session,
patient_id: str,
application_id: str,
tenant_no: str,
user_id: str,
) -> Optional[str]:
"""为患者创建体检记录(如不存在)。返回 checkup_id 或 None。"""
existing = (
db.query(BizPilotCheckup)
.filter(
BizPilotCheckup.pilot_patient_id == patient_id,
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
)
.first()
)
if existing:
return existing.id
now = datetime.now()
row = BizPilotCheckup(
id=uuid.uuid4().hex,
pilot_application_id=application_id,
pilot_patient_id=patient_id,
checkup_institution_id="",
checkup_status="dtj",
fee_status="wjs",
fee_settled=0,
checkup_remark="",
report_attachments="",
tenant_no=tenant_no,
order_num=0,
remark="",
create_by=user_id,
create_dept_id="",
create_time=now,
update_by=user_id,
update_time=now,
del_flag=0,
)
db.add(row)
db.flush()
return row.id
def remove_checkup_for_patient(
db: Session,
patient_id: str,
tenant_no: str,
) -> None:
"""软删除患者的体检记录(仅在初始状态,无机构数据时才删除)。"""
row = (
db.query(BizPilotCheckup)
.filter(
BizPilotCheckup.pilot_patient_id == patient_id,
BizPilotCheckup.tenant_no == tenant_no,
BizPilotCheckup.del_flag == 0,
)
.first()
)
if not row:
return
if row.checkup_institution_id:
return
now = datetime.now()
row.del_flag = 1
row.update_time = now
db.query(BizPilotCheckupReserveItem).filter(
BizPilotCheckupReserveItem.pilot_checkup_id == row.id,
BizPilotCheckupReserveItem.tenant_no == tenant_no,
BizPilotCheckupReserveItem.del_flag == 0,
).update({"del_flag": 1, "update_time": now}, synchronize_session=False)
db.query(BizPilotCheckupActualItem).filter(
BizPilotCheckupActualItem.pilot_checkup_id == row.id,
BizPilotCheckupActualItem.tenant_no == tenant_no,
BizPilotCheckupActualItem.del_flag == 0,
).update({"del_flag": 1, "update_time": now}, synchronize_session=False)