657 lines
21 KiB
Python
657 lines
21 KiB
Python
"""质检任务 CRUD"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from decimal import Decimal
|
|
from typing import Any, Dict, List, Optional, Tuple
|
|
|
|
from sqlalchemy import and_, func, or_
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.utils import generate_uuid
|
|
from app.crud.collection_protocol import urls_to_attachment_list
|
|
from app.crud import sample_reception as sample_reception_svc
|
|
from app.crud.qc_work_order import (
|
|
_load_sample_type_name_map,
|
|
_qc_biz_type_label,
|
|
_reception_source_label,
|
|
_sample_type_name_for_reception,
|
|
_work_order_qc_biz_type,
|
|
_OUTBOUND_BIZ_TYPE_LABELS,
|
|
)
|
|
from app.models.models import (
|
|
BizCollectionProtocol,
|
|
BizProtocolSample,
|
|
BizQcTask,
|
|
BizQcWorkOrder,
|
|
BizSampleReception,
|
|
)
|
|
from app.models.research_donation import BizResearchDonation, BizResearchDonationSample
|
|
|
|
|
|
def _dec(v: Any) -> Optional[float]:
|
|
if v is None:
|
|
return None
|
|
return float(v)
|
|
|
|
|
|
def _fmt_dt(t: Optional[datetime]) -> str:
|
|
return t.strftime("%Y-%m-%d %H:%M:%S") if t else ""
|
|
|
|
|
|
def _gen_task_no(db: Session, work_order, seq: int) -> str:
|
|
return f"{work_order.work_order_no}-{seq:02d}"
|
|
|
|
|
|
_CONCLUSION_LABELS = {"tg": "通过", "btg": "不通过"}
|
|
_PROTOCOL_STATUS_LABELS = {
|
|
"dsx": "待生效", "sxz": "生效中", "ygq": "已过期", "yzf": "已作废", "zky": "转科研"
|
|
}
|
|
_DONATION_STATUS_LABELS = {
|
|
"dsx": "待生效", "sxz": "生效中", "ygq": "已过期", "yzf": "已作废", "zckc": "转细胞存储"
|
|
}
|
|
|
|
|
|
def _conclusion_label(v: Optional[str]) -> str:
|
|
key = (v or "").strip()
|
|
return _CONCLUSION_LABELS.get(key, key)
|
|
|
|
|
|
def _task_to_dict(
|
|
t: BizQcTask,
|
|
work_order_no: str = "",
|
|
db: Optional[Session] = None,
|
|
tenant_no: Optional[str] = None,
|
|
) -> Dict[str, Any]:
|
|
tn = tenant_no or t.tenant_no
|
|
return {
|
|
"id": t.id,
|
|
"workOrderId": t.work_order_id,
|
|
"orderSource": getattr(t, "order_source", "inbound") or "inbound",
|
|
"workOrderNo": work_order_no,
|
|
"taskNo": t.task_no,
|
|
"taskType": t.task_type,
|
|
"sourceLineId": t.source_line_id,
|
|
"itemCode": t.item_code,
|
|
"itemName": t.item_name,
|
|
"companyId": t.company_id or "",
|
|
"companyName": t.company_name or "",
|
|
"feeAmount": _dec(t.fee_amount),
|
|
"taskStatus": t.task_status,
|
|
"conclusion": t.conclusion or "",
|
|
"conclusionLabel": _conclusion_label(t.conclusion),
|
|
"thirdPartyAttachments": t.third_party_attachments or "",
|
|
"attachmentFiles": urls_to_attachment_list(t.third_party_attachments, db, tn) if db else [],
|
|
"completedTime": _fmt_dt(t.completed_time),
|
|
"completedBy": t.completed_by or "",
|
|
"remark": t.remark or "",
|
|
"createTime": _fmt_dt(t.create_time),
|
|
"updateTime": _fmt_dt(t.update_time),
|
|
}
|
|
|
|
|
|
def _task_work_order_context(wo: BizQcWorkOrder, t: BizQcTask) -> Dict[str, Any]:
|
|
biz = _work_order_qc_biz_type(wo)
|
|
wo_type = getattr(wo, "work_order_type", None) or "inbound"
|
|
if wo_type == "temporary":
|
|
order_source = "temporary"
|
|
recv_source = ""
|
|
recv_label = ""
|
|
elif wo_type == "outbound":
|
|
order_source = "outbound"
|
|
recv_source = getattr(wo, "biz_type", "") or ""
|
|
recv_label = _OUTBOUND_BIZ_TYPE_LABELS.get(recv_source, recv_source) if recv_source else ""
|
|
else:
|
|
order_source = getattr(t, "order_source", "inbound") or "inbound"
|
|
recv_source = getattr(wo, "reception_source", "cell_storage") or "cell_storage"
|
|
recv_label = _reception_source_label(recv_source)
|
|
return {
|
|
"orderSource": order_source,
|
|
"receptionId": wo.reception_id,
|
|
"protocolNo": wo.protocol_no or "",
|
|
"sampleCode": wo.sample_code or t.sample_code or "",
|
|
"qcBizType": biz,
|
|
"qcBizTypeLabel": _qc_biz_type_label(biz),
|
|
"receptionSource": recv_source,
|
|
"receptionSourceLabel": recv_label,
|
|
"cellProductId": getattr(wo, "cell_product_id", None) or "",
|
|
"cellProductCode": "",
|
|
"cellProductName": "",
|
|
"cellProductTypeName": "",
|
|
"cellProductPassage": "",
|
|
"cellProductSpecName": "",
|
|
"receptionTime": "",
|
|
"handlerName": "",
|
|
"sampleTypeName": "",
|
|
"workOrderStatus": wo.work_order_status or "",
|
|
}
|
|
|
|
|
|
def _enrich_tasks_reception_fields(
|
|
db: Session, items: List[Dict[str, Any]]
|
|
) -> List[Dict[str, Any]]:
|
|
if not items:
|
|
return items
|
|
rec_ids = [x.get("receptionId") for x in items if x.get("receptionId")]
|
|
if not rec_ids:
|
|
return items
|
|
rec_map = {
|
|
r.id: r
|
|
for r in db.query(BizSampleReception)
|
|
.filter(BizSampleReception.id.in_(rec_ids), BizSampleReception.del_flag == 0)
|
|
.all()
|
|
}
|
|
cell_sample_ids = [
|
|
r.protocol_sample_id
|
|
for r in rec_map.values()
|
|
if (r.reception_source or "cell_storage") != "research_donation" and r.protocol_sample_id
|
|
]
|
|
donation_sample_ids = [
|
|
r.donation_sample_id
|
|
for r in rec_map.values()
|
|
if (r.reception_source or "") == "research_donation" and r.donation_sample_id
|
|
]
|
|
protocol_samples: Dict[str, BizProtocolSample] = {}
|
|
if cell_sample_ids:
|
|
protocol_samples = {
|
|
s.id: s
|
|
for s in db.query(BizProtocolSample)
|
|
.filter(BizProtocolSample.id.in_(cell_sample_ids), BizProtocolSample.del_flag == 0)
|
|
.all()
|
|
}
|
|
donation_samples: Dict[str, BizResearchDonationSample] = {}
|
|
if donation_sample_ids:
|
|
donation_samples = {
|
|
s.id: s
|
|
for s in db.query(BizResearchDonationSample)
|
|
.filter(
|
|
BizResearchDonationSample.id.in_(donation_sample_ids),
|
|
BizResearchDonationSample.del_flag == 0,
|
|
)
|
|
.all()
|
|
}
|
|
type_ids = list(
|
|
{
|
|
s.sample_type_id
|
|
for s in list(protocol_samples.values()) + list(donation_samples.values())
|
|
if s.sample_type_id
|
|
}
|
|
)
|
|
type_map = _load_sample_type_name_map(db, type_ids)
|
|
cell_proto_ids = [
|
|
rec.collection_protocol_id
|
|
for rec in rec_map.values()
|
|
if (rec.reception_source or "cell_storage") != "research_donation" and rec.collection_protocol_id
|
|
]
|
|
donation_ids = [
|
|
rec.research_donation_id
|
|
for rec in rec_map.values()
|
|
if (rec.reception_source or "") == "research_donation" and rec.research_donation_id
|
|
]
|
|
proto_status_map: Dict[str, str] = {}
|
|
if cell_proto_ids:
|
|
for p in (
|
|
db.query(BizCollectionProtocol.id, BizCollectionProtocol.protocol_status)
|
|
.filter(BizCollectionProtocol.id.in_(cell_proto_ids), BizCollectionProtocol.del_flag == 0)
|
|
.all()
|
|
):
|
|
proto_status_map[p.id] = p.protocol_status or ""
|
|
donation_status_map: Dict[str, str] = {}
|
|
if donation_ids:
|
|
for d in (
|
|
db.query(BizResearchDonation.id, BizResearchDonation.donation_status)
|
|
.filter(BizResearchDonation.id.in_(donation_ids), BizResearchDonation.del_flag == 0)
|
|
.all()
|
|
):
|
|
donation_status_map[d.id] = d.donation_status or ""
|
|
for item in items:
|
|
if item.get("orderSource") in ("temporary", "outbound"):
|
|
item.setdefault("receptionSource", "")
|
|
item.setdefault("receptionSourceLabel", "")
|
|
continue
|
|
rec = rec_map.get(item.get("receptionId") or "")
|
|
if not rec:
|
|
continue
|
|
item["receptionTime"] = _fmt_dt(rec.reception_time)
|
|
item["handlerName"] = rec.handler_name or ""
|
|
item["sampleTypeName"] = _sample_type_name_for_reception(
|
|
db,
|
|
rec,
|
|
type_map,
|
|
protocol_samples=protocol_samples,
|
|
donation_samples=donation_samples,
|
|
)
|
|
source = item.get("receptionSource") or (rec.reception_source if rec else "cell_storage")
|
|
if source == "research_donation":
|
|
_did = rec.research_donation_id if rec else ""
|
|
_st = donation_status_map.get(_did or "", "")
|
|
item["protocolStatus"] = _st
|
|
item["protocolStatusLabel"] = _DONATION_STATUS_LABELS.get(_st, _st)
|
|
else:
|
|
_pid = rec.collection_protocol_id if rec else ""
|
|
_st = proto_status_map.get(_pid or "", "")
|
|
item["protocolStatus"] = _st
|
|
item["protocolStatusLabel"] = _PROTOCOL_STATUS_LABELS.get(_st, _st)
|
|
return items
|
|
|
|
|
|
def _task_row_to_dict(
|
|
t: BizQcTask,
|
|
wo: BizQcWorkOrder,
|
|
db: Session,
|
|
tenant_no: Optional[str],
|
|
) -> Dict[str, Any]:
|
|
out = _task_to_dict(t, wo.work_order_no or "", db, tenant_no)
|
|
out.update(_task_work_order_context(wo, t))
|
|
return out
|
|
|
|
|
|
def create_task_for_line(
|
|
db: Session,
|
|
*,
|
|
work_order: BizQcWorkOrder,
|
|
task_type: str,
|
|
source_line_id: str,
|
|
item_code: str,
|
|
item_name: str,
|
|
tenant_no: str,
|
|
user_id: Optional[str] = None,
|
|
create_dept_id: str = "",
|
|
seq: int = 1,
|
|
company_id: Optional[str] = None,
|
|
company_name: Optional[str] = None,
|
|
fee_amount: Optional[Decimal] = None,
|
|
order_source: str = "inbound",
|
|
) -> BizQcTask:
|
|
obj = BizQcTask(
|
|
id=generate_uuid(),
|
|
work_order_id=work_order.id,
|
|
order_source=order_source,
|
|
task_no=_gen_task_no(db, work_order, seq),
|
|
task_type=task_type,
|
|
source_line_id=source_line_id,
|
|
sample_code=getattr(work_order, "sample_code", None) or None,
|
|
item_code=item_code,
|
|
item_name=item_name,
|
|
company_id=company_id,
|
|
company_name=company_name,
|
|
fee_amount=fee_amount,
|
|
task_status="dzx",
|
|
tenant_no=tenant_no,
|
|
order_num=seq,
|
|
create_by=user_id,
|
|
create_dept_id=create_dept_id or "",
|
|
create_time=datetime.now(),
|
|
update_by=user_id,
|
|
update_time=datetime.now(),
|
|
del_flag=0,
|
|
)
|
|
db.add(obj)
|
|
db.flush()
|
|
return obj
|
|
|
|
|
|
def list_tasks(
|
|
db: Session,
|
|
*,
|
|
page: int = 1,
|
|
page_size: int = 10,
|
|
keyword: Optional[str] = None,
|
|
task_type: Optional[str] = None,
|
|
task_status: Optional[str] = None,
|
|
work_order_id: Optional[str] = None,
|
|
qc_biz_type: Optional[str] = None,
|
|
tenant_no: Optional[str] = None,
|
|
user_info=None,
|
|
) -> Tuple[List[Dict[str, Any]], int]:
|
|
def _filtered():
|
|
q0 = (
|
|
db.query(BizQcTask, BizQcWorkOrder)
|
|
.join(
|
|
BizQcWorkOrder,
|
|
and_(
|
|
BizQcWorkOrder.id == BizQcTask.work_order_id,
|
|
BizQcWorkOrder.del_flag == 0,
|
|
),
|
|
)
|
|
.filter(BizQcTask.del_flag == 0)
|
|
)
|
|
if tenant_no:
|
|
q0 = q0.filter(BizQcTask.tenant_no == tenant_no)
|
|
if work_order_id:
|
|
q0 = q0.filter(BizQcTask.work_order_id == work_order_id)
|
|
kw = (keyword or "").strip()
|
|
if kw:
|
|
like = f"%{kw}%"
|
|
q0 = q0.filter(
|
|
or_(
|
|
BizQcTask.task_no.like(like),
|
|
BizQcTask.item_name.like(like),
|
|
BizQcWorkOrder.work_order_no.like(like),
|
|
BizQcWorkOrder.sample_code.like(like),
|
|
BizQcWorkOrder.protocol_no.like(like),
|
|
)
|
|
)
|
|
tt = (task_type or "").strip()
|
|
if tt:
|
|
q0 = q0.filter(BizQcTask.task_type == tt)
|
|
st = (task_status or "").strip()
|
|
if st:
|
|
q0 = q0.filter(BizQcTask.task_status == st)
|
|
bt = (qc_biz_type or "").strip()
|
|
if bt:
|
|
if bt == "temporary":
|
|
q0 = q0.filter(
|
|
or_(
|
|
BizQcWorkOrder.qc_biz_type == "temporary",
|
|
BizQcWorkOrder.work_order_type == "temporary",
|
|
)
|
|
)
|
|
else:
|
|
q0 = q0.filter(BizQcWorkOrder.qc_biz_type == bt)
|
|
if user_info:
|
|
from app.core.data_scope import apply_data_scope
|
|
q0 = apply_data_scope(q0, BizQcTask, user_info, db, tenant_no)
|
|
return q0
|
|
|
|
total = _filtered().order_by(None).with_entities(func.count(BizQcTask.id)).scalar() or 0
|
|
page = max(1, page)
|
|
page_size = min(max(1, page_size), 100)
|
|
rows = (
|
|
_filtered()
|
|
.order_by(
|
|
BizQcTask.create_time.desc(),
|
|
BizQcWorkOrder.work_order_no.desc(),
|
|
BizQcTask.task_no.asc(),
|
|
)
|
|
.offset((page - 1) * page_size)
|
|
.limit(page_size)
|
|
.all()
|
|
)
|
|
items = [_task_row_to_dict(t, wo, db, tenant_no) for t, wo in rows]
|
|
return _enrich_tasks_reception_fields(db, items), int(total)
|
|
|
|
|
|
def list_tasks_by_work_order(db: Session, work_order_id: str, tenant_no: str) -> List[Dict[str, Any]]:
|
|
rows = (
|
|
db.query(BizQcTask, BizQcWorkOrder)
|
|
.join(BizQcWorkOrder, BizQcWorkOrder.id == BizQcTask.work_order_id)
|
|
.filter(
|
|
BizQcTask.work_order_id == work_order_id,
|
|
BizQcTask.tenant_no == tenant_no,
|
|
BizQcTask.del_flag == 0,
|
|
BizQcWorkOrder.del_flag == 0,
|
|
)
|
|
.order_by(BizQcTask.order_num.asc())
|
|
.all()
|
|
)
|
|
items = [_task_row_to_dict(t, wo, db, tenant_no) for t, wo in rows]
|
|
return _enrich_tasks_reception_fields(db, items)
|
|
|
|
|
|
def get_task(
|
|
db: Session, row_id: str, tenant_no: Optional[str] = None
|
|
) -> Optional[BizQcTask]:
|
|
q = db.query(BizQcTask).filter(BizQcTask.id == row_id, BizQcTask.del_flag == 0)
|
|
if tenant_no:
|
|
q = q.filter(BizQcTask.tenant_no == tenant_no)
|
|
return q.first()
|
|
|
|
|
|
def get_task_detail(db: Session, row_id: str, tenant_no: str) -> Dict[str, Any]:
|
|
row = (
|
|
db.query(BizQcTask, BizQcWorkOrder)
|
|
.join(BizQcWorkOrder, BizQcWorkOrder.id == BizQcTask.work_order_id)
|
|
.filter(
|
|
BizQcTask.id == row_id,
|
|
BizQcTask.tenant_no == tenant_no,
|
|
BizQcTask.del_flag == 0,
|
|
BizQcWorkOrder.del_flag == 0,
|
|
)
|
|
.first()
|
|
)
|
|
if not row:
|
|
raise ValueError("任务不存在")
|
|
t, wo = row
|
|
out = _task_row_to_dict(t, wo, db, tenant_no)
|
|
out = _enrich_tasks_reception_fields(db, [out])[0]
|
|
from app.crud.qc_work_order import _enrich_work_order_cell_products
|
|
|
|
out = _enrich_work_order_cell_products(db, tenant_no, [out])[0]
|
|
if (out.get("qcBizType") or "") != "temporary":
|
|
reception_detail = sample_reception_svc.get_reception_by_id(db, wo.reception_id, tenant_no)
|
|
if reception_detail:
|
|
out["reception"] = reception_detail
|
|
return out
|
|
|
|
|
|
def start_task(db: Session, row_id: str, *, tenant_no: str, user_id: Optional[str]) -> BizQcTask:
|
|
t = get_task(db, row_id, tenant_no=tenant_no)
|
|
if not t:
|
|
raise ValueError("任务不存在")
|
|
if t.task_type != "sysz":
|
|
raise ValueError("仅实验室自检任务可开始")
|
|
if t.task_status != "dzx":
|
|
raise ValueError("当前状态不可开始")
|
|
t.task_status = "jxz"
|
|
t.update_by = user_id
|
|
t.update_time = datetime.now()
|
|
db.add(t)
|
|
db.commit()
|
|
db.refresh(t)
|
|
return t
|
|
|
|
|
|
def _set_task_remark(t: BizQcTask, remark: Optional[str]) -> None:
|
|
t.remark = (remark or "").strip() or None
|
|
|
|
|
|
def complete_task(
|
|
db: Session,
|
|
row_id: str,
|
|
*,
|
|
tenant_no: str,
|
|
user_id: Optional[str],
|
|
conclusion: Optional[str] = None,
|
|
remark: Optional[str] = None,
|
|
commit: bool = True,
|
|
) -> BizQcTask:
|
|
t = get_task(db, row_id, tenant_no=tenant_no)
|
|
if not t:
|
|
raise ValueError("任务不存在")
|
|
concl = (conclusion or "").strip() if conclusion is not None else ""
|
|
if concl and concl not in ("tg", "btg"):
|
|
raise ValueError("检测结论无效")
|
|
if t.task_type == "sysz":
|
|
if t.task_status not in ("dzx", "jxz"):
|
|
raise ValueError("当前状态不可完成")
|
|
elif t.task_type == "dsfjc":
|
|
if not (t.third_party_attachments or "").strip():
|
|
raise ValueError("请先上传第三方检测材料")
|
|
else:
|
|
raise ValueError("任务类型无效")
|
|
t.task_status = "ywc"
|
|
if concl:
|
|
t.conclusion = concl
|
|
_set_task_remark(t, remark)
|
|
t.completed_time = datetime.now()
|
|
t.completed_by = user_id
|
|
t.update_by = user_id
|
|
t.update_time = datetime.now()
|
|
db.add(t)
|
|
if commit:
|
|
db.commit()
|
|
db.refresh(t)
|
|
from app.crud import qc_work_order as wo_svc
|
|
|
|
wo_svc.try_complete_work_order(db, t.work_order_id, tenant_no)
|
|
else:
|
|
db.flush()
|
|
return t
|
|
|
|
|
|
def apply_task_result(
|
|
db: Session,
|
|
row_id: str,
|
|
*,
|
|
tenant_no: str,
|
|
user_id: Optional[str],
|
|
conclusion: str,
|
|
remark: Optional[str] = None,
|
|
material_usages: Optional[List[Dict[str, Any]]] = None,
|
|
commit: bool = True,
|
|
) -> BizQcTask:
|
|
"""保存检测结果与结论;任务未完成时顺带标记为已完成。"""
|
|
from app.crud import qc_material_usage as mu_svc
|
|
|
|
t = get_task(db, row_id, tenant_no=tenant_no)
|
|
if not t:
|
|
raise ValueError("任务不存在")
|
|
concl = (conclusion or "").strip()
|
|
if concl not in ("tg", "btg"):
|
|
raise ValueError("请选择检测结论(通过/不通过)")
|
|
if material_usages is not None:
|
|
mu_svc.deduct_for_task(
|
|
db,
|
|
row_id,
|
|
task_no=t.task_no or "",
|
|
material_usages=material_usages,
|
|
tenant_no=tenant_no,
|
|
user_id=user_id,
|
|
)
|
|
if (t.task_status or "").strip() == "ywc":
|
|
t.conclusion = concl
|
|
_set_task_remark(t, remark if remark is not None else "")
|
|
t.update_by = user_id
|
|
t.update_time = datetime.now()
|
|
db.add(t)
|
|
if commit:
|
|
db.commit()
|
|
db.refresh(t)
|
|
else:
|
|
db.flush()
|
|
return t
|
|
return complete_task(
|
|
db,
|
|
row_id,
|
|
tenant_no=tenant_no,
|
|
user_id=user_id,
|
|
conclusion=concl,
|
|
remark=remark,
|
|
commit=commit,
|
|
)
|
|
|
|
|
|
def update_task_attachments(
|
|
db: Session,
|
|
row_id: str,
|
|
*,
|
|
attachments: str,
|
|
tenant_no: str,
|
|
user_id: Optional[str],
|
|
commit: bool = True,
|
|
) -> BizQcTask:
|
|
t = get_task(db, row_id, tenant_no=tenant_no)
|
|
if not t:
|
|
raise ValueError("任务不存在")
|
|
t.third_party_attachments = (attachments or "").strip() or None
|
|
if (
|
|
t.task_type == "dsfjc"
|
|
and t.task_status == "dzx"
|
|
and t.third_party_attachments
|
|
):
|
|
t.task_status = "jxz"
|
|
t.update_by = user_id
|
|
t.update_time = datetime.now()
|
|
db.add(t)
|
|
if commit:
|
|
db.commit()
|
|
db.refresh(t)
|
|
else:
|
|
db.flush()
|
|
return t
|
|
|
|
|
|
def create_qc_task_manual(
|
|
db: Session,
|
|
*,
|
|
tenant_no: str,
|
|
user_id: Optional[str] = None,
|
|
create_dept_id: str = "",
|
|
task_type: str = "sysz",
|
|
item_code: str = "",
|
|
item_name: str = "",
|
|
company_id: Optional[str] = None,
|
|
company_name: Optional[str] = None,
|
|
fee_amount: Optional[float] = None,
|
|
sample_code: str = "",
|
|
work_order_id: str = "",
|
|
remark: str = "",
|
|
) -> BizQcTask:
|
|
"""手动创建质检任务(可独立于工单)"""
|
|
# 生成任务号:ZJRW + 日期 + 序号
|
|
day = datetime.now().strftime("%Y%m%d")
|
|
like = f"ZJRW{day}%"
|
|
cnt = db.query(BizQcTask).filter(
|
|
BizQcTask.tenant_no == tenant_no,
|
|
BizQcTask.task_no.like(like),
|
|
).count()
|
|
task_no = f"ZJRW{day}{cnt + 1:04d}"
|
|
|
|
task = BizQcTask(
|
|
id=generate_uuid(),
|
|
work_order_id=work_order_id or "",
|
|
task_no=task_no,
|
|
task_type=task_type,
|
|
source_line_id="",
|
|
sample_code=sample_code,
|
|
item_code=item_code,
|
|
item_name=item_name,
|
|
company_id=company_id,
|
|
company_name=company_name,
|
|
fee_amount=fee_amount,
|
|
task_status="dzx",
|
|
tenant_no=tenant_no,
|
|
remark=remark,
|
|
create_by=user_id,
|
|
create_dept_id=create_dept_id,
|
|
)
|
|
db.add(task)
|
|
db.flush()
|
|
return task
|
|
|
|
|
|
def delete_qc_task(db: Session, task_id: str, tenant_no: str, user_id: Optional[str]) -> None:
|
|
"""软删除质检任务及其关联的检测结果"""
|
|
task = db.query(BizQcTask).filter(
|
|
and_(
|
|
BizQcTask.id == task_id,
|
|
BizQcTask.tenant_no == tenant_no,
|
|
BizQcTask.del_flag == 0,
|
|
)
|
|
).first()
|
|
if not task:
|
|
raise ValueError("任务不存在")
|
|
if task.task_status != "dzx":
|
|
raise ValueError("仅待执行的任务可以删除")
|
|
|
|
now = datetime.now()
|
|
|
|
# 软删除任务结果
|
|
from app.models.qc_param import BizQcTaskResult
|
|
|
|
results = db.query(BizQcTaskResult).filter(
|
|
and_(BizQcTaskResult.task_id == task_id, BizQcTaskResult.del_flag == 0)
|
|
).all()
|
|
for r in results:
|
|
r.del_flag = 1
|
|
r.update_by = user_id
|
|
r.update_time = now
|
|
|
|
# 软删除任务本体
|
|
task.del_flag = 1
|
|
task.update_by = user_id
|
|
task.update_time = now
|
|
|
|
db.commit()
|