Files
zkxw/backend/app/api/presign_order.py
T
2026-10-14 12:32:03 +08:00

411 lines
14 KiB
Python

"""预签约订单 / 意向金转账 / 转正式 API"""
from __future__ import annotations
from typing import Any, Dict, List, 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_admin_or_super_admin, require_strict_menu_code
from app.core.response import error_response, success_response
from app.crud import presign_order as po_svc
from app.models.models import SysUser
router = APIRouter(prefix="/web/admin", tags=["细胞存储-预签约订单"])
PAYMENT_CONFIRM_MENU = "biz:cellStoragePaymentConfirm:list"
def _get_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 _get_current_user_id(user: dict) -> str:
user_id = user.get("user_id")
if not user_id:
raise PermissionError("用户身份信息缺失")
return str(user_id)
class PresignOrderBody(BaseModel):
model_config = ConfigDict(extra="ignore", populate_by_name=True)
order_date: Optional[str] = Field(None, alias="orderDate")
protocol_no: Optional[str] = Field(None, alias="protocolNo")
mother_name: Optional[str] = Field(None, alias="motherName")
expected_delivery_date: Optional[str] = Field(None, alias="expectedDeliveryDate")
region_id: Optional[str] = Field(None, alias="regionId")
hospital_id: Optional[str] = Field(None, alias="hospitalId")
sample_collect_time: Optional[str] = Field(None, alias="sampleCollectTime")
pay_mode: Optional[str] = Field(None, alias="payMode")
contract_amount: Optional[float] = Field(None, alias="contractAmount")
collector_user_id: Optional[str] = Field(None, alias="collectorUserId")
sales_user_id: Optional[str] = Field(None, alias="salesUserId")
region_manager_user_id: Optional[str] = Field(None, alias="regionManagerUserId")
order_status: Optional[str] = Field(None, alias="orderStatus")
remark: Optional[str] = None
sample_type_ids: Optional[List[str]] = Field(None, alias="sampleTypeIds")
transfers: Optional[List[Dict[str, Any]]] = None
class PresignTransferBody(BaseModel):
model_config = ConfigDict(extra="ignore", populate_by_name=True)
transfer_amount: Optional[float] = Field(None, alias="transferAmount")
transfer_time: Optional[str] = Field(None, alias="transferTime")
transfer_type: Optional[str] = Field(None, alias="transferType")
transfer_attachments: Optional[str] = Field(None, alias="transferAttachments")
remark: Optional[str] = None
class FinanceConfirmBody(BaseModel):
model_config = ConfigDict(extra="ignore", populate_by_name=True)
finance_confirm_attachments: Optional[str] = Field(
None, alias="financeConfirmAttachments"
)
finance_remark: Optional[str] = Field(None, alias="financeRemark")
@router.get("/presign-orders")
async def list_presign_orders(
page: int = Query(1, ge=1),
pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
keyword: Optional[str] = None,
orderStatus: Optional[str] = Query(None, alias="orderStatus"),
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
items, total = po_svc.list_presign_orders(
db,
tenant_no=tenant_no,
page=page,
page_size=pageSize,
keyword=keyword,
order_status=orderStatus,
user_info=user,
)
return success_response(
{"list": items, "total": total, "page": page, "pageSize": pageSize}
)
except PermissionError as e:
return error_response(403, str(e))
@router.get("/presign-orders/{order_id}")
async def get_presign_order(
order_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
data = po_svc.get_presign_order(db, order_id=order_id, tenant_no=tenant_no)
if not data:
return error_response(404, "预签约订单不存在")
return success_response(data)
except PermissionError as e:
return error_response(403, str(e))
@router.post("/presign-orders")
async def create_presign_order(
body: PresignOrderBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
dumped = body.model_dump(by_alias=False)
obj = po_svc.create_presign_order(
db,
tenant_no=tenant_no,
user_id=user_id,
fields=dumped,
sample_type_ids=body.sample_type_ids,
transfers=body.transfers,
)
return success_response(
po_svc.order_to_dict(db, obj, tenant_no, with_children=True),
message="创建成功",
)
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
@router.put("/presign-orders/{order_id}")
async def update_presign_order(
order_id: str,
body: PresignOrderBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
dumped = body.model_dump(by_alias=False, exclude_unset=True)
sample_type_ids = dumped.pop("sample_type_ids", None)
dumped.pop("transfers", None)
obj = po_svc.update_presign_order(
db,
order_id=order_id,
tenant_no=tenant_no,
user_id=user_id,
fields=dumped,
sample_type_ids=sample_type_ids,
)
return success_response(
po_svc.order_to_dict(db, obj, tenant_no, with_children=True),
message="保存成功",
)
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
@router.delete("/presign-orders/{order_id}")
async def delete_presign_order(
order_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
po_svc.soft_delete_presign_order(
db, order_id=order_id, tenant_no=tenant_no, user_id=user_id
)
return success_response(None, message="删除成功")
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
@router.post("/presign-orders/{order_id}/convert")
async def convert_presign_order(
order_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
data = po_svc.convert_to_protocol(
db, order_id=order_id, tenant_no=tenant_no, user_id=user_id
)
return success_response(data, message="已转正式协议")
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
@router.post("/presign-orders/{order_id}/transfers")
async def create_presign_transfer(
order_id: str,
body: PresignTransferBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
obj = po_svc.add_transfer(
db,
presign_order_id=order_id,
tenant_no=tenant_no,
user_id=user_id,
fields=body.model_dump(by_alias=False),
)
return success_response(
po_svc._transfer_to_dict(db, obj, tenant_no), message="添加成功"
)
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
@router.put("/presign-transfers/{transfer_id}")
async def update_presign_transfer(
transfer_id: str,
body: PresignTransferBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
obj = po_svc.update_transfer_draft(
db,
transfer_id=transfer_id,
tenant_no=tenant_no,
user_id=user_id,
fields=body.model_dump(by_alias=False, exclude_unset=True),
)
return success_response(
po_svc._transfer_to_dict(db, obj, tenant_no), message="保存成功"
)
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
@router.post("/presign-transfers/{transfer_id}/submit-receipt-finance")
async def submit_presign_transfer_finance(
transfer_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
obj = po_svc.submit_receipt_finance(
db, transfer_id=transfer_id, tenant_no=tenant_no, user_id=user_id
)
return success_response(
po_svc._transfer_to_dict(db, obj, tenant_no), message="已提交财务确认"
)
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
@router.post("/presign-transfers/{transfer_id}/withdraw")
async def withdraw_presign_transfer(
transfer_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
obj = po_svc.withdraw_receipt(
db, transfer_id=transfer_id, tenant_no=tenant_no, user_id=user_id
)
return success_response(
po_svc._transfer_to_dict(db, obj, tenant_no), message="已撤回"
)
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
@router.get("/presign-transfers/receipt-confirm")
async def list_presign_receipt_confirm(
page: int = Query(1, ge=1),
pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
keyword: 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 = po_svc.list_presign_transfers_for_finance(
db,
pay_status="jfqrz",
tenant_no=tenant_no,
keyword=keyword,
page=page,
page_size=pageSize,
user_info=user,
)
return success_response(
{"list": items, "total": total, "page": page, "pageSize": pageSize}
)
except PermissionError as e:
return error_response(403, str(e))
@router.get("/presign-transfers/receipt-confirmed")
async def list_presign_receipt_confirmed(
page: int = Query(1, ge=1),
pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
keyword: 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 = po_svc.list_presign_transfers_for_finance(
db,
pay_status="yjf",
tenant_no=tenant_no,
keyword=keyword,
page=page,
page_size=pageSize,
user_info=user,
)
return success_response(
{"list": items, "total": total, "page": page, "pageSize": pageSize}
)
except PermissionError as e:
return error_response(403, str(e))
@router.post("/presign-transfers/{transfer_id}/receipt-confirm")
async def confirm_presign_transfer(
transfer_id: str,
body: Optional[FinanceConfirmBody] = None,
user: dict = Depends(require_strict_menu_code(PAYMENT_CONFIRM_MENU)),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
obj = po_svc.confirm_receipt(
db,
transfer_id=transfer_id,
tenant_no=tenant_no,
user_id=user_id,
finance_confirm_attachments=body.finance_confirm_attachments if body else None,
finance_remark=body.finance_remark if body else None,
)
return success_response(
po_svc._transfer_to_dict(db, obj, tenant_no), message="确认收款成功"
)
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
@router.post("/presign-transfers/{transfer_id}/receipt-reject")
async def reject_presign_transfer(
transfer_id: str,
user: dict = Depends(require_strict_menu_code(PAYMENT_CONFIRM_MENU)),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
obj = po_svc.reject_receipt(
db, transfer_id=transfer_id, tenant_no=tenant_no, user_id=user_id
)
return success_response(
po_svc._transfer_to_dict(db, obj, tenant_no), message="已退回"
)
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))