dingdanquanliucheng/backend/app/repositories/order_repository.py

253 lines
11 KiB
Python
Raw Normal View History

"""
订单数据访问层
负责封装销售订单SalesOrder订单明细SalesOrderItem
供应商Supplier及供应商短信确认日志OrderSupplierTextLog的数据库查询操作
提供订单的增删改查状态流转取消流程供应商确认等功能
OrderServiceLogisticsService 调用
"""
2026-05-14 13:51:06 +08:00
from datetime import datetime
2026-05-28 22:59:04 +08:00
from sqlalchemy import func, select
2026-05-14 13:51:06 +08:00
from sqlalchemy.orm import Session
2026-05-19 17:30:35 +08:00
from backend.app.models.business import OrderSupplierTextLog, SalesOrder, SalesOrderItem, Supplier
2026-05-14 13:51:06 +08:00
class OrderRepository:
"""订单数据访问层,封装销售订单及其相关表的数据库操作。
OrderServiceLogisticsService 调用
"""
2026-05-14 13:51:06 +08:00
def list_orders(self, session: Session) -> list[SalesOrder]:
"""查询所有未删除的订单列表(不做分页),按 id 降序排列。
:param session: 数据库会话
:return: 订单列表
OrderService 内部使用
"""
2026-05-14 13:51:06 +08:00
stmt = select(SalesOrder).where(SalesOrder.deleted == 0).order_by(SalesOrder.id.desc())
return list(session.execute(stmt).scalars())
def list_orders_by_filters(self, session: Session, filters: dict) -> list[SalesOrder]:
"""根据筛选条件查询订单列表,支持订单号、状态、客户名、手机号、业务员、工厂、来源、
时间范围等条件的模糊/精确匹配并支持分页
:param session: 数据库会话
:param filters: 筛选条件字典可包含 order_noorder_statuscustomer_name
customer_mobilesalesman_idfactory_idorder_source
start_timeend_timepage_nopage_size 等键
:return: 字典包含 total总数 list订单列表若未传分页参数则 total None
OrderService.list_orders 调用
"""
2026-05-14 13:51:06 +08:00
stmt = select(SalesOrder).where(SalesOrder.deleted == 0)
if filters.get("order_no"):
stmt = stmt.where(SalesOrder.order_no.contains(filters["order_no"]))
2026-05-14 13:51:06 +08:00
if filters.get("order_status"):
stmt = stmt.where(SalesOrder.order_status == filters["order_status"])
if filters.get("customer_name"):
stmt = stmt.where(SalesOrder.customer_name.contains(filters["customer_name"]))
if filters.get("customer_mobile"):
stmt = stmt.where(SalesOrder.customer_mobile.contains(filters["customer_mobile"]))
if filters.get("salesman_id") is not None:
stmt = stmt.where(SalesOrder.salesman_id == filters["salesman_id"])
if filters.get("factory_id") is not None:
stmt = stmt.where(SalesOrder.factory_id == filters["factory_id"])
if filters.get("order_source"):
stmt = stmt.where(SalesOrder.order_source == filters["order_source"])
if filters.get("start_time"):
start_time = datetime.strptime(filters["start_time"], "%Y-%m-%d %H:%M:%S")
stmt = stmt.where(SalesOrder.created_at >= start_time)
if filters.get("end_time"):
end_time = datetime.strptime(filters["end_time"], "%Y-%m-%d %H:%M:%S")
stmt = stmt.where(SalesOrder.created_at <= end_time)
stmt = stmt.order_by(SalesOrder.id.desc())
2026-05-28 22:59:04 +08:00
page_no = filters.get("page_no")
page_size = filters.get("page_size")
if page_no is not None and page_size is not None:
count_stmt = select(func.count()).select_from(stmt.subquery())
total = session.execute(count_stmt).scalar() or 0
offset = max(page_no - 1, 0) * page_size
stmt = stmt.offset(offset).limit(page_size)
rows = list(session.execute(stmt).scalars())
return {"total": total, "list": rows}
return {"total": None, "list": list(session.execute(stmt).scalars())}
2026-05-14 13:51:06 +08:00
def get_order(self, session: Session, order_id: int) -> SalesOrder | None:
"""根据 ID 获取单个订单详情。
:param session: 数据库会话
:param order_id: 订单主键 ID
:return: 订单对象不存在则返回 None
OrderService.get_order 等方法调用
"""
2026-05-14 13:51:06 +08:00
stmt = select(SalesOrder).where(SalesOrder.id == order_id, SalesOrder.deleted == 0)
return session.execute(stmt).scalar_one_or_none()
def get_supplier(self, session: Session, supplier_id: int | None) -> Supplier | None:
"""根据供应商 ID 获取供应商信息。
:param session: 数据库会话
:param supplier_id: 供应商主键 ID None 时直接返回 None
:return: 供应商对象不存在则返回 None
OrderService 在查询订单时关联获取供应商信息调用
"""
2026-05-14 13:51:06 +08:00
if supplier_id is None:
return None
stmt = select(Supplier).where(Supplier.id == supplier_id, Supplier.deleted == 0)
return session.execute(stmt).scalar_one_or_none()
def list_order_items(self, session: Session, order_id: int) -> list[SalesOrderItem]:
"""查询指定订单下的所有订单明细项。
:param session: 数据库会话
:param order_id: 订单主键 ID
:return: 订单明细项列表
OrderService.get_ordercreate_order 等方法调用
"""
2026-05-14 13:51:06 +08:00
stmt = select(SalesOrderItem).where(SalesOrderItem.order_id == order_id, SalesOrderItem.deleted == 0)
return list(session.execute(stmt).scalars())
def create_order(self, session: Session, payload: dict, items: list[dict]) -> SalesOrder:
"""创建订单及其明细项(在一个事务中完成)。
:param session: 数据库会话
:param payload: 订单主表字段字典
:param items: 订单明细项字段字典列表
:return: 新创建的订单对象含自增 ID 和关联的明细项
OrderService.create_order 调用
"""
2026-05-14 13:51:06 +08:00
order = SalesOrder(**payload)
session.add(order)
session.flush()
for item_payload in items:
session.add(SalesOrderItem(order_id=order.id, **item_payload))
session.flush()
return order
2026-05-19 17:30:35 +08:00
def update_order_with_items(self, session: Session, order: SalesOrder, payload: dict, items: list[dict]) -> SalesOrder:
"""更新订单主表信息并替换其全部明细项(先删后插)。
:param session: 数据库会话
:param order: 待更新的订单对象
:param payload: 订单主表更新字段字典
:param items: 新的订单明细项字段字典列表将完全替换原有明细
:return: 更新后的订单对象
OrderService.update_order 调用
"""
2026-05-19 17:30:35 +08:00
order.customer_id = payload["customer_id"]
order.customer_name = payload["customer_name"]
order.customer_mobile = payload["customer_mobile"]
order.customer_address = payload.get("customer_address")
order.salesman_id = payload.get("salesman_id")
order.order_source = payload.get("order_source")
order.delivery_type = payload.get("delivery_type")
order.factory_id = payload.get("factory_id")
order.sale_price_total = payload["sale_price_total"]
order.cost_price_total = payload["cost_price_total"]
order.rebate_total = payload["rebate_total"]
order.freight_total = payload["freight_total"]
order.tax_total = payload["tax_total"]
order.other_fee_total = payload["other_fee_total"]
order.profit_total = payload["profit_total"]
order.profit_rate = payload["profit_rate"]
order.commission_amount = payload["commission_amount"]
order.remark = payload.get("remark")
session.add(order)
session.flush()
session.query(SalesOrderItem).filter(SalesOrderItem.order_id == order.id, SalesOrderItem.deleted == 0).delete(synchronize_session=False)
for item_payload in items:
session.add(SalesOrderItem(order_id=order.id, **item_payload))
session.flush()
return order
2026-05-14 13:51:06 +08:00
def update_order_status(self, session: Session, order: SalesOrder, target_status: str) -> SalesOrder:
"""更新订单状态(用于流程流转)。
:param session: 数据库会话
:param order: 订单对象
:param target_status: 目标状态值
:return: 更新后的订单对象
OrderService 中各状态流转方法approvereject 调用
"""
2026-05-14 13:51:06 +08:00
order.order_status = target_status
session.add(order)
session.flush()
return order
def update_cancel_fields(self, session: Session, order: SalesOrder, payload: dict) -> SalesOrder:
"""更新订单的取消相关信息(取消请求发起时调用)。
:param session: 数据库会话
:param order: 订单对象
:param payload: 取消相关字段字典包含 order_statuscancel_requested_by
cancel_requested_atcancel_reasoncancel_opinion
cancel_previous_status 等键
:return: 更新后的订单对象
OrderService.cancel_order 调用
"""
2026-05-14 13:51:06 +08:00
order.order_status = payload["order_status"]
2026-05-19 17:30:35 +08:00
order.cancel_requested_by = payload.get("cancel_requested_by")
order.cancel_requested_at = payload.get("cancel_requested_at")
2026-05-14 13:51:06 +08:00
order.cancel_reason = payload["cancel_reason"]
order.cancel_opinion = payload.get("cancel_opinion")
order.cancel_previous_status = payload.get("cancel_previous_status")
session.add(order)
session.flush()
return order
2026-05-19 17:30:35 +08:00
def clear_cancel_request(self, session: Session, order: SalesOrder) -> SalesOrder:
"""清除订单的取消请求信息(审批驳回取消请求时调用)。
:param session: 数据库会话
:param order: 订单对象
:return: 清除取消信息后的订单对象
OrderService.reject_cancel_order 调用
"""
2026-05-19 17:30:35 +08:00
order.cancel_requested_by = None
order.cancel_requested_at = None
order.cancel_reason = None
order.cancel_opinion = None
order.cancel_previous_status = None
session.add(order)
session.flush()
return order
2026-05-14 13:51:06 +08:00
def update_supplier_text_confirm(self, session: Session, order: SalesOrder, operator_id: int | None = None) -> SalesOrder:
"""确认供应商短信通知,将订单状态流转为 pending_factory待工厂处理
:param session: 数据库会话
:param order: 订单对象
:param operator_id: 操作人 ID可选
:return: 更新后的订单对象
OrderService.confirm_supplier_text 调用
"""
2026-05-14 13:51:06 +08:00
order.order_status = "pending_factory"
order.supplier_text_confirmed_at = datetime.now()
order.supplier_text_confirmed_by = operator_id
session.add(order)
session.flush()
return order
2026-05-19 17:30:35 +08:00
def create_supplier_text_log(self, session: Session, payload: dict) -> OrderSupplierTextLog:
"""创建供应商短信确认日志记录。
:param session: 数据库会话
:param payload: 日志字段字典
:return: 新创建的日志对象
OrderService.confirm_supplier_text 调用记录短信确认操作
"""
2026-05-19 17:30:35 +08:00
log = OrderSupplierTextLog(**payload)
session.add(log)
session.flush()
return log