2026-10-13 00:25:33 -04:00
|
|
|
|
"""发货管理接口(需求 2.2.2)。
|
|
|
|
|
|
|
|
|
|
|
|
校验规则(状态门槛、行金额固化、双重汇总回写、删除保护)见
|
|
|
|
|
|
`shipment_service` 模块 docstring;业务数据属业务操作,登录即可访问。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from typing import Annotated
|
|
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter, Depends, Path, Query
|
|
|
|
|
|
|
|
|
|
|
|
from app.api.deps import DbSession, RequestMetaDep, get_current_user
|
|
|
|
|
|
from app.core.response import ApiResponse, PageResult, ok
|
|
|
|
|
|
from app.models import User
|
|
|
|
|
|
from app.schemas.shipment import (
|
|
|
|
|
|
ShipmentCreateIn,
|
|
|
|
|
|
ShipmentDetailOut,
|
|
|
|
|
|
ShipmentOut,
|
|
|
|
|
|
ShipmentQuery,
|
|
|
|
|
|
ShipmentUpdateIn,
|
|
|
|
|
|
)
|
|
|
|
|
|
from app.services import shipment_service
|
|
|
|
|
|
|
|
|
|
|
|
# 基础数据是业务操作:登录即可,不要求管理员(区别于系统管理的 AdminUser)
|
|
|
|
|
|
CurrentUser = Annotated[User, Depends(get_current_user)]
|
|
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/shipments", tags=["发货管理"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("", response_model=ApiResponse[PageResult[ShipmentOut]], summary="发货单列表")
|
|
|
|
|
|
def list_shipments(
|
|
|
|
|
|
session: DbSession,
|
|
|
|
|
|
_: CurrentUser,
|
|
|
|
|
|
query: Annotated[ShipmentQuery, Query()],
|
|
|
|
|
|
) -> ApiResponse[PageResult[ShipmentOut]]:
|
|
|
|
|
|
"""分页查询发货单(附业务编号),可按业务/发货日期范围筛选。"""
|
|
|
|
|
|
return ok(shipment_service.list_shipments(session, query))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("", response_model=ApiResponse[ShipmentOut], summary="创建发货单")
|
|
|
|
|
|
def create_shipment(
|
|
|
|
|
|
session: DbSession,
|
|
|
|
|
|
current_user: CurrentUser,
|
|
|
|
|
|
payload: ShipmentCreateIn,
|
|
|
|
|
|
meta: RequestMetaDep,
|
|
|
|
|
|
) -> ApiResponse[ShipmentOut]:
|
|
|
|
|
|
"""创建发货单(明细 ≥1)。业务须处于执行中;锁业务行后生成 SH 编号。"""
|
|
|
|
|
|
return ok(
|
|
|
|
|
|
shipment_service.create_shipment(session, payload, operator=current_user, meta=meta),
|
|
|
|
|
|
message="发货单已创建",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-10-14 06:46:43 -04:00
|
|
|
|
@router.get("/{shipment_id}", response_model=ApiResponse[ShipmentDetailOut], summary="发货单详情")
|
2026-10-13 00:25:33 -04:00
|
|
|
|
def get_shipment(
|
|
|
|
|
|
session: DbSession,
|
|
|
|
|
|
_: CurrentUser,
|
|
|
|
|
|
shipment_id: Annotated[int, Path(ge=1)],
|
|
|
|
|
|
) -> ApiResponse[ShipmentDetailOut]:
|
|
|
|
|
|
"""发货单详情,附产品明细行,供编辑抽屉一次回显。"""
|
|
|
|
|
|
return ok(shipment_service.get_detail(session, shipment_id))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.put("/{shipment_id}", response_model=ApiResponse[ShipmentOut], summary="编辑发货单")
|
|
|
|
|
|
def update_shipment(
|
|
|
|
|
|
session: DbSession,
|
|
|
|
|
|
current_user: CurrentUser,
|
|
|
|
|
|
shipment_id: Annotated[int, Path(ge=1)],
|
|
|
|
|
|
payload: ShipmentUpdateIn,
|
|
|
|
|
|
meta: RequestMetaDep,
|
|
|
|
|
|
) -> ApiResponse[ShipmentOut]:
|
|
|
|
|
|
"""编辑发货单(明细全量替换并重算汇总)。终态业务的发货单禁改。"""
|
|
|
|
|
|
return ok(
|
|
|
|
|
|
shipment_service.update_shipment(
|
|
|
|
|
|
session, shipment_id, payload, operator=current_user, meta=meta
|
|
|
|
|
|
),
|
|
|
|
|
|
message="已保存",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete("/{shipment_id}", response_model=ApiResponse[None], summary="删除发货单")
|
|
|
|
|
|
def delete_shipment(
|
|
|
|
|
|
session: DbSession,
|
|
|
|
|
|
current_user: CurrentUser,
|
|
|
|
|
|
shipment_id: Annotated[int, Path(ge=1)],
|
|
|
|
|
|
meta: RequestMetaDep,
|
|
|
|
|
|
) -> ApiResponse[None]:
|
|
|
|
|
|
"""删除发货单(连带明细行并回写业务汇总)。被回款批次指定时禁删。"""
|
|
|
|
|
|
shipment_service.delete_shipment(session, shipment_id, operator=current_user, meta=meta)
|
|
|
|
|
|
return ok(message="发货单已删除")
|