from app.core.account import AccountManager from fastapi import APIRouter, Depends from sqlalchemy.orm import Session from typing import List, Optional from app.models.order import ( ShippingOrderDB, ShippingOrderPackageDB, OrderCreate, OrderInfo, OrderPackageInfo, OrderPriceCalculateRequest, OrderPriceInfo, OrderStatus, OrderCancel, OrderComplete, OrderPriceResult ) from app.models.database import get_db from app.api.deps import get_current_user, get_deliveryman_user, get_admin_user from app.models.user import UserDB,UserRole from app.core.response import success_response, error_response, ResponseModel from app.models.coupon import UserCouponDB, CouponStatus from datetime import datetime, timezone from app.core.config import settings from app.models.address import AddressDB from sqlalchemy.orm import joinedload from app.models.community import CommunityDB from app.models.community_building import CommunityBuildingDB, CommunityBuildingInfo from app.models.station import StationDB from app.models.point import PointRecordDB, PointRecordType from app.core.utils import CommonUtils import logging from sqlalchemy import func from app.core.mpclient import mp_client from datetime import timedelta router = APIRouter() def calculate_price(price_request: OrderPriceCalculateRequest,user: UserDB,db: Session) -> OrderPriceResult: """ 计算订单价格,自动使用优惠券或积分抵扣 Args: price_request: 价格计算请求 user: 用户信息 Returns: OrderPriceResult: 包含价格信息和使用的优惠券/积分信息 """ # 计算所有包裹中的取件码总数 package_count = sum( # 如果package.pickup_codes是空字符串,则取0 0 if len(package.pickup_codes.split(',')) == 0 else len(package.pickup_codes.split(',')) for package in price_request.packages if package.pickup_codes ) result = OrderPriceResult( price_info=OrderPriceInfo( package_count=package_count, original_amount=settings.ORDER_BASE_PRICE, coupon_discount_amount=0, points_discount_amount=0, final_amount=settings.ORDER_BASE_PRICE ), price_detail_text=settings.ORDER_PREORDER_PRICE_TEXT ) original_amount = settings.ORDER_BASE_PRICE # 超过阈值的包裹额外收费 if package_count > settings.ORDER_EXTRA_PACKAGE_THRESHOLD: extra_count = package_count - settings.ORDER_EXTRA_PACKAGE_THRESHOLD original_amount += extra_count * settings.ORDER_EXTRA_PACKAGE_PRICE result.price_info.package_count = package_count result.price_info.original_amount = original_amount result.price_info.final_amount = original_amount remaining_amount = original_amount # 1. 查找用户可用的优惠券(按金额从大到小排序) available_coupon = db.query(UserCouponDB).filter( UserCouponDB.user_id == user.userid, UserCouponDB.status == CouponStatus.UNUSED, UserCouponDB.expire_time > datetime.now() ).order_by(UserCouponDB.coupon_amount.desc()).first() # 2. 如果有可用优惠券,优先使用优惠券 if available_coupon: coupon_discount = min(remaining_amount, available_coupon.coupon_amount) result.price_info.coupon_discount_amount = coupon_discount result.price_info.coupon_id = available_coupon.id result.used_coupon_id = available_coupon.id remaining_amount -= coupon_discount # 3. 如果没有优惠券,且用户有积分,则使用积分抵扣 elif user.points > 0: # 计算最大可抵扣金额 max_points_discount = user.points // settings.POINT_RATIO # 使用整除 points_discount_amount = min(remaining_amount, max_points_discount) if points_discount_amount > 0: result.price_info.points_discount_amount = points_discount_amount result.used_points = int(points_discount_amount * settings.POINT_RATIO) remaining_amount -= points_discount_amount # 计算最终金额 result.price_info.final_amount = remaining_amount return result @router.post("/pre-order", response_model=ResponseModel) async def pre_order( request: OrderPriceCalculateRequest, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): # 检查是否有未支付的订单 unpay_order = db.query(ShippingOrderDB).filter( ShippingOrderDB.userid == current_user.userid, ShippingOrderDB.status.not_in([OrderStatus.CANCELLED, OrderStatus.COMPLETED]) ).first() if unpay_order: return error_response(code=400, message="存在未完成的订单", data={ "orderid": unpay_order.orderid }) """预下单 - 计算价格""" price_info = calculate_price(request, current_user, db) return success_response(data=price_info) @router.post("", response_model=ResponseModel) async def create_order( order: OrderCreate, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): """创建配送订单""" # 计算订单价格 price_result = calculate_price(order.price_request, current_user, db) price_info = price_result.price_info # 生成订单号 orderid = CommonUtils.generate_order_id('D') # 计算原始金额 original_amount = price_info.original_amount # 计算优惠券折扣 coupon_discount = price_info.coupon_discount_amount coupon_id = price_info.coupon_id # 查询用户优惠券 if coupon_id: user_coupon = db.query(UserCouponDB).filter( UserCouponDB.id == coupon_id ).first() if user_coupon: coupon_discount = user_coupon.coupon_amount coupon_id = user_coupon.id # 更新优惠券状态 user_coupon.status = CouponStatus.USED # 查询地址信息 address = db.query(AddressDB).filter( AddressDB.id == order.addressid ).first() # 创建订单 db_order = ShippingOrderDB( orderid=orderid, userid=current_user.userid, address_customer_name=address.name, address_customer_phone=address.phone, address_customer_gender=address.gender, address_community_id=address.community_id, address_community_building_id=address.community_building_id, address_community_name=address.community_name, address_community_building_name=address.community_building_name, address_detail=address.address_detail, package_count=price_info.package_count, original_amount=original_amount, coupon_discount_amount=coupon_discount, point_discount_amount=price_info.points_discount_amount, coupon_id=coupon_id, final_amount=price_info.final_amount, status=OrderStatus.CREATED, delivery_method=order.delivery_method ) db.add(db_order) # 创建订单包裹 for package in order.price_request.packages: # 如果包裹有取件码,则创建包裹 if len(package.pickup_codes) > 0: station = db.query(StationDB).filter( StationDB.id == package.station_id ).first() db_package = ShippingOrderPackageDB( orderid=orderid, station_id=package.station_id, station_name=station.name, pickup_codes=package.pickup_codes ) db.add(db_package) try: # 如果使用了优惠券,更新优惠券状态 if price_result.used_coupon_id: coupon = db.query(UserCouponDB).filter( UserCouponDB.id == price_result.used_coupon_id, ).first() if coupon: coupon.status = CouponStatus.USED # 如果使用了积分,扣减用户积分并记录 if price_result.used_points: # 扣减用户积分 current_user.points -= price_result.used_points # 记录积分变动 point_record = PointRecordDB( user_id=current_user.userid, points=-price_result.used_points, # 负数表示扣减 type=PointRecordType.CONSUME_DEDUCT, order_id=db_order.orderid, description=f"配送订单抵扣积分" ) db.add(point_record) db.commit() db.refresh(db_order) # 查询包裹信息 packages = db.query(ShippingOrderPackageDB).filter( ShippingOrderPackageDB.orderid == orderid ).all() #发送订单创建成功的消息 if current_user.mp_openid: await mp_client.send_template_message( openid=current_user.mp_openid, template_id=settings.DELIVERY_ORDER_CREATED_TEMPLATE_ID, data={ "character_string13": db_order.orderid, "time4": db_order.create_time.strftime("%Y-%m-%d %H:%M:%S"), "thing10": db_order.address_customer_name, "thing15": f"{db_order.address_community_name} {db_order.address_community_building_name} {db_order.address_detail}", "thing9": db_order.status.status_text }, miniprogram={ "appid": settings.WECHAT_APPID, "path": f"/pages/order/detail/index?id={db_order.orderid}" }) return success_response( message="订单创建成功", data={ "order": OrderInfo.model_validate(db_order), "packages": [OrderPackageInfo.model_validate(p) for p in packages], "success_text" : settings.ORDER_SUCCESS_TEXT } ) except Exception as e: db.rollback() logging.exception(f"订单创建失败: {str(e)}") return error_response(code=500, message=f"订单创建失败: {str(e)}") @router.get("/{orderid}", response_model=ResponseModel) async def get_order_detail( orderid: str, db: Session = Depends(get_db)): """获取订单详情""" # 使用 join 查询获取订单和相关地址信息 order = db.query( ShippingOrderDB ).filter( ShippingOrderDB.orderid == orderid ).first() if not order: return error_response(code=404, message="订单不存在") # 查询包裹信息,包含驿站名称 packages = db.query( ShippingOrderPackageDB, StationDB.name.label('station_name') ).join( StationDB, ShippingOrderPackageDB.station_id == StationDB.id ).filter( ShippingOrderPackageDB.orderid == orderid ).all() # 如果有配送员 id,则获取配送员信息 if order.deliveryman_user_id: deliveryman_user = db.query(UserDB).filter( UserDB.userid == order.deliveryman_user_id ).first() deliveryman_user_name = deliveryman_user.nickname deliveryman_user_avatar = deliveryman_user.optimized_avatar deliveryman_user_phone = deliveryman_user.phone delivery_count = db.query(ShippingOrderDB).filter( ShippingOrderDB.deliveryman_user_id == order.deliveryman_user_id, ShippingOrderDB.status == OrderStatus.COMPLETED ).count() else: delivery_count = 0 deliveryman_user_name = None deliveryman_user_avatar = None deliveryman_user_phone = None # 构建响应数据 order_data = { "orderid": order.orderid, "userid": order.userid, "package_count": order.package_count, "original_amount": order.original_amount, "coupon_discount_amount": order.coupon_discount_amount, "coupon_id": order.coupon_id, "final_amount": order.final_amount, "status": order.status, "complete_images": order.complete_images.split(",") if order.complete_images else None, "create_time": order.create_time, "complete_time": order.completed_time, "pickup_time": order.pickup_time, "received_time": order.received_time, "delivery_method": order.delivery_method, "deliveryman_user_id": order.deliveryman_user_id, "deliveryman_nickname": deliveryman_user_name, "deliveryman_avatar": deliveryman_user_avatar, "deliveryman_phone": deliveryman_user_phone, "delivery_count": delivery_count, # 地址相关信息 "address_name": order.address_customer_name, "address_phone": order.address_customer_phone, "address_detail": order.address_detail, "address_gender": order.address_customer_gender, "building_id": order.address_community_building_id, "building_name": order.address_community_building_name, "community_id": order.address_community_id, "community_name": order.address_community_name } # 构建包裹信息,包含驿站名称 package_list = [{ "id": p.ShippingOrderPackageDB.id, "orderid": p.ShippingOrderPackageDB.orderid, "station_id": p.ShippingOrderPackageDB.station_id, "station_name": p.station_name, "pickup_codes": p.ShippingOrderPackageDB.pickup_codes, "create_time": p.ShippingOrderPackageDB.create_time } for p in packages] return success_response(data={ "order": order_data, "packages": package_list }) # 提供一个接口,传入community_id,返回订单状态数量 @router.get("/status/count", response_model=ResponseModel) async def get_order_status_count( community_id: int, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): """获取社区订单状态数量""" status_order_count = db.query( ShippingOrderDB.status, func.count(ShippingOrderDB.orderid) ).filter( ShippingOrderDB.address_community_id == community_id ).group_by( ShippingOrderDB.status ).all() result = [] for status, count in status_order_count: result.append({ "status": status, "count": count }) return success_response(data=result) # 提供一个接口,传入 community_id 返回每栋楼栋的订单数量 @router.get("/community_building/count", response_model=ResponseModel) async def get_community_building_order_count( community_id: int, status: str, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): """获取社区每栋楼栋的订单数量""" # 查询当前社区所有楼栋 community_buildings = db.query( CommunityBuildingDB ).filter( CommunityBuildingDB.community_id == community_id ).all() if not community_buildings: return error_response(code=404, message="社区不存在") # 查询每个楼栋的订单数量 building_order_count = db.query( ShippingOrderDB.address_community_building_id, func.count(ShippingOrderDB.orderid) ).filter( ShippingOrderDB.address_community_building_id.in_( [building.id for building in community_buildings] ) ).filter( ShippingOrderDB.status.in_(status.split(",")) ).group_by( ShippingOrderDB.address_community_building_id ).all() # 没有订单的楼栋,订单数量为0 result = [] building_order_count_dict = dict(building_order_count) for building in community_buildings: if building.id not in building_order_count_dict: result.append({ "building_id": building.id, "building_name": building.building_name, "order_count": 0 }) else: result.append({ "building_id": building.id, "building_name": building.building_name, "order_count": building_order_count_dict[building.id] }) return success_response(data=result) @router.get("/user/list", response_model=ResponseModel) async def get_user_orders( status: Optional[OrderStatus] = None, skip: int = 0, limit: int = 20, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): """获取用户订单列表""" try: # 查询订单 query = db.query( ShippingOrderDB ).filter( ShippingOrderDB.userid == current_user.userid ) # 添加状态过滤 if status: query = query.filter(ShippingOrderDB.status == status) # 获取总数 total = query.count() # 分页查询 results = query.order_by( ShippingOrderDB.create_time.desc() ).offset(skip).limit(limit).all() orders = [] for order in results: # 查询订单包裹信息 packages = db.query( ShippingOrderPackageDB ).filter( ShippingOrderPackageDB.orderid == order.orderid ).all() # 格式化包裹信息 package_list = [{ "id": package.id, "station_id": package.station_id, "station_name": package.station_name, "pickup_codes": package.pickup_codes } for package in packages] orders.append({ "orderid": order.orderid, "userid": order.userid, "status": order.status, "package_count": order.package_count, "create_time": order.create_time, "delivery_method": order.delivery_method, "original_amount": order.original_amount, "coupon_discount_amount": order.coupon_discount_amount, "point_discount_amount": order.point_discount_amount, "final_amount": order.final_amount, "packages": package_list, "address": { "name": order.address_customer_name, "phone": order.address_customer_phone, "gender": order.address_customer_gender, "community_id": order.address_community_id, "community_name": order.address_community_name, "building_id": order.address_community_building_id, "building_name": order.address_community_building_name, "address_detail": order.address_detail } }) return success_response(data={ "total": total, "items": orders }) except Exception as e: return error_response(code=500, message=f"获取订单列表失败: {str(e)}") @router.post("/{orderid}/user/cancel", response_model=ResponseModel) async def cancel_order( orderid: str, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): """取消订单""" # 查询订单 order = db.query(ShippingOrderDB).filter( ShippingOrderDB.orderid == orderid, ShippingOrderDB.userid == current_user.userid ).first() if not order: return error_response(code=404, message="订单不存在") # 检查订单状态是否可取消 if order.status not in [OrderStatus.CREATED, OrderStatus.RECEIVED]: return error_response(code=400, message="当前订单状态不可取消") try: # 更新订单状态、取消原因和取消用户 order.status = OrderStatus.CANCELLED order.cancel_reason = "用户主动取消" order.cancel_user_id = current_user.userid # 记录取消订单的用户ID # 如果使用了优惠券,返还优惠券 if order.coupon_id: coupon = db.query(UserCouponDB).filter( UserCouponDB.id == order.coupon_id ).first() if coupon: coupon.status = CouponStatus.UNUSED # 如果使用了积分,返还积分 if order.point_discount_amount > 0: # 返还积分 return_points = int(order.point_discount_amount * settings.POINT_RATIO) current_user.points += return_points # 记录积分变动 point_record = PointRecordDB( user_id=current_user.userid, points=return_points, type=PointRecordType.CONSUME_RETURN, order_id=order.orderid, description=f"订单取消返还积分" ) db.add(point_record) db.commit() # 发送模板消息 if current_user.mp_openid: await mp_client.send_template_message( openid=current_user.mp_openid, template_id=settings.DELIVERY_ORDER_CANCELLED_TEMPLATE_ID, data={ "character_string1": order.orderid, "time19": CommonUtils.get_current_time(), "thing5": "用户主动取消订单" } ) return success_response( message="订单取消成功", data=OrderInfo.model_validate(order) ) except Exception as e: db.rollback() return error_response(code=500, message=f"取消订单失败: {str(e)}") @router.get("/deliveryman/list", response_model=ResponseModel) async def get_deliveryman_orders( status: Optional[str] = None, building_id: Optional[int] = None, skip: int = 0, limit: int = 20, db: Session = Depends(get_db), deliveryman: UserDB = Depends(get_deliveryman_user) ): """获取配送员订单列表""" # 基础查询 query = db.query( ShippingOrderDB ) # 状态筛选 if status: statuses = status.split(",") query = query.filter(ShippingOrderDB.status.in_(statuses)) # 楼栋筛选 if building_id: query = query.filter(ShippingOrderDB.address_community_building_id == building_id) # 获取总数 total = query.count() # 获取分页数据 results = query.order_by( ShippingOrderDB.create_time.desc() ).offset(skip).limit(limit).all() # 格式化返回数据 orders = [] for order in results: # 查询订单包裹信息 packages = db.query( ShippingOrderPackageDB, StationDB.name.label('station_name') ).join( StationDB, ShippingOrderPackageDB.station_id == StationDB.id ).filter( ShippingOrderPackageDB.orderid == order.orderid ).all() # 格式化包裹信息 package_list = [{ "id": package.ShippingOrderPackageDB.id, "station_id": package.ShippingOrderPackageDB.station_id, "station_name": package.station_name, "pickup_codes": package.ShippingOrderPackageDB.pickup_codes } for package in packages] orders.append({ "orderid": order.orderid, "userid": order.userid, "status": order.status, "package_count": order.package_count, "create_time": order.create_time, "delivery_method": order.delivery_method, "packages": package_list, "address": { "name": order.address_customer_name, "phone": order.address_customer_phone, "gender": order.address_customer_gender, "community_id": order.address_community_id, "community_name": order.address_community_name, "building_id": order.address_community_building_id, "building_name": order.address_community_building_name, "address_detail": order.address_detail }, "complete_images": order.complete_images.split(",") if order.complete_images else None, "received_time": order.received_time, "pickup_time": order.pickup_time, "completed_time": order.completed_time }) return success_response(data={ "total": total, "items": orders }) @router.post("/{orderid}/deliveryman/cancel", response_model=ResponseModel) async def deliveryman_cancel_order( orderid: str, cancel_data: OrderCancel, db: Session = Depends(get_db), deliveryman: UserDB = Depends(get_deliveryman_user) ): """配送员取消订单""" order = db.query(ShippingOrderDB).filter( ShippingOrderDB.orderid == orderid, ShippingOrderDB.deliveryman_user_id == deliveryman.userid ).first() if not order: return error_response(code=404, message="订单不存在") # 检查订单状态 if order.status != OrderStatus.CREATED and order.status != OrderStatus.RECEIVED: return error_response(code=400, message="只有未接单或者已接单的订单才能取消") try: # 更新订单状态、取消原因和取消用户 order.status = OrderStatus.CANCELLED order.cancel_reason = cancel_data.reason order.cancel_user_id = deliveryman.userid # 如果使用了优惠券,返还优惠券 if order.coupon_id: coupon = db.query(UserCouponDB).filter( UserCouponDB.id == order.coupon_id ).first() if coupon: coupon.status = CouponStatus.UNUSED # 如果使用了积分,返还积分 if order.point_discount_amount > 0: # 返还积分 return_points = int(order.point_discount_amount * settings.POINT_RATIO) order_user = db.query(UserDB).filter( UserDB.userid == order.userid ).first() order_user.points += return_points # 记录积分变动 point_record = PointRecordDB( user_id=order_user.userid, points=return_points, type=PointRecordType.CONSUME_RETURN, order_id=order.orderid, description=f"订单取消返还积分" ) db.add(point_record) db.commit() # 发送模板消息 if order.userid: order_user = db.query(UserDB).filter( UserDB.userid == order.userid ).first() if order_user.mp_openid: await mp_client.send_template_message( openid=order_user.mp_openid, template_id=settings.DELIVERY_ORDER_CANCELLED_TEMPLATE_ID, data={ "character_string1": order.orderid, "time19": CommonUtils.get_current_time(), "thing5": order.cancel_reason } ) return success_response( message="订单取消成功", data=OrderInfo.model_validate(order) ) except Exception as e: db.rollback() return error_response(code=500, message=f"取消订单失败: {str(e)}") @router.post("/{orderid}/deliveryman/complete", response_model=ResponseModel) async def complete_order( orderid: str, complete_data: OrderComplete, db: Session = Depends(get_db), current_user: UserDB = Depends(get_deliveryman_user) ): """完成订单""" # 查询订单 order = db.query(ShippingOrderDB).filter( ShippingOrderDB.orderid == orderid, ShippingOrderDB.deliveryman_user_id == current_user.userid ).first() if not order: return error_response(code=404, message="订单不存在") # 检查订单状态 if order.status != OrderStatus.DELIVERING: return error_response(code=400, message="只有配送中的订单才能标记为完成") try: # 根据订单金额决定状态 if order.final_amount > 0: order.status = OrderStatus.UNPAID # 需要支付 else: order.status = OrderStatus.COMPLETED # 无需支付,直接完成 # 保存完成图片 if complete_data.images: order.complete_images = ",".join(complete_data.images) # 更新完成时间 order.completed_time = datetime.now() # 计算配送员分账金额 deliveryman_share = order.original_amount * settings.ORDER_DELIVERYMAN_SHARE_RATIO # 使用账户管理器处理分账 account_manager = AccountManager(db) account_manager.change_balance( user_id=order.deliveryman_user_id, amount=deliveryman_share, description=f"配送订单收益", transaction_id=orderid ) db.commit() # 发送模板消息 if order.userid: order_user = db.query(UserDB).filter( UserDB.userid == order.userid ).first() if order_user.mp_openid: deliveryman_user = db.query(UserDB).filter( UserDB.userid == order.deliveryman_user_id ).first() await mp_client.send_template_message( openid=order_user.mp_openid, template_id=settings.DELIVERY_ORDER_COMPLETED_TEMPLATE_ID, data={ "character_string13": order.orderid, "thing3": deliveryman_user.nickname, "time5" : CommonUtils.get_current_time() }, miniprogram={ "appid": settings.WECHAT_APPID, "path": f"/pages/order/detail/index?id={order.orderid}" } ) return success_response( message="订单已完成" if order.final_amount == 0 else "请继续支付", data=OrderInfo.model_validate(order) ) except Exception as e: db.rollback() return error_response(code=500, message=f"操作失败: {str(e)}") @router.post("/{orderid}/deliveryman/receive", response_model=ResponseModel) async def receive_order( orderid: str, db: Session = Depends(get_db), deliveryman: UserDB = Depends(get_deliveryman_user) ): """接单(仅配送员可用)""" # 查询订单 order = db.query(ShippingOrderDB).filter( ShippingOrderDB.orderid == orderid ).first() if not order: return error_response(code=404, message="订单不存在") # 检查订单状态 if order.status != OrderStatus.CREATED: return error_response(code=400, message="只能接待新创建的订单") # 检查订单是否已被接单 if order.deliveryman_user_id is not None: return error_response(code=400, message="订单已被其他配送员接单") try: # 更新订单状态和配送员ID order.status = OrderStatus.RECEIVED order.deliveryman_user_id = deliveryman.userid order.received_time = datetime.now() db.commit() # 发送模板消息 if order.userid: order_user = db.query(UserDB).filter( UserDB.userid == order.userid ).first() if order_user.mp_openid: deliveryman_user = db.query(UserDB).filter( UserDB.userid == order.deliveryman_user_id ).first() await mp_client.send_template_message( openid=order_user.mp_openid, template_id=settings.DELIVERY_ORDER_RECEIVED_TEMPLATE_ID, data={ "character_string9": order.orderid, "time8": CommonUtils.get_current_time(), "thing3": deliveryman_user.nickname }, miniprogram={ "appid": settings.WECHAT_APPID, "path": f"/pages/order/detail/index?id={order.orderid}" } ) return success_response( message="接单成功", data=OrderInfo.model_validate(order) ) except Exception as e: db.rollback() return error_response(code=500, message=f"接单失败: {str(e)}") @router.post("/{orderid}/deliveryman/pickup", response_model=ResponseModel) async def pickup_order( orderid: str, db: Session = Depends(get_db), deliveryman: UserDB = Depends(get_deliveryman_user) ): """标记订单为已取货(仅配送员可用)""" # 查询订单 order = db.query(ShippingOrderDB).filter( ShippingOrderDB.orderid == orderid, ShippingOrderDB.deliveryman_user_id == deliveryman.userid # 必须是该配送员的订单 ).first() if not order: return error_response(code=404, message="订单不存在") # 检查订单状态 if order.status != OrderStatus.RECEIVED: return error_response(code=400, message="只有已接单的订单才能标记为已取货") try: # 更新订单状态为配送中 order.status = OrderStatus.DELIVERING order.pickup_time = datetime.now() db.commit() return success_response( message="已标记为取货", data=OrderInfo.model_validate(order) ) except Exception as e: db.rollback() return error_response(code=500, message=f"操作失败: {str(e)}") @router.get("/admin/list", response_model=ResponseModel) async def get_admin_orders( status: Optional[OrderStatus] = None, user_id: Optional[int] = None, order_id: Optional[str] = None, skip: int = 0, limit: int = 20, db: Session = Depends(get_db), admin_user: UserDB = Depends(get_admin_user) ): """获取订单列表(管理员接口) Args: status: 订单状态过滤 user_id: 用户ID过滤 order_id: 订单号过滤 skip: 跳过记录数 limit: 返回记录数 """ try: # 构建基础查询 query = db.query(ShippingOrderDB) # 添加用户ID过滤 if user_id: query = query.filter(ShippingOrderDB.userid == user_id) # 添加状态过滤 if status: query = query.filter(ShippingOrderDB.status == status) # 添加订单号过滤 if order_id: query = query.filter(ShippingOrderDB.orderid == order_id) # 获取总数 total = query.count() # 分页查询 results = query.order_by( ShippingOrderDB.create_time.desc() ).offset(skip).limit(limit).all() orders = [] for order in results: # 查询订单包裹信息 packages = db.query( ShippingOrderPackageDB, StationDB.name.label('station_name') ).join( StationDB, ShippingOrderPackageDB.station_id == StationDB.id ).filter( ShippingOrderPackageDB.orderid == order.orderid ).all() # 格式化包裹信息 package_list = [{ "id": package.ShippingOrderPackageDB.id, "station_id": package.ShippingOrderPackageDB.station_id, "station_name": package.station_name, "pickup_codes": package.ShippingOrderPackageDB.pickup_codes } for package in packages] orders.append({ "orderid": order.orderid, "userid": order.userid, "status": order.status, "package_count": order.package_count, "create_time": order.create_time, "delivery_method": order.delivery_method, "original_amount": order.original_amount, "coupon_discount_amount": order.coupon_discount_amount, "point_discount_amount": order.point_discount_amount, "final_amount": order.final_amount, "packages": package_list, "address": { "name": order.address_customer_name, "phone": order.address_customer_phone, "community_name": order.address_community_name, "building_name": order.address_community_building_name, "address_detail": order.address_detail } }) return success_response(data={ "total": total, "items": orders }) except Exception as e: logging.exception(f"获取订单列表失败: {str(e)}") return error_response(code=500, message=f"获取订单列表失败: {str(e)}") # 获取配送员订单数量汇总 @router.get("/deliveryman/summary", response_model=ResponseModel) async def get_deliveryman_order_summary( db: Session = Depends(get_db), deliveryman: UserDB = Depends(get_deliveryman_user) ): """获取配送员订单数量汇总""" # 查询配送员总订单数量 total = db.query(ShippingOrderDB).filter( ShippingOrderDB.deliveryman_user_id == deliveryman.userid, ShippingOrderDB.status == OrderStatus.COMPLETED ).count() today = datetime.now().date() yesterday = today - timedelta(days=1) today_start = datetime.combine(today, datetime.min.time()) today_end = datetime.combine(today, datetime.max.time()) yesterday_start = datetime.combine(yesterday, datetime.min.time()) yesterday_end = datetime.combine(yesterday, datetime.max.time()) # 查询配送员昨日、今日订单数量 yesterday_total = db.query(ShippingOrderDB).filter( ShippingOrderDB.deliveryman_user_id == deliveryman.userid, ShippingOrderDB.status == OrderStatus.COMPLETED, ShippingOrderDB.create_time.between(yesterday_start, yesterday_end) ).count() today_total = db.query(ShippingOrderDB).filter( ShippingOrderDB.deliveryman_user_id == deliveryman.userid, ShippingOrderDB.status == OrderStatus.COMPLETED, ShippingOrderDB.create_time.between(today_start, today_end) ).count() return success_response(data={ "total_count": total, "yesterday_count": yesterday_total, "today_count": today_total })