dingdanquanliucheng/backend/app/repositories/logistics_repository.py

179 lines
7.1 KiB
Python
Raw Normal View History

"""
物流数据访问层
负责封装物流任务LogisticsTask和物流跟踪记录LogisticsTrace的数据库查询操作
提供物流任务的条件筛选创建状态更新以及物流节点跟踪记录的查询和创建等功能
OrderServiceLogisticsService 调用
"""
2026-05-14 15:17:56 +08:00
from sqlalchemy import select
from sqlalchemy.orm import Session
from backend.app.models.business import LogisticsTask, LogisticsTrace, LogisticsWaybill
2026-05-14 15:17:56 +08:00
class LogisticsRepository:
"""物流数据访问层,封装物流任务和物流跟踪表的数据库操作。
OrderServiceLogisticsService 调用
"""
2026-05-14 15:17:56 +08:00
def list_tasks_by_filters(self, session: Session, filters: dict) -> list[LogisticsTask]:
"""根据筛选条件查询物流任务列表,支持按订单 ID、任务号、状态、司机、工厂筛选。
:param session: 数据库会话
:param filters: 筛选条件字典可包含 order_idtask_no模糊
statusdriver_idfactory_id 等键
:return: 符合条件的物流任务列表 id 降序排列
LogisticsService.list_tasks 调用
"""
2026-05-14 15:17:56 +08:00
stmt = select(LogisticsTask).where(LogisticsTask.deleted == 0)
if filters.get("order_id") is not None:
stmt = stmt.where(LogisticsTask.order_id == filters["order_id"])
if filters.get("task_no"):
stmt = stmt.where(LogisticsTask.task_no.contains(filters["task_no"]))
if filters.get("status"):
stmt = stmt.where(LogisticsTask.status == filters["status"])
if filters.get("driver_id") is not None:
stmt = stmt.where(LogisticsTask.driver_id == filters["driver_id"])
if filters.get("factory_id") is not None:
stmt = stmt.where(LogisticsTask.factory_id == filters["factory_id"])
stmt = stmt.order_by(LogisticsTask.id.desc())
return list(session.execute(stmt).scalars())
def get_task(self, session: Session, task_id: int) -> LogisticsTask | None:
"""根据 ID 获取单个物流任务详情。
:param session: 数据库会话
:param task_id: 物流任务主键 ID
:return: 物流任务对象不存在则返回 None
LogisticsService.get_task 调用
"""
2026-05-14 15:17:56 +08:00
stmt = select(LogisticsTask).where(LogisticsTask.id == task_id, LogisticsTask.deleted == 0)
return session.execute(stmt).scalar_one_or_none()
def get_task_by_order_id(self, session: Session, order_id: int) -> LogisticsTask | None:
"""根据订单 ID 获取关联的最新物流任务(按 id 降序取第一条)。
:param session: 数据库会话
:param order_id: 订单主键 ID
:return: 最新的物流任务对象不存在则返回 None
OrderService 在查询订单详情时关联获取物流信息调用
"""
2026-05-14 15:17:56 +08:00
stmt = (
select(LogisticsTask)
.where(LogisticsTask.order_id == order_id, LogisticsTask.deleted == 0)
.order_by(LogisticsTask.id.desc())
)
return session.execute(stmt).scalar_one_or_none()
def create_task(self, session: Session, payload: dict) -> LogisticsTask:
"""创建新的物流任务记录。
:param session: 数据库会话
:param payload: 物流任务字段字典
:return: 新创建的物流任务对象含自增 ID
LogisticsService.create_task 调用
"""
2026-05-14 15:17:56 +08:00
task = LogisticsTask(**payload)
session.add(task)
session.flush()
return task
def update_task_status(self, session: Session, task: LogisticsTask, status: str) -> LogisticsTask:
"""更新物流任务的状态。
:param session: 数据库会话
:param task: 物流任务对象
:param status: 目标状态值
:return: 更新后的物流任务对象
LogisticsService 中的状态流转方法调用
"""
2026-05-14 15:17:56 +08:00
task.status = status
session.add(task)
session.flush()
return task
def list_traces_by_order_id(self, session: Session, order_id: int) -> list[LogisticsTrace]:
"""根据订单 ID 查询该订单的所有物流跟踪节点记录,按节点时间和 id 升序排列。
:param session: 数据库会话
:param order_id: 订单主键 ID
:return: 物流跟踪记录列表
LogisticsService.list_tracesOrderService.get_order 调用
用于展示物流轨迹时间线
"""
stmt = (
select(LogisticsTrace)
.where(LogisticsTrace.order_id == order_id)
.order_by(LogisticsTrace.node_time.asc(), LogisticsTrace.id.asc())
)
return list(session.execute(stmt).scalars())
def create_trace(self, session: Session, payload: dict) -> LogisticsTrace:
"""创建一条物流跟踪节点记录。
:param session: 数据库会话
:param payload: 物流跟踪记录字段字典
:return: 新创建的跟踪记录对象
LogisticsService.create_trace 调用用于记录物流各节点信息
"""
trace = LogisticsTrace(**payload)
session.add(trace)
session.flush()
return trace
def list_waybills_by_task_id(self, session: Session, task_id: int) -> list[LogisticsWaybill]:
"""查询指定任务的所有运单号记录。
:param session: 数据库会话
:param task_id: 物流任务 ID
:return: 运单号列表 id 升序排列
LogisticsService.list_waybills 调用
"""
stmt = (
select(LogisticsWaybill)
.where(LogisticsWaybill.task_id == task_id, LogisticsWaybill.deleted == 0)
.order_by(LogisticsWaybill.id.asc())
)
return list(session.execute(stmt).scalars())
def create_waybill(self, session: Session, payload: dict) -> LogisticsWaybill:
"""创建运单号记录。
:param session: 数据库会话
:param payload: 运单号字段字典
:return: 新创建的运单号对象
LogisticsService.submit_waybills 调用
"""
waybill = LogisticsWaybill(**payload)
session.add(waybill)
session.flush()
return waybill
def delete_waybill(self, session: Session, waybill_id: int, task_id: int) -> bool:
"""软删除单条运单号记录。
校验 task_id 防止越权删除其他任务的运单号
:param session: 数据库会话
:param waybill_id: 运单号记录 ID
:param task_id: 物流任务 ID用于校验归属
:return: 删除成功返回 True
LogisticsService.delete_waybill 调用
"""
stmt = select(LogisticsWaybill).where(
LogisticsWaybill.id == waybill_id,
LogisticsWaybill.task_id == task_id,
LogisticsWaybill.deleted == 0,
)
waybill = session.execute(stmt).scalar_one_or_none()
if waybill is None:
return False
waybill.deleted = 1
session.add(waybill)
session.flush()
return True