From c915f4ffe474aa8c20148485bace3410ca62bb75 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Tue, 4 Mar 2025 22:13:51 +0800 Subject: [PATCH] update --- app/api/endpoints/community_timeperiod.py | 8 +++- app/api/endpoints/order.py | 47 ++++++++++++++++------- app/core/config.py | 6 --- app/core/redis_client.py | 35 ++++++++++++++++- app/models/order.py | 16 +++++++- 5 files changed, 88 insertions(+), 24 deletions(-) diff --git a/app/api/endpoints/community_timeperiod.py b/app/api/endpoints/community_timeperiod.py index b2a5486..f068ae7 100644 --- a/app/api/endpoints/community_timeperiod.py +++ b/app/api/endpoints/community_timeperiod.py @@ -17,6 +17,7 @@ from app.models.community import CommunityDB, CommunityInfo from typing import List, Optional import logging from sqlalchemy.orm import joinedload +from app.core.redis_client import redis_client router = APIRouter() @@ -120,12 +121,17 @@ async def get_community_time_periods( result = [] for ctp in community_time_periods: + # 获取今日订单数量 + today_orders_count = redis_client.get_community_period_today_orders_count(ctp.CommunityTimePeriodDB.id) + result.append({ "time_period_id": ctp.CommunityTimePeriodDB.time_period_id, "time_period_name": ctp.time_period_name, "capacity": ctp.CommunityTimePeriodDB.capacity, "from_time": ctp.time_period_from_time, - "to_time": ctp.time_period_to_time + "to_time": ctp.time_period_to_time, + "order_full": today_orders_count >= ctp.CommunityTimePeriodDB.capacity, + "order_busy": today_orders_count >= ctp.CommunityTimePeriodDB.capacity * 0.8 }) return success_response(data=result) diff --git a/app/api/endpoints/order.py b/app/api/endpoints/order.py index fee25fb..69c7705 100644 --- a/app/api/endpoints/order.py +++ b/app/api/endpoints/order.py @@ -43,7 +43,7 @@ from app.core.mpmessage import sent_order_status_change_message from fastapi import BackgroundTasks from app.core.coupon_manager import CouponManager from app.core.redis_client import redis_client - +from app.models.timeperiod import TimePeriodDB router = APIRouter() def calculate_price(price_request: OrderPriceCalculateRequest,user: UserDB,db: Session) -> OrderPriceResult: @@ -241,6 +241,19 @@ async def create_order( delivery_method=order.delivery_method, is_first_order=is_first_order ) + + # 获取社区配送时段 + time_period = db.query(TimePeriodDB).filter( + TimePeriodDB.id == order.time_period_id + ).first() + + if time_period: + db_order.time_period_id = time_period.id + db_order.time_period_name = time_period.name + db_order.time_period_from_time = time_period.from_time + db_order.time_period_to_time = time_period.to_time + + # 获取取件图片 if order.price_request.pickup_images: db_order.pickup_images = order.price_request.pickup_images @@ -308,7 +321,7 @@ async def create_order( OrderStatus.CREATED ) - #发送订单创建成功的消息 + #发送订单创建成功的公众号消息 if current_user.mp_openid: data={ "character_string13": db_order.orderid, @@ -325,12 +338,6 @@ async def create_order( data=data, orderid=db_order.orderid ) - - # 超过晚上8点,则使用明天送达的文案 - if datetime.now() > datetime.now().replace(hour=settings.ORDER_SPLIT_TIME_HOUR, minute=0, second=0): - success_text = settings.ORDER_SUCCESS_TOMORROW_TEXT - else: - success_text = settings.ORDER_SUCCESS_TODAY_TEXT # 添加到新订单队列 if db_order.address_community_id: @@ -340,13 +347,20 @@ async def create_order( db_order.orderid, db ) + + # 今日订单加入今日选中的配送时段的 Redis 消息队列 + background_tasks.add_task( + redis_client.push_order_to_community_period_today_queue, + order.community_time_period_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" : success_text + "success_text" : f"订单预计 {db_order.time_period_name} 送达,请注意查收" } ) except Exception as e: @@ -421,6 +435,10 @@ async def get_order_detail( # 计算配送时间 delivery_time = "预计明日送达" if datetime.now() > datetime.now().replace(hour=settings.ORDER_SPLIT_TIME_HOUR, minute=0, second=0) else "预计今日送达" + # 如果配送时段不为空,则使用配送时段的时间 + if order.time_period_id: + delivery_time = f"{order.time_period_name} {order.time_period_from_time.strftime('%H:%M')} - {order.time_period_to_time.strftime('%H:%M')}" + # 构建响应数据 order_data = { "orderid": order.orderid, @@ -461,6 +479,12 @@ async def get_order_detail( "community_id": order.address_community_id, "community_name": order.address_community_name, + # 配送时段 + "time_period_id": order.time_period_id, + "time_period_name": order.time_period_name, + "time_period_from_time": order.time_period_from_time, + "time_period_to_time": order.time_period_to_time, + # 配送时间 "delivery_time": delivery_time } @@ -796,11 +820,6 @@ async def deliveryman_orders( if OrderStatus.CREATED not in statuses: query = query.filter(ShippingOrderDB.deliveryman_user_id == deliveryman.userid) - # 如果订单状态是待接单,则只显示小于等于 20 点的订单 - if settings.ORDER_SPLIT_ENABLE: - if OrderStatus.CREATED in statuses: - query = query.filter(ShippingOrderDB.create_time <= datetime.now().replace(hour=settings.ORDER_SPLIT_TIME_HOUR, minute=0, second=0)) - # 楼栋筛选 if building_id: query = query.filter(ShippingOrderDB.address_community_building_id == building_id) diff --git a/app/core/config.py b/app/core/config.py index ece0fcc..64f4c17 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -22,12 +22,6 @@ class Settings(BaseSettings): ORDER_EXTRA_PACKAGE_PRICE: float = 0.5 # 额外包裹费用 ORDER_EXTRA_PACKAGE_THRESHOLD: int = 5 # 额外收费阈值 - #订单创建成功文案 - ORDER_SPLIT_ENABLE: bool = False - ORDER_SPLIT_TIME_HOUR: int = 20 # 订单分割时间 - ORDER_SUCCESS_TODAY_TEXT: str = "订单预计今晚前送达,请注意查收" - ORDER_SUCCESS_TOMORROW_TEXT: str = "订单预计明晚前送达,请注意查收" - # 邀请新人赠送优惠券ID FIRST_ORDER_REFERRAL_COUPON_ID: int = 1 FIRST_ORDER_REFERRAL_COUPON_COUNT: int = 1 diff --git a/app/core/redis_client.py b/app/core/redis_client.py index a7ba4ed..3576073 100644 --- a/app/core/redis_client.py +++ b/app/core/redis_client.py @@ -5,6 +5,9 @@ from app.core.config import settings from typing import List, Dict, Any, Optional from sqlalchemy.orm import Session from app.models.user import UserDB +from datetime import datetime +from app.models.user import UserRole + class RedisClient: """Redis 客户端""" @@ -33,6 +36,36 @@ class RedisClient: """获取 Redis 客户端""" return self.client + + def push_order_to_community_period_today_queue(self, community_time_period_id: int, order_id: str) -> bool: + """ + 添加新订单到今日队列 + """ + try: + today_date_str = datetime.now().strftime("%Y-%m-%d") + key = f"community_period:{community_time_period_id}:today_orders:{today_date_str}" + self.client.lpush(key, order_id) + + # 设置过期时间为24小时 + self.client.expire(key, 86400) + + return True + except Exception as e: + logging.error(f"添加新订单到今日队列失败: {str(e)}") + return False + + def get_community_period_today_orders_count(self, community_time_period_id: int) -> int: + """ + 获取今日队列中的订单数量 + """ + try: + today_date_str = datetime.now().strftime("%Y-%m-%d") + key = f"community_period:{community_time_period_id}:today_orders:{today_date_str}" + return self.client.llen(key) + except Exception as e: + logging.error(f"获取今日队列中的订单数量失败: {str(e)}") + return 0 + def push_order_to_queue(self, community_id: int, order_id: str, db: Session) -> bool: """ 添加新订单到社区队列 @@ -47,7 +80,7 @@ class RedisClient: """ try: # 查询所有社区的用户 - users = db.query(UserDB).filter(UserDB.community_id == community_id).all() + users = db.query(UserDB).filter(UserDB.community_id == community_id, UserDB.roles == UserRole.DELIVERYMAN).all() for user in users: key = f"user:{user.userid}:community:{community_id}:new_orders" # 使用 LPUSH 将订单ID添加到列表头部 diff --git a/app/models/order.py b/app/models/order.py index 117bc90..5957742 100644 --- a/app/models/order.py +++ b/app/models/order.py @@ -1,13 +1,13 @@ from datetime import datetime from typing import Optional, List -from sqlalchemy import Column, String, Integer, Float, DateTime, ForeignKey, Enum, Boolean +from sqlalchemy import Column, String, Integer, Float, DateTime, ForeignKey, Enum, Boolean, Time from sqlalchemy.sql import func from pydantic import BaseModel, Field from .database import Base import enum from app.models.user import Gender from app.core.imageprocessor import process_image, ImageFormat - +from datetime import time class OrderStatus(str, enum.Enum): CREATED = "CREATED" # 已创建 CANCELLED = "CANCELLED" # 已取消 @@ -40,6 +40,11 @@ class ShippingOrderDB(Base): orderid = Column(String(32), primary_key=True) userid = Column(Integer, ForeignKey("users.userid"), index=True) + # 配送时段ID + time_period_id = Column(Integer, nullable=False, default=0) + time_period_name = Column(String(50), nullable=False, default='') + time_period_from_time = Column(Time, nullable=False, default=time(0, 0, 0)) + time_period_to_time = Column(Time, nullable=False, default=time(0, 0, 0)) # 配送地址信息 address_customer_name = Column(String(50), nullable=False, default='') # 客户名称快照 @@ -120,6 +125,8 @@ class OrderPriceCalculateRequest(BaseModel): class OrderCreate(BaseModel): addressid: int price_request: OrderPriceCalculateRequest + community_time_period_id: int = 0 + time_period_id: int = 0 delivery_method: DeliveryMethod = Field( default=DeliveryMethod.DELIVERY_AT_DOORSTEP, description="配送方式:放在门口或投递到家" @@ -129,6 +136,11 @@ class OrderInfo(BaseModel): orderid: str userid: int + time_period_id: int + time_period_name: str + time_period_from_time: time + time_period_to_time: time + address_customer_name: str address_customer_phone: str address_community_id: int