From 27d014c2bf7980c0b8c0dd9686d7b559eb1e01ca Mon Sep 17 00:00:00 2001 From: aaron <> Date: Thu, 6 Mar 2025 13:37:43 +0800 Subject: [PATCH] udpate --- app/api/deps.py | 4 +-- app/api/endpoints/community_timeperiod.py | 39 ++++++++++++++++++++--- app/api/endpoints/order.py | 11 ++++++- app/api/endpoints/user.py | 6 ++-- app/api/endpoints/wechat.py | 2 +- app/core/redis_client.py | 9 +++--- app/core/security.py | 18 +++++------ app/models/order.py | 11 ++++++- 8 files changed, 74 insertions(+), 26 deletions(-) diff --git a/app/api/deps.py b/app/api/deps.py index 5765db6..d624a25 100644 --- a/app/api/deps.py +++ b/app/api/deps.py @@ -20,8 +20,8 @@ async def get_current_user( if not token: raise HTTPException(status_code=401, detail="未提供有效的认证信息") - phone = verify_token(token) - if not phone: + sub, phone = verify_token(token) + if not sub: raise HTTPException(status_code=401, detail="Token已过期或无效") user = db.query(UserDB).filter(UserDB.phone == phone).first() diff --git a/app/api/endpoints/community_timeperiod.py b/app/api/endpoints/community_timeperiod.py index dc00f72..cf9272f 100644 --- a/app/api/endpoints/community_timeperiod.py +++ b/app/api/endpoints/community_timeperiod.py @@ -18,7 +18,7 @@ from typing import List, Optional import logging from sqlalchemy.orm import joinedload from app.core.redis_client import redis_client -from datetime import datetime +from datetime import datetime, timedelta router = APIRouter() @router.post("", response_model=ResponseModel) @@ -120,21 +120,52 @@ async def get_community_time_periods( ).order_by(TimePeriodDB.from_time).all() result = [] + tomorrow_count=0 + today_date = datetime.now().date() + tomorrow_date = today_date + timedelta(days=1) + + # 构建今日配送时段 for ctp in community_time_periods: # 获取今日订单数量 - today_orders_count = redis_client.get_community_period_today_orders_count(ctp.CommunityTimePeriodDB.id) + today_orders_count = redis_client.get_community_period_orders_count(today_date,ctp.CommunityTimePeriodDB.id) + + # 如果已经过了时段,则不加入列表 + if datetime.now().time() > ctp.time_period_to_time: + tomorrow_count+=1 + continue result.append({ "communtiy_time_period_id" :ctp.CommunityTimePeriodDB.id, "time_period_id": ctp.CommunityTimePeriodDB.time_period_id, - "time_period_name": ctp.time_period_name, + "time_period_name": f"今日 {ctp.time_period_name}", + "time_period_date": today_date, "capacity": ctp.CommunityTimePeriodDB.capacity, "from_time": ctp.time_period_from_time, "to_time": ctp.time_period_to_time, "order_full": today_orders_count >= ctp.CommunityTimePeriodDB.capacity, - "expired": datetime.now().time() > ctp.time_period_from_time + "is_default": False }) + # 构建明日配送时段 + for i in range(tomorrow_count): + ctp = community_time_periods[i] + result.append({ + "communtiy_time_period_id" :ctp.CommunityTimePeriodDB.id, + "time_period_id": ctp.CommunityTimePeriodDB.time_period_id, + "time_period_name": f"明日 {ctp.time_period_name}", + "time_period_date": tomorrow_date, + "capacity": ctp.CommunityTimePeriodDB.capacity, + "from_time": ctp.time_period_from_time, + "to_time": ctp.time_period_to_time, + "order_full": False, + "is_default": False + }) + + for ctp in result: + if not ctp['order_full']: + ctp['is_default'] = True + break + return success_response(data=result) except Exception as e: diff --git a/app/api/endpoints/order.py b/app/api/endpoints/order.py index 0470a22..54df245 100644 --- a/app/api/endpoints/order.py +++ b/app/api/endpoints/order.py @@ -240,6 +240,7 @@ async def create_order( final_amount=price_info.final_amount, status=OrderStatus.CREATED, delivery_method=order.delivery_method, + delivery_date=order.delivery_date, is_first_order=is_first_order ) @@ -444,7 +445,14 @@ async def get_order_detail( # 如果配送时段不为空,则使用配送时段的时间 if order.time_period_id: - delivery_time = f"预计 {order.time_period_name} 送达" + if order.delivery_date == datetime.now().date(): + delivery_time = f"今日 {order.time_period_name}" + elif order.delivery_date == datetime.now().date() + timedelta(days=1): + delivery_time = f"明日 {order.time_period_name}" + else: + delivery_time = f"{order.delivery_date} {order.time_period_name}" + else: + delivery_time = f"今日" # 构建响应数据 order_data = { @@ -471,6 +479,7 @@ async def get_order_detail( "pickup_time": order.pickup_time, "received_time": order.received_time, + "delivery_date": order.delivery_date, "delivery_method": order.delivery_method, "deliveryman_user_id": order.deliveryman_user_id, "deliveryman_nickname": deliveryman_user_name, diff --git a/app/api/endpoints/user.py b/app/api/endpoints/user.py index e1d2eca..a4b313f 100644 --- a/app/api/endpoints/user.py +++ b/app/api/endpoints/user.py @@ -103,7 +103,7 @@ async def login( # 创建访问令牌 access_token = create_access_token( - data={"phone": user.phone,"userid":user.userid} + data={"sub": user.userid, "phone": user.phone} ) # 设置JWT cookie @@ -203,7 +203,7 @@ async def phone_login( # 创建访问令牌 access_token = create_access_token( - data={"phone": user.phone,"userid":user.userid} + data={"phone": user.phone,"sub":user.userid} ) # 设置JWT cookie @@ -343,7 +343,7 @@ async def password_login( return error_response(code=401, message="配送员账户,请先设置归属小区") # 生成访问令牌 - access_token = create_access_token(data={"phone": user.phone,"userid":user.userid}) + access_token = create_access_token(data={"phone": user.phone,"sub":user.userid}) # 设置JWT cookie if response: diff --git a/app/api/endpoints/wechat.py b/app/api/endpoints/wechat.py index fd75a4e..600a0b4 100644 --- a/app/api/endpoints/wechat.py +++ b/app/api/endpoints/wechat.py @@ -111,7 +111,7 @@ async def wechat_phone_login( # 创建访问令牌 access_token = create_access_token( - data={"phone": user.phone, "userid": user.userid} + data={"phone": user.phone, "sub": user.userid} ) # 设置JWT cookie diff --git a/app/core/redis_client.py b/app/core/redis_client.py index 3576073..d437222 100644 --- a/app/core/redis_client.py +++ b/app/core/redis_client.py @@ -7,6 +7,7 @@ from sqlalchemy.orm import Session from app.models.user import UserDB from datetime import datetime from app.models.user import UserRole +from datetime import date class RedisClient: """Redis 客户端""" @@ -37,12 +38,12 @@ class RedisClient: return self.client - def push_order_to_community_period_today_queue(self, community_time_period_id: int, order_id: str) -> bool: + def push_order_to_community_period_queue(self, delivery_date: date,community_time_period_id: int, order_id: str) -> bool: """ 添加新订单到今日队列 """ try: - today_date_str = datetime.now().strftime("%Y-%m-%d") + today_date_str = delivery_date.strftime("%Y-%m-%d") key = f"community_period:{community_time_period_id}:today_orders:{today_date_str}" self.client.lpush(key, order_id) @@ -54,12 +55,12 @@ class RedisClient: logging.error(f"添加新订单到今日队列失败: {str(e)}") return False - def get_community_period_today_orders_count(self, community_time_period_id: int) -> int: + def get_community_period_orders_count(self, delivery_date: date, community_time_period_id: int) -> int: """ 获取今日队列中的订单数量 """ try: - today_date_str = datetime.now().strftime("%Y-%m-%d") + today_date_str = delivery_date.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: diff --git a/app/core/security.py b/app/core/security.py index f67d50d..3ea340d 100644 --- a/app/core/security.py +++ b/app/core/security.py @@ -11,11 +11,10 @@ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str: to_encode = data.copy() - # 更新 token 数据,不设置过期时间 - to_encode.update({ - "userid": data.get("userid"), - "phone": data.get("phone") - }) + if expires_delta: + to_encode.update({"exp": datetime.now(timezone.utc) + expires_delta}) + else: + to_encode.update({"exp": datetime.now(timezone.utc) + timedelta(days=180)}) encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm="HS256") return encoded_jwt @@ -44,12 +43,11 @@ def clear_jwt_cookie(response: Response): def verify_token(token: str) -> Optional[str]: try: payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"]) + sub: str = payload.get("sub") phone: str = payload.get("phone") - if phone is None: - return None - return phone + return sub, phone except JWTError: - return None + return None, None def get_password_hash(password: str) -> str: """获取密码哈希值""" @@ -64,7 +62,7 @@ def decode_jwt(token: str) -> dict: try: payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"]) return { - "userid": payload.get("userid"), + "userid": payload.get("sub"), "phone": payload.get("phone") } except: diff --git a/app/models/order.py b/app/models/order.py index 1fc582a..ecc0d8e 100644 --- a/app/models/order.py +++ b/app/models/order.py @@ -1,6 +1,6 @@ from datetime import datetime from typing import Optional, List -from sqlalchemy import Column, String, Integer, Float, DateTime, ForeignKey, Enum, Boolean, Time +from sqlalchemy import Column, String, Integer, Float, DateTime, ForeignKey, Enum, Boolean, Time, Date from sqlalchemy.sql import func from pydantic import BaseModel, Field from .database import Base @@ -8,6 +8,9 @@ import enum from app.models.user import Gender from app.core.imageprocessor import process_image, ImageFormat from datetime import time +from datetime import date + + class OrderStatus(str, enum.Enum): CREATED = "CREATED" # 已创建 CANCELLED = "CANCELLED" # 已取消 @@ -63,6 +66,7 @@ class ShippingOrderDB(Base): pickup_code_count = Column(Integer, nullable=False, default=0) # 取件码数量 delivery_method = Column(Enum(DeliveryMethod), nullable=False) + delivery_date = Column(Date, nullable=False, default=datetime.now().date()) package_count = Column(Integer, nullable=False) original_amount = Column(Float, nullable=False) coupon_discount_amount = Column(Float, default=0) @@ -126,6 +130,10 @@ class OrderCreate(BaseModel): addressid: int price_request: OrderPriceCalculateRequest community_time_period_id: int = 0 + delivery_date: date = Field( + default=datetime.now().date(), + description="配送日期" + ) delivery_method: DeliveryMethod = Field( default=DeliveryMethod.DELIVERY_AT_DOORSTEP, description="配送方式:放在门口或投递到家" @@ -163,6 +171,7 @@ class OrderInfo(BaseModel): optimized_complete_images: Optional[List[str]] = None create_time: datetime delivery_method: DeliveryMethod + delivery_date: date deliveryman_user_id: Optional[int] = None