825 lines
27 KiB
Python
825 lines
27 KiB
Python
"""中试申请单 CRUD(申请单、患者信息、输注方案、输注计划)"""
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
from datetime import datetime
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from sqlalchemy import and_, func
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.models.models import (
|
|
BizChannelServiceOrder,
|
|
BizCustomer,
|
|
BizPilotApplication,
|
|
BizPilotInfusionPlan,
|
|
BizPilotInfusionSchedule,
|
|
BizPilotPatient,
|
|
)
|
|
|
|
|
|
# ────────────────────────────────────────────
|
|
# Helpers: _row_to_dict
|
|
# ────────────────────────────────────────────
|
|
|
|
|
|
def _generate_application_no(db: Session, tenant_no: str) -> str:
|
|
today_str = datetime.now().strftime("%Y%m%d")
|
|
prefix = f"ZSSQ{today_str}"
|
|
existing = (
|
|
db.query(BizPilotApplication.application_no)
|
|
.filter(
|
|
BizPilotApplication.tenant_no == tenant_no,
|
|
BizPilotApplication.application_no.like(f"{prefix}%"),
|
|
BizPilotApplication.del_flag == 0,
|
|
)
|
|
.order_by(BizPilotApplication.application_no.desc())
|
|
.first()
|
|
)
|
|
seq = 1
|
|
if existing and existing[0]:
|
|
try:
|
|
seq = int(existing[0][-4:]) + 1
|
|
except ValueError:
|
|
seq = 1
|
|
return f"{prefix}{seq:04d}"
|
|
|
|
|
|
def _row_to_dict_application(row, db=None, tenant_no=None) -> Dict[str, Any]:
|
|
d: Dict[str, Any] = {
|
|
"id": row.id,
|
|
"applicationNo": row.application_no or "",
|
|
"applicationStatus": row.application_status or "",
|
|
"channelServiceOrderId": row.channel_service_order_id or "",
|
|
"channelId": row.channel_id or "",
|
|
"channelName": row.channel_name 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:
|
|
# patientName
|
|
patient = (
|
|
db.query(BizPilotPatient.patient_name)
|
|
.filter(
|
|
BizPilotPatient.pilot_application_id == row.id,
|
|
BizPilotPatient.tenant_no == tenant_no,
|
|
BizPilotPatient.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
d["patientName"] = patient.patient_name if patient else ""
|
|
|
|
# infusionPlanCount
|
|
plan_count = (
|
|
db.query(func.count(BizPilotInfusionPlan.id))
|
|
.filter(
|
|
BizPilotInfusionPlan.pilot_application_id == row.id,
|
|
BizPilotInfusionPlan.tenant_no == tenant_no,
|
|
BizPilotInfusionPlan.del_flag == 0,
|
|
)
|
|
.scalar()
|
|
) or 0
|
|
d["infusionPlanCount"] = plan_count
|
|
|
|
# serviceOrderNo + orderType
|
|
svc_order = (
|
|
db.query(BizChannelServiceOrder)
|
|
.filter(BizChannelServiceOrder.id == row.channel_service_order_id)
|
|
.first()
|
|
)
|
|
if svc_order:
|
|
d["serviceOrderNo"] = svc_order.channel_name or ""
|
|
d["orderType"] = svc_order.order_type or ""
|
|
else:
|
|
d["serviceOrderNo"] = ""
|
|
d["orderType"] = ""
|
|
|
|
return d
|
|
|
|
|
|
def _row_to_dict_patient(row) -> Dict[str, Any]:
|
|
return {
|
|
"id": row.id,
|
|
"pilotApplicationId": row.pilot_application_id or "",
|
|
"customerId": row.customer_id or "",
|
|
"patientName": row.patient_name or "",
|
|
"sex": row.sex or "",
|
|
"age": row.age if row.age is not None else None,
|
|
"idCardNo": row.id_card_no or "",
|
|
"phoneNo": row.phone_no or "",
|
|
"emergencyContact": row.emergency_contact or "",
|
|
"emergencyPhone": row.emergency_phone or "",
|
|
"clinicalDiagnosis": row.clinical_diagnosis or "",
|
|
"diagnosisAttachments": row.diagnosis_attachments or "",
|
|
"needCheckup": row.need_checkup if row.need_checkup is not None else 1,
|
|
"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 "",
|
|
}
|
|
|
|
|
|
def _row_to_dict_infusion_plan(row, db=None, tenant_no=None) -> Dict[str, Any]:
|
|
d: Dict[str, Any] = {
|
|
"id": row.id,
|
|
"pilotApplicationId": row.pilot_application_id or "",
|
|
"cellType": row.cell_type or "",
|
|
"specText": row.spec_text or "",
|
|
"totalCourseCount": row.total_course_count if row.total_course_count is not None else 0,
|
|
"courseInterval": row.course_interval or "",
|
|
"infusionRoute": row.infusion_route or "",
|
|
"infusionStartDate": row.infusion_start_date 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:
|
|
# scheduleCount (all schedules)
|
|
schedule_count = (
|
|
db.query(func.count(BizPilotInfusionSchedule.id))
|
|
.filter(
|
|
BizPilotInfusionSchedule.infusion_plan_id == row.id,
|
|
BizPilotInfusionSchedule.tenant_no == tenant_no,
|
|
BizPilotInfusionSchedule.del_flag == 0,
|
|
)
|
|
.scalar()
|
|
) or 0
|
|
d["scheduleCount"] = schedule_count
|
|
|
|
# completedCount (schedule_status='ywc')
|
|
completed_count = (
|
|
db.query(func.count(BizPilotInfusionSchedule.id))
|
|
.filter(
|
|
BizPilotInfusionSchedule.infusion_plan_id == row.id,
|
|
BizPilotInfusionSchedule.tenant_no == tenant_no,
|
|
BizPilotInfusionSchedule.del_flag == 0,
|
|
BizPilotInfusionSchedule.schedule_status == "ywc",
|
|
)
|
|
.scalar()
|
|
) or 0
|
|
d["completedCount"] = completed_count
|
|
|
|
return d
|
|
|
|
|
|
def _row_to_dict_infusion_schedule(row) -> Dict[str, Any]:
|
|
return {
|
|
"id": row.id,
|
|
"infusionPlanId": row.infusion_plan_id or "",
|
|
"cellType": row.cell_type or "",
|
|
"specText": row.spec_text or "",
|
|
"infusionTime": row.infusion_time.strftime("%Y-%m-%d %H:%M:%S") if row.infusion_time else "",
|
|
"scheduleStatus": row.schedule_status or "",
|
|
"attachments": row.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 "",
|
|
}
|
|
|
|
|
|
# ────────────────────────────────────────────
|
|
# Application CRUD
|
|
# ────────────────────────────────────────────
|
|
|
|
|
|
def list_applications(
|
|
db: Session,
|
|
tenant_no: str,
|
|
page: int = 1,
|
|
page_size: int = 10,
|
|
channel_id: Optional[str] = None,
|
|
application_status: Optional[str] = None,
|
|
channel_service_order_id: Optional[str] = None,
|
|
):
|
|
q = db.query(BizPilotApplication).filter(
|
|
BizPilotApplication.tenant_no == tenant_no,
|
|
BizPilotApplication.del_flag == 0,
|
|
)
|
|
if channel_id:
|
|
q = q.filter(BizPilotApplication.channel_id == channel_id)
|
|
if application_status:
|
|
statuses = [s.strip() for s in application_status.split(",") if s.strip()]
|
|
if statuses:
|
|
q = q.filter(BizPilotApplication.application_status.in_(statuses))
|
|
if channel_service_order_id:
|
|
q = q.filter(BizPilotApplication.channel_service_order_id == channel_service_order_id)
|
|
|
|
total = q.order_by(None).with_entities(func.count(BizPilotApplication.id)).scalar() or 0
|
|
page = max(1, page)
|
|
page_size = min(max(1, page_size), 100)
|
|
rows = (
|
|
q.order_by(BizPilotApplication.create_time.desc())
|
|
.offset((page - 1) * page_size)
|
|
.limit(page_size)
|
|
.all()
|
|
)
|
|
items = [_row_to_dict_application(r, db, tenant_no) for r in rows]
|
|
return {
|
|
"list": items,
|
|
"pagination": {"page": page, "pageSize": page_size, "total": total},
|
|
}
|
|
|
|
|
|
def get_application(db: Session, app_id: str, tenant_no: str) -> Optional[Dict[str, Any]]:
|
|
row = (
|
|
db.query(BizPilotApplication)
|
|
.filter(
|
|
BizPilotApplication.id == app_id,
|
|
BizPilotApplication.tenant_no == tenant_no,
|
|
BizPilotApplication.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
return None
|
|
return _row_to_dict_application(row, db, tenant_no)
|
|
|
|
|
|
def create_application(
|
|
db: Session,
|
|
data: dict,
|
|
tenant_no: str,
|
|
user_id: str,
|
|
dept_id: str,
|
|
) -> Dict[str, Any]:
|
|
channel_service_order_id = data.get("channelServiceOrderId") or ""
|
|
if not channel_service_order_id:
|
|
raise ValueError("请选择渠道服务订单")
|
|
|
|
# Validate service order exists and is active
|
|
svc_order = (
|
|
db.query(BizChannelServiceOrder)
|
|
.filter(
|
|
BizChannelServiceOrder.id == channel_service_order_id,
|
|
BizChannelServiceOrder.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not svc_order:
|
|
raise ValueError("渠道服务订单不存在")
|
|
if svc_order.order_status != "sxz":
|
|
raise ValueError("渠道服务订单未生效,无法创建中试申请")
|
|
|
|
now = datetime.now()
|
|
application_no = _generate_application_no(db, tenant_no)
|
|
|
|
row = BizPilotApplication(
|
|
id=str(uuid.uuid4()),
|
|
application_no=application_no,
|
|
application_status="dks",
|
|
channel_service_order_id=channel_service_order_id,
|
|
channel_id=svc_order.channel_id or "",
|
|
channel_name=svc_order.channel_name or "",
|
|
tenant_no=tenant_no,
|
|
order_num=0,
|
|
remark=data.get("remark") or "",
|
|
create_by=user_id,
|
|
create_dept_id=dept_id or "",
|
|
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_application(row, db, tenant_no)
|
|
|
|
|
|
def update_application(db: Session, app_id: str, data: dict, tenant_no: str) -> Dict[str, Any]:
|
|
row = (
|
|
db.query(BizPilotApplication)
|
|
.filter(
|
|
BizPilotApplication.id == app_id,
|
|
BizPilotApplication.tenant_no == tenant_no,
|
|
BizPilotApplication.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("申请单不存在")
|
|
if row.application_status != "dks":
|
|
raise ValueError("当前状态不允许编辑")
|
|
|
|
if "remark" in data and data["remark"] is not None:
|
|
row.remark = data["remark"]
|
|
|
|
db.commit()
|
|
db.refresh(row)
|
|
return _row_to_dict_application(row, db, tenant_no)
|
|
|
|
|
|
def soft_delete_application(db: Session, app_id: str, tenant_no: str) -> None:
|
|
row = (
|
|
db.query(BizPilotApplication)
|
|
.filter(
|
|
BizPilotApplication.id == app_id,
|
|
BizPilotApplication.tenant_no == tenant_no,
|
|
BizPilotApplication.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("申请单不存在")
|
|
if row.application_status != "dks":
|
|
raise ValueError("当前状态不允许删除")
|
|
|
|
row.del_flag = 1
|
|
row.update_time = datetime.now()
|
|
db.commit()
|
|
|
|
|
|
def start_application(db: Session, app_id: str, tenant_no: str, user_id: str) -> Dict[str, Any]:
|
|
row = (
|
|
db.query(BizPilotApplication)
|
|
.filter(
|
|
BizPilotApplication.id == app_id,
|
|
BizPilotApplication.tenant_no == tenant_no,
|
|
BizPilotApplication.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("申请单不存在")
|
|
if row.application_status != "dks":
|
|
raise ValueError("当前状态不允许开始")
|
|
|
|
row.application_status = "jxz"
|
|
row.update_by = user_id
|
|
row.update_time = datetime.now()
|
|
db.commit()
|
|
db.refresh(row)
|
|
return _row_to_dict_application(row, db, tenant_no)
|
|
|
|
|
|
def complete_application(db: Session, app_id: str, tenant_no: str, user_id: str) -> Dict[str, Any]:
|
|
row = (
|
|
db.query(BizPilotApplication)
|
|
.filter(
|
|
BizPilotApplication.id == app_id,
|
|
BizPilotApplication.tenant_no == tenant_no,
|
|
BizPilotApplication.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("申请单不存在")
|
|
if row.application_status != "jxz":
|
|
raise ValueError("当前状态不允许完成")
|
|
|
|
row.application_status = "ywc"
|
|
row.update_by = user_id
|
|
row.update_time = datetime.now()
|
|
db.commit()
|
|
db.refresh(row)
|
|
return _row_to_dict_application(row, db, tenant_no)
|
|
|
|
|
|
def void_application(db: Session, app_id: str, tenant_no: str, user_id: str) -> Dict[str, Any]:
|
|
row = (
|
|
db.query(BizPilotApplication)
|
|
.filter(
|
|
BizPilotApplication.id == app_id,
|
|
BizPilotApplication.tenant_no == tenant_no,
|
|
BizPilotApplication.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("申请单不存在")
|
|
if row.application_status not in ("dks", "jxz"):
|
|
raise ValueError("当前状态不允许作废")
|
|
|
|
row.application_status = "yzf"
|
|
row.update_by = user_id
|
|
row.update_time = datetime.now()
|
|
db.commit()
|
|
db.refresh(row)
|
|
return _row_to_dict_application(row, db, tenant_no)
|
|
|
|
|
|
# ────────────────────────────────────────────
|
|
# Patient CRUD
|
|
# ────────────────────────────────────────────
|
|
|
|
|
|
def get_patient_by_application(
|
|
db: Session, app_id: str, tenant_no: str
|
|
) -> Optional[Dict[str, Any]]:
|
|
row = (
|
|
db.query(BizPilotPatient)
|
|
.filter(
|
|
BizPilotPatient.pilot_application_id == app_id,
|
|
BizPilotPatient.tenant_no == tenant_no,
|
|
BizPilotPatient.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
return None
|
|
return _row_to_dict_patient(row)
|
|
|
|
|
|
def save_patient(
|
|
db: Session,
|
|
app_id: str,
|
|
data: dict,
|
|
tenant_no: str,
|
|
user_id: str,
|
|
dept_id: str,
|
|
) -> Dict[str, Any]:
|
|
now = datetime.now()
|
|
customer_id = data.get("customerId") or ""
|
|
|
|
if customer_id:
|
|
customer = (
|
|
db.query(BizCustomer)
|
|
.filter(BizCustomer.id == customer_id, BizCustomer.del_flag == 0)
|
|
.first()
|
|
)
|
|
if customer:
|
|
if data.get("patientName"):
|
|
customer.customer_name = data["patientName"]
|
|
if data.get("sex"):
|
|
customer.sex = data["sex"]
|
|
if data.get("age") is not None:
|
|
customer.age = data["age"]
|
|
if data.get("idCardNo"):
|
|
customer.id_card_no = data["idCardNo"]
|
|
if data.get("phoneNo"):
|
|
customer.phone_no = data["phoneNo"]
|
|
customer.update_by = user_id
|
|
customer.update_time = now
|
|
else:
|
|
customer_id = str(uuid.uuid4())
|
|
customer = BizCustomer(
|
|
id=customer_id,
|
|
customer_name=data.get("patientName") or "",
|
|
sex=data.get("sex") or "2",
|
|
id_card_no=data.get("idCardNo") or "",
|
|
age=data.get("age"),
|
|
phone_no=data.get("phoneNo") or "",
|
|
tenant_no=tenant_no,
|
|
order_num=0,
|
|
remark="",
|
|
create_by=user_id,
|
|
create_dept_id=dept_id or "",
|
|
create_time=now,
|
|
update_by=user_id,
|
|
update_time=now,
|
|
del_flag=0,
|
|
)
|
|
db.add(customer)
|
|
db.flush()
|
|
|
|
existing = (
|
|
db.query(BizPilotPatient)
|
|
.filter(
|
|
BizPilotPatient.pilot_application_id == app_id,
|
|
BizPilotPatient.tenant_no == tenant_no,
|
|
BizPilotPatient.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
|
|
if existing:
|
|
existing.customer_id = customer_id
|
|
existing.patient_name = data.get("patientName") or ""
|
|
existing.sex = data.get("sex") or ""
|
|
existing.age = data.get("age")
|
|
existing.id_card_no = data.get("idCardNo") or ""
|
|
existing.phone_no = data.get("phoneNo") or ""
|
|
existing.emergency_contact = data.get("emergencyContact") or ""
|
|
existing.emergency_phone = data.get("emergencyPhone") or ""
|
|
existing.clinical_diagnosis = data.get("clinicalDiagnosis") or ""
|
|
existing.diagnosis_attachments = data.get("diagnosisAttachments") or ""
|
|
existing.need_checkup = data.get("needCheckup") if data.get("needCheckup") is not None else 1
|
|
existing.remark = data.get("remark") or ""
|
|
existing.update_by = user_id
|
|
existing.update_time = now
|
|
else:
|
|
existing = BizPilotPatient(
|
|
id=str(uuid.uuid4()),
|
|
pilot_application_id=app_id,
|
|
customer_id=customer_id,
|
|
patient_name=data.get("patientName") or "",
|
|
sex=data.get("sex") or "",
|
|
age=data.get("age"),
|
|
id_card_no=data.get("idCardNo") or "",
|
|
phone_no=data.get("phoneNo") or "",
|
|
emergency_contact=data.get("emergencyContact") or "",
|
|
emergency_phone=data.get("emergencyPhone") or "",
|
|
clinical_diagnosis=data.get("clinicalDiagnosis") or "",
|
|
diagnosis_attachments=data.get("diagnosisAttachments") or "",
|
|
need_checkup=data.get("needCheckup") if data.get("needCheckup") is not None else 1,
|
|
tenant_no=tenant_no,
|
|
order_num=0,
|
|
remark=data.get("remark") or "",
|
|
create_by=user_id,
|
|
create_dept_id=dept_id or "",
|
|
create_time=now,
|
|
update_by=user_id,
|
|
update_time=now,
|
|
del_flag=0,
|
|
)
|
|
db.add(existing)
|
|
|
|
db.commit()
|
|
db.refresh(existing)
|
|
return _row_to_dict_patient(existing)
|
|
|
|
|
|
# ────────────────────────────────────────────
|
|
# InfusionPlan CRUD
|
|
# ────────────────────────────────────────────
|
|
|
|
|
|
def list_infusion_plans(
|
|
db: Session, app_id: str, tenant_no: str
|
|
) -> List[Dict[str, Any]]:
|
|
rows = (
|
|
db.query(BizPilotInfusionPlan)
|
|
.filter(
|
|
BizPilotInfusionPlan.pilot_application_id == app_id,
|
|
BizPilotInfusionPlan.tenant_no == tenant_no,
|
|
BizPilotInfusionPlan.del_flag == 0,
|
|
)
|
|
.order_by(BizPilotInfusionPlan.order_num.asc(), BizPilotInfusionPlan.create_time.asc())
|
|
.all()
|
|
)
|
|
return [_row_to_dict_infusion_plan(r, db, tenant_no) for r in rows]
|
|
|
|
|
|
def create_infusion_plan(
|
|
db: Session,
|
|
app_id: str,
|
|
data: dict,
|
|
tenant_no: str,
|
|
user_id: str,
|
|
dept_id: str,
|
|
) -> Dict[str, Any]:
|
|
now = datetime.now()
|
|
row = BizPilotInfusionPlan(
|
|
id=str(uuid.uuid4()),
|
|
pilot_application_id=app_id,
|
|
cell_type=data.get("cellType") or "",
|
|
spec_text=data.get("specText") or "",
|
|
total_course_count=data.get("totalCourseCount") or 0,
|
|
course_interval=data.get("courseInterval") or "",
|
|
infusion_route=data.get("infusionRoute") or "",
|
|
infusion_start_date=data.get("infusionStartDate") or "",
|
|
tenant_no=tenant_no,
|
|
order_num=data.get("orderNum") or 0,
|
|
remark=data.get("remark") or "",
|
|
create_by=user_id,
|
|
create_dept_id=dept_id or "",
|
|
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_infusion_plan(row, db, tenant_no)
|
|
|
|
|
|
def update_infusion_plan(
|
|
db: Session, plan_id: str, data: dict, tenant_no: str
|
|
) -> Dict[str, Any]:
|
|
row = (
|
|
db.query(BizPilotInfusionPlan)
|
|
.filter(
|
|
BizPilotInfusionPlan.id == plan_id,
|
|
BizPilotInfusionPlan.tenant_no == tenant_no,
|
|
BizPilotInfusionPlan.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("输注方案不存在")
|
|
|
|
fields = {
|
|
"cellType": "cell_type",
|
|
"specText": "spec_text",
|
|
"totalCourseCount": "total_course_count",
|
|
"courseInterval": "course_interval",
|
|
"infusionRoute": "infusion_route",
|
|
"infusionStartDate": "infusion_start_date",
|
|
"remark": "remark",
|
|
}
|
|
for camel, snake in fields.items():
|
|
if camel in data and data[camel] is not None:
|
|
setattr(row, snake, data[camel])
|
|
|
|
row.update_time = datetime.now()
|
|
db.commit()
|
|
db.refresh(row)
|
|
return _row_to_dict_infusion_plan(row, db, tenant_no)
|
|
|
|
|
|
def soft_delete_infusion_plan(db: Session, plan_id: str, tenant_no: str) -> None:
|
|
now = datetime.now()
|
|
row = (
|
|
db.query(BizPilotInfusionPlan)
|
|
.filter(
|
|
BizPilotInfusionPlan.id == plan_id,
|
|
BizPilotInfusionPlan.tenant_no == tenant_no,
|
|
BizPilotInfusionPlan.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("输注方案不存在")
|
|
|
|
row.del_flag = 1
|
|
row.update_time = now
|
|
|
|
# Also soft-delete all schedules under this plan
|
|
db.query(BizPilotInfusionSchedule).filter(
|
|
BizPilotInfusionSchedule.infusion_plan_id == plan_id,
|
|
BizPilotInfusionSchedule.tenant_no == tenant_no,
|
|
BizPilotInfusionSchedule.del_flag == 0,
|
|
).update({"del_flag": 1, "update_time": now}, synchronize_session=False)
|
|
|
|
db.commit()
|
|
|
|
|
|
# ────────────────────────────────────────────
|
|
# InfusionSchedule CRUD
|
|
# ────────────────────────────────────────────
|
|
|
|
|
|
def list_schedules_by_plan(
|
|
db: Session, plan_id: str, tenant_no: str
|
|
) -> List[Dict[str, Any]]:
|
|
rows = (
|
|
db.query(BizPilotInfusionSchedule)
|
|
.filter(
|
|
BizPilotInfusionSchedule.infusion_plan_id == plan_id,
|
|
BizPilotInfusionSchedule.tenant_no == tenant_no,
|
|
BizPilotInfusionSchedule.del_flag == 0,
|
|
)
|
|
.order_by(BizPilotInfusionSchedule.order_num.asc())
|
|
.all()
|
|
)
|
|
return [_row_to_dict_infusion_schedule(r) for r in rows]
|
|
|
|
|
|
def auto_generate_schedules(
|
|
db: Session,
|
|
plan_id: str,
|
|
tenant_no: str,
|
|
user_id: str,
|
|
dept_id: str,
|
|
) -> Dict[str, Any]:
|
|
plan = (
|
|
db.query(BizPilotInfusionPlan)
|
|
.filter(
|
|
BizPilotInfusionPlan.id == plan_id,
|
|
BizPilotInfusionPlan.tenant_no == tenant_no,
|
|
BizPilotInfusionPlan.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not plan:
|
|
raise ValueError("输注方案不存在")
|
|
|
|
total = plan.total_course_count or 0
|
|
if total <= 0:
|
|
raise ValueError("总疗程数必须大于0")
|
|
|
|
now = datetime.now()
|
|
for i in range(1, total + 1):
|
|
sched = BizPilotInfusionSchedule(
|
|
id=str(uuid.uuid4()),
|
|
infusion_plan_id=plan_id,
|
|
cell_type=plan.cell_type or "",
|
|
spec_text=plan.spec_text or "",
|
|
schedule_status="",
|
|
tenant_no=tenant_no,
|
|
order_num=i,
|
|
remark="",
|
|
create_by=user_id,
|
|
create_dept_id=dept_id or "",
|
|
create_time=now,
|
|
update_by=user_id,
|
|
update_time=now,
|
|
del_flag=0,
|
|
)
|
|
db.add(sched)
|
|
|
|
db.commit()
|
|
return {"generatedCount": total}
|
|
|
|
|
|
def create_schedule(
|
|
db: Session,
|
|
plan_id: str,
|
|
data: dict,
|
|
tenant_no: str,
|
|
user_id: str,
|
|
dept_id: str,
|
|
) -> Dict[str, Any]:
|
|
now = datetime.now()
|
|
row = BizPilotInfusionSchedule(
|
|
id=str(uuid.uuid4()),
|
|
infusion_plan_id=plan_id,
|
|
cell_type=data.get("cellType") or "",
|
|
spec_text=data.get("specText") or "",
|
|
schedule_status=data.get("scheduleStatus") or "",
|
|
attachments=data.get("attachments") or "",
|
|
tenant_no=tenant_no,
|
|
order_num=data.get("orderNum") or 0,
|
|
remark=data.get("remark") or "",
|
|
create_by=user_id,
|
|
create_dept_id=dept_id or "",
|
|
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_infusion_schedule(row)
|
|
|
|
|
|
def update_schedule(
|
|
db: Session, schedule_id: str, data: dict, tenant_no: str
|
|
) -> Dict[str, Any]:
|
|
row = (
|
|
db.query(BizPilotInfusionSchedule)
|
|
.filter(
|
|
BizPilotInfusionSchedule.id == schedule_id,
|
|
BizPilotInfusionSchedule.tenant_no == tenant_no,
|
|
BizPilotInfusionSchedule.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("输注计划不存在")
|
|
|
|
if "infusionTime" in data and data["infusionTime"] is not None:
|
|
row.infusion_time = data["infusionTime"]
|
|
if "remark" in data and data["remark"] is not None:
|
|
row.remark = data["remark"]
|
|
if "attachments" in data and data["attachments"] is not None:
|
|
row.attachments = data["attachments"]
|
|
|
|
row.update_time = datetime.now()
|
|
db.commit()
|
|
db.refresh(row)
|
|
return _row_to_dict_infusion_schedule(row)
|
|
|
|
|
|
def soft_delete_schedule(db: Session, schedule_id: str, tenant_no: str) -> None:
|
|
row = (
|
|
db.query(BizPilotInfusionSchedule)
|
|
.filter(
|
|
BizPilotInfusionSchedule.id == schedule_id,
|
|
BizPilotInfusionSchedule.tenant_no == tenant_no,
|
|
BizPilotInfusionSchedule.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("输注计划不存在")
|
|
|
|
row.del_flag = 1
|
|
row.update_time = datetime.now()
|
|
db.commit()
|
|
|
|
|
|
def mark_schedule_complete(
|
|
db: Session, schedule_id: str, tenant_no: str, user_id: str
|
|
) -> Dict[str, Any]:
|
|
row = (
|
|
db.query(BizPilotInfusionSchedule)
|
|
.filter(
|
|
BizPilotInfusionSchedule.id == schedule_id,
|
|
BizPilotInfusionSchedule.tenant_no == tenant_no,
|
|
BizPilotInfusionSchedule.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("输注计划不存在")
|
|
|
|
row.schedule_status = "ysc"
|
|
row.update_by = user_id
|
|
row.update_time = datetime.now()
|
|
db.commit()
|
|
db.refresh(row)
|
|
return _row_to_dict_infusion_schedule(row)
|