2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
物流任务管理路由模块
|
|
|
|
|
|
|
|
|
|
|
|
提供物流运输任务的全生命周期管理接口,包括:
|
|
|
|
|
|
- 物流任务的创建、查询、取消(管理端)
|
|
|
|
|
|
- 司机端任务的接单、提货、送达操作
|
|
|
|
|
|
- 物流轨迹的查询与新增
|
|
|
|
|
|
|
|
|
|
|
|
URL 前缀:/api/logistics、/api/driver
|
|
|
|
|
|
权限要求:manager/admin 管理端操作,driver 司机端操作
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
2026-05-14 15:17:56 +08:00
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
|
|
|
|
from sqlalchemy.orm import Session
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
2026-05-15 14:33:09 +08:00
|
|
|
|
from backend.app.api.deps import get_logistics_service, require_permissions, require_roles
|
2026-05-14 15:17:56 +08:00
|
|
|
|
from backend.app.db import get_db_session
|
2026-05-14 13:51:06 +08:00
|
|
|
|
from backend.app.schemas.common import success_payload
|
2026-05-30 16:13:33 +08:00
|
|
|
|
from backend.app.schemas.logistics import CreateLogisticsTaskRequest, CreateLogisticsTraceRequest, DriverTaskOperateRequest, UpdateTrackingRequest
|
2026-05-14 15:17:56 +08:00
|
|
|
|
from backend.app.services.logistics_service import LogisticsService
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
router = APIRouter(tags=["logistics"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/api/logistics/tasks")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def list_logistics_tasks(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
order_id: int | None = Query(default=None), # 按订单ID筛选
|
|
|
|
|
|
task_no: str | None = Query(default=None), # 按任务编号精确搜索
|
|
|
|
|
|
status: str | None = Query(default=None), # 按任务状态筛选(如 pending/in_transit/completed)
|
|
|
|
|
|
driver_id: int | None = Query(default=None), # 按司机ID筛选
|
|
|
|
|
|
factory_id: int | None = Query(default=None), # 按工厂ID筛选
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("manager", "admin")), # 当前登录用户,仅manager和admin可访问
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("logistics:task:list")), # 权限校验:物流任务查看权限
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
获取物流任务列表(管理端)
|
|
|
|
|
|
|
|
|
|
|
|
支持按订单ID、任务编号、状态、司机ID、工厂ID进行筛选查询。
|
|
|
|
|
|
仅管理员和经理角色可访问。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
order_id: 订单ID(可选)
|
|
|
|
|
|
task_no: 任务编号(可选)
|
|
|
|
|
|
status: 任务状态(可选)
|
|
|
|
|
|
driver_id: 司机ID(可选)
|
|
|
|
|
|
factory_id: 工厂ID(可选)
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
包含物流任务列表的分页数据
|
|
|
|
|
|
"""
|
2026-05-14 15:17:56 +08:00
|
|
|
|
return success_payload(
|
|
|
|
|
|
logistics_service.list_tasks(
|
|
|
|
|
|
session=session,
|
|
|
|
|
|
filters={
|
|
|
|
|
|
"order_id": order_id,
|
|
|
|
|
|
"task_no": task_no,
|
|
|
|
|
|
"status": status,
|
|
|
|
|
|
"driver_id": driver_id,
|
|
|
|
|
|
"factory_id": factory_id,
|
|
|
|
|
|
},
|
2026-05-15 12:05:18 +08:00
|
|
|
|
current_user=current_user,
|
2026-05-14 15:17:56 +08:00
|
|
|
|
)
|
|
|
|
|
|
)
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/api/logistics/tasks")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def create_logistics_task(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
payload: CreateLogisticsTaskRequest, # 创建物流任务请求体,包含订单ID、司机ID等信息
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("manager", "admin")), # 当前登录用户
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("logistics:task:create")), # 权限校验:物流任务创建权限
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
创建物流任务
|
|
|
|
|
|
|
|
|
|
|
|
为指定订单创建新的物流运输任务,分配司机并启动物流流程。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
payload: CreateLogisticsTaskRequest 请求体,包含订单关联信息
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
新创建的物流任务详情
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:manager、admin 角色,需 logistics:task:create 权限
|
|
|
|
|
|
"""
|
2026-05-15 12:05:18 +08:00
|
|
|
|
return success_payload(logistics_service.create_task(payload.model_dump(), session, current_user))
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/api/logistics/tasks/{task_id}")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def get_logistics_task(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
task_id: int, # 物流任务ID
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("manager", "admin")), # 当前登录用户
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("logistics:task:create")), # 权限校验
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
获取物流任务详情
|
|
|
|
|
|
|
|
|
|
|
|
根据任务ID查询物流任务的完整信息,包括关联的订单和司机信息。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
task_id: 路径参数,物流任务ID
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
物流任务详情信息
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:manager、admin 角色
|
|
|
|
|
|
"""
|
2026-05-15 12:05:18 +08:00
|
|
|
|
return success_payload(logistics_service.get_task(task_id, session, current_user))
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-30 16:13:33 +08:00
|
|
|
|
@router.put("/api/logistics/tasks/{task_id}/tracking")
|
|
|
|
|
|
def update_tracking_number(
|
|
|
|
|
|
task_id: int, # 物流任务ID
|
|
|
|
|
|
payload: UpdateTrackingRequest, # 修改物流单号请求体
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service),
|
|
|
|
|
|
session: Session = Depends(get_db_session),
|
|
|
|
|
|
current_user: dict = Depends(require_roles("salesman", "manager", "admin")),
|
|
|
|
|
|
) -> dict:
|
|
|
|
|
|
"""
|
|
|
|
|
|
修改物流单号
|
|
|
|
|
|
|
|
|
|
|
|
业务员或管理员修改已有物流任务的快递单号和快递公司。
|
|
|
|
|
|
业务员仅可修改自己订单关联的物流任务。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
task_id: 路径参数,物流任务ID
|
|
|
|
|
|
payload: UpdateTrackingRequest 请求体
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
更新后的物流任务信息
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:salesman、manager、admin 角色
|
|
|
|
|
|
"""
|
|
|
|
|
|
return success_payload(logistics_service.update_tracking(task_id, payload.model_dump(), session, current_user))
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-05-14 13:51:06 +08:00
|
|
|
|
@router.get("/api/driver/tasks")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def list_driver_tasks(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("driver")), # 当前登录用户,仅司机角色
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("driver:task:list")), # 权限校验:司机任务列表权限
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
获取司机任务列表(司机端)
|
|
|
|
|
|
|
|
|
|
|
|
返回当前登录司机的待处理任务列表。
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
当前司机的物流任务列表
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:driver 角色,需 driver:task:list 权限
|
|
|
|
|
|
"""
|
2026-05-15 12:05:18 +08:00
|
|
|
|
return success_payload(logistics_service.list_driver_tasks(session, current_user))
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/api/driver/tasks/{task_id}")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def get_driver_task(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
task_id: int, # 物流任务ID
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("driver")), # 当前登录用户,仅司机角色
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("driver:task:list")), # 权限校验
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
获取司机任务详情(司机端)
|
|
|
|
|
|
|
|
|
|
|
|
根据任务ID查询当前司机的物流任务详情。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
task_id: 路径参数,物流任务ID
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
物流任务详情信息
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:driver 角色,需 driver:task:list 权限
|
|
|
|
|
|
"""
|
2026-05-15 12:05:18 +08:00
|
|
|
|
return success_payload(logistics_service.get_driver_task(task_id, session, current_user))
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/api/driver/tasks/{task_id}/accept")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def accept_driver_task(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
task_id: int, # 物流任务ID
|
|
|
|
|
|
payload: DriverTaskOperateRequest, # 司机操作请求体,包含操作备注等信息
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("driver")), # 当前登录用户,仅司机角色
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("driver:task:accept")), # 权限校验:接单权限
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
司机接单操作
|
|
|
|
|
|
|
|
|
|
|
|
司机接受指定的物流任务,任务状态变更为已接单。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
task_id: 路径参数,物流任务ID
|
|
|
|
|
|
payload: DriverTaskOperateRequest 请求体,包含操作备注
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
接单后的任务详情
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:driver 角色,需 driver:task:accept 权限
|
|
|
|
|
|
"""
|
2026-05-15 12:05:18 +08:00
|
|
|
|
return success_payload(logistics_service.accept_task(task_id, payload.model_dump(), session, current_user))
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/api/driver/tasks/{task_id}/pickup")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def pickup_driver_task(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
task_id: int, # 物流任务ID
|
|
|
|
|
|
payload: DriverTaskOperateRequest, # 司机操作请求体,包含提货备注等信息
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("driver")), # 当前登录用户,仅司机角色
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("driver:task:pickup")), # 权限校验:提货权限
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
司机提货操作
|
|
|
|
|
|
|
|
|
|
|
|
司机确认提货,任务状态变更为运输中。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
task_id: 路径参数,物流任务ID
|
|
|
|
|
|
payload: DriverTaskOperateRequest 请求体,包含提货备注
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
提货后的任务详情
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:driver 角色,需 driver:task:pickup 权限
|
|
|
|
|
|
"""
|
2026-05-15 12:05:18 +08:00
|
|
|
|
return success_payload(logistics_service.pickup_task(task_id, payload.model_dump(), session, current_user))
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/api/driver/tasks/{task_id}/deliver")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def deliver_driver_task(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
task_id: int, # 物流任务ID
|
|
|
|
|
|
payload: DriverTaskOperateRequest, # 司机操作请求体,包含送达备注等信息
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("driver")), # 当前登录用户,仅司机角色
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("driver:task:deliver")), # 权限校验:送达权限
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
司机送达操作
|
|
|
|
|
|
|
|
|
|
|
|
司机确认货物已送达目的地,任务状态变更为已完成。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
task_id: 路径参数,物流任务ID
|
|
|
|
|
|
payload: DriverTaskOperateRequest 请求体,包含送达备注
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
送达后的任务详情
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:driver 角色,需 driver:task:deliver 权限
|
|
|
|
|
|
"""
|
2026-05-15 12:05:18 +08:00
|
|
|
|
return success_payload(logistics_service.deliver_task(task_id, payload.model_dump(), session, current_user))
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-19 17:30:35 +08:00
|
|
|
|
@router.post("/api/logistics/tasks/{task_id}/cancel")
|
|
|
|
|
|
def cancel_logistics_task(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
task_id: int, # 物流任务ID
|
|
|
|
|
|
payload: DriverTaskOperateRequest, # 操作请求体,包含取消原因等信息
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("manager", "admin")), # 当前登录用户,仅manager和admin
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("logistics:task:cancel")), # 权限校验:任务取消权限
|
2026-05-19 17:30:35 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
取消物流任务(管理端)
|
|
|
|
|
|
|
|
|
|
|
|
管理员取消指定的物流任务,任务状态变更为已取消。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
task_id: 路径参数,物流任务ID
|
|
|
|
|
|
payload: DriverTaskOperateRequest 请求体,包含取消原因
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
取消后的任务详情
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:manager、admin 角色,需 logistics:task:cancel 权限
|
|
|
|
|
|
"""
|
2026-05-19 17:30:35 +08:00
|
|
|
|
return success_payload(logistics_service.cancel_task(task_id, payload.model_dump(), session, current_user))
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-05-14 13:51:06 +08:00
|
|
|
|
@router.get("/api/logistics/{order_id}/trace")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def get_logistics_trace(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
order_id: int, # 订单ID
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("manager", "admin", "driver")), # 当前登录用户
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("logistics:trace:list")), # 权限校验:轨迹查看权限
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
查询物流轨迹
|
|
|
|
|
|
|
|
|
|
|
|
根据订单ID查询该订单的完整物流运输轨迹记录。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
order_id: 路径参数,订单ID
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
物流轨迹列表,按时间倒序排列
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:manager、admin、driver 角色,需 logistics:trace:list 权限
|
|
|
|
|
|
"""
|
2026-05-15 12:05:18 +08:00
|
|
|
|
return success_payload(logistics_service.get_trace(order_id, session, current_user))
|
2026-05-14 13:51:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/api/logistics/{order_id}/trace")
|
2026-05-14 15:17:56 +08:00
|
|
|
|
def create_logistics_trace(
|
2026-05-30 07:23:33 +08:00
|
|
|
|
order_id: int, # 订单ID
|
|
|
|
|
|
payload: CreateLogisticsTraceRequest, # 创建轨迹请求体,包含轨迹状态、备注等信息
|
|
|
|
|
|
logistics_service: LogisticsService = Depends(get_logistics_service), # 物流服务实例
|
|
|
|
|
|
session: Session = Depends(get_db_session), # 数据库会话
|
|
|
|
|
|
current_user: dict = Depends(require_roles("manager", "admin", "driver")), # 当前登录用户
|
|
|
|
|
|
_permission_user: dict = Depends(require_permissions("logistics:trace:create")), # 权限校验:轨迹创建权限
|
2026-05-14 15:17:56 +08:00
|
|
|
|
) -> dict:
|
2026-05-30 07:23:33 +08:00
|
|
|
|
"""
|
|
|
|
|
|
新增物流轨迹记录
|
|
|
|
|
|
|
|
|
|
|
|
为指定订单添加一条新的物流轨迹记录,如更新运输状态、添加备注等。
|
|
|
|
|
|
|
|
|
|
|
|
请求参数:
|
|
|
|
|
|
order_id: 路径参数,订单ID
|
|
|
|
|
|
payload: CreateLogisticsTraceRequest 请求体,包含轨迹详情
|
|
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
|
新创建的轨迹记录信息
|
|
|
|
|
|
|
|
|
|
|
|
权限要求:manager、admin、driver 角色,需 logistics:trace:create 权限
|
|
|
|
|
|
"""
|
2026-05-15 12:05:18 +08:00
|
|
|
|
return success_payload(logistics_service.create_trace(order_id, payload.model_dump(), session, current_user))
|