feat(backend): add sample options for freight config dialog
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
971af93132
commit
f092b64a33
2 files changed
+196
-1
No files matched your search
@@ -100,6 +100,34 @@ async def list_sample_freights(
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/sample-freights/sample-options")
|
||||
async def list_sample_freight_options(
|
||||
page: int = Query(1, ge=1),
|
||||
pageSize: int = Query(20, ge=1, le=100, alias="pageSize"),
|
||||
keyword: Optional[str] = None,
|
||||
sampleSource: Optional[str] = None,
|
||||
user: dict = Depends(require_admin_or_super_admin),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
items, total = freight_svc.list_sample_options(
|
||||
db,
|
||||
tenant_no=tenant_no,
|
||||
page=page,
|
||||
page_size=pageSize,
|
||||
keyword=keyword,
|
||||
sample_source=sampleSource,
|
||||
)
|
||||
return success_response(
|
||||
{"list": items, "total": total, "page": page, "pageSize": pageSize}
|
||||
)
|
||||
except PermissionError as e:
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/sample-freights/{freight_id}")
|
||||
async def get_sample_freight(
|
||||
freight_id: str,
|
||||
|
||||
@@ -455,10 +455,177 @@ def get_freight_detail(db: Session, freight_id: str, tenant_no: str) -> Dict[str
|
||||
linked_sample_count=len(items),
|
||||
transport_mode_label=labels.get(obj.transport_mode or "", obj.transport_mode or ""),
|
||||
)
|
||||
data["items"] = [_item_to_dict(i) for i in items]
|
||||
protocol_no_map, type_name_map = _enrich_items_maps(db, items, tenant_no)
|
||||
enriched = []
|
||||
for i in items:
|
||||
key = f"{i.sample_source}|{i.sample_id}"
|
||||
enriched.append(
|
||||
_item_to_dict_enriched(
|
||||
i,
|
||||
protocol_no=protocol_no_map.get(key, ""),
|
||||
sample_type_name=type_name_map.get(key, ""),
|
||||
)
|
||||
)
|
||||
data["items"] = enriched
|
||||
return data
|
||||
|
||||
|
||||
def list_sample_options(
|
||||
db: Session,
|
||||
*,
|
||||
tenant_no: str,
|
||||
page: int = 1,
|
||||
page_size: int = 20,
|
||||
keyword: Optional[str] = None,
|
||||
sample_source: Optional[str] = None,
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
"""可选样本列表(配置运费弹窗),支持细胞存储 / 科研捐赠。"""
|
||||
page = max(1, int(page or 1))
|
||||
page_size = max(1, min(100, int(page_size or 20)))
|
||||
src = (sample_source or "").strip() or None
|
||||
if src and src not in (SAMPLE_SOURCE_CELL, SAMPLE_SOURCE_DONATION):
|
||||
raise ValueError("sampleSource 无效")
|
||||
kw = (keyword or "").strip()
|
||||
like = f"%{kw}%" if kw else None
|
||||
|
||||
rows: List[Dict[str, Any]] = []
|
||||
|
||||
if src in (None, SAMPLE_SOURCE_CELL):
|
||||
cq = (
|
||||
db.query(
|
||||
BizProtocolSample.id,
|
||||
BizProtocolSample.sample_code,
|
||||
BizProtocolSample.collection_protocol_id,
|
||||
BizProtocolSample.create_time,
|
||||
BizCollectionProtocol.protocol_no,
|
||||
BizCellSampleType.type_name,
|
||||
)
|
||||
.outerjoin(
|
||||
BizCollectionProtocol,
|
||||
and_(
|
||||
BizCollectionProtocol.id
|
||||
== BizProtocolSample.collection_protocol_id,
|
||||
BizCollectionProtocol.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.outerjoin(
|
||||
BizCellSampleType,
|
||||
and_(
|
||||
BizCellSampleType.id == BizProtocolSample.sample_type_id,
|
||||
BizCellSampleType.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.filter(
|
||||
BizProtocolSample.tenant_no == tenant_no,
|
||||
BizProtocolSample.del_flag == 0,
|
||||
)
|
||||
)
|
||||
if like:
|
||||
cq = cq.filter(
|
||||
or_(
|
||||
BizProtocolSample.sample_code.like(like),
|
||||
BizCollectionProtocol.protocol_no.like(like),
|
||||
)
|
||||
)
|
||||
for sid, scode, pid, ctime, pno, tname in cq.all():
|
||||
rows.append(
|
||||
{
|
||||
"sampleSource": SAMPLE_SOURCE_CELL,
|
||||
"sampleId": sid,
|
||||
"sampleCode": scode or "",
|
||||
"protocolId": pid or "",
|
||||
"protocolNo": pno or "",
|
||||
"sampleTypeName": tname or "",
|
||||
"createTime": ctime,
|
||||
"freightId": "",
|
||||
}
|
||||
)
|
||||
|
||||
if src in (None, SAMPLE_SOURCE_DONATION):
|
||||
dq = (
|
||||
db.query(
|
||||
BizResearchDonationSample.id,
|
||||
BizResearchDonationSample.sample_code,
|
||||
BizResearchDonationSample.research_donation_id,
|
||||
BizResearchDonationSample.create_time,
|
||||
BizResearchDonation.donation_no,
|
||||
BizCellSampleType.type_name,
|
||||
)
|
||||
.outerjoin(
|
||||
BizResearchDonation,
|
||||
and_(
|
||||
BizResearchDonation.id
|
||||
== BizResearchDonationSample.research_donation_id,
|
||||
BizResearchDonation.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.outerjoin(
|
||||
BizCellSampleType,
|
||||
and_(
|
||||
BizCellSampleType.id == BizResearchDonationSample.sample_type_id,
|
||||
BizCellSampleType.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.filter(
|
||||
BizResearchDonationSample.tenant_no == tenant_no,
|
||||
BizResearchDonationSample.del_flag == 0,
|
||||
)
|
||||
)
|
||||
if like:
|
||||
dq = dq.filter(
|
||||
or_(
|
||||
BizResearchDonationSample.sample_code.like(like),
|
||||
BizResearchDonation.donation_no.like(like),
|
||||
)
|
||||
)
|
||||
for sid, scode, pid, ctime, dno, tname in dq.all():
|
||||
rows.append(
|
||||
{
|
||||
"sampleSource": SAMPLE_SOURCE_DONATION,
|
||||
"sampleId": sid,
|
||||
"sampleCode": scode or "",
|
||||
"protocolId": pid or "",
|
||||
"protocolNo": dno or "",
|
||||
"sampleTypeName": tname or "",
|
||||
"createTime": ctime,
|
||||
"freightId": "",
|
||||
}
|
||||
)
|
||||
|
||||
# 左连当前运费关联
|
||||
if rows:
|
||||
sample_ids = [r["sampleId"] for r in rows]
|
||||
link_rows = (
|
||||
db.query(
|
||||
BizSampleFreightItem.sample_source,
|
||||
BizSampleFreightItem.sample_id,
|
||||
BizSampleFreightItem.freight_id,
|
||||
)
|
||||
.filter(
|
||||
BizSampleFreightItem.tenant_no == tenant_no,
|
||||
BizSampleFreightItem.del_flag == 0,
|
||||
BizSampleFreightItem.sample_id.in_(sample_ids),
|
||||
)
|
||||
.all()
|
||||
)
|
||||
freight_map = {
|
||||
f"{src_}|{sid}": fid for src_, sid, fid in link_rows if src_ and sid and fid
|
||||
}
|
||||
for r in rows:
|
||||
r["freightId"] = freight_map.get(f"{r['sampleSource']}|{r['sampleId']}", "") or ""
|
||||
|
||||
rows.sort(
|
||||
key=lambda r: (r["createTime"] or datetime.min, r["sampleId"]),
|
||||
reverse=True,
|
||||
)
|
||||
total = len(rows)
|
||||
start = (page - 1) * page_size
|
||||
page_rows = rows[start : start + page_size]
|
||||
for r in page_rows:
|
||||
r["createTime"] = _fmt_dt(r.get("createTime"))
|
||||
return page_rows, total
|
||||
|
||||
|
||||
def _upsert_item(
|
||||
db: Session,
|
||||
*,
|
||||
|
||||
Reference in new issue
Block a user