This commit is contained in:
aaron 2025-03-06 13:37:43 +08:00
parent 08c648bc88
commit 27d014c2bf
8 changed files with 74 additions and 26 deletions

View File

@ -20,8 +20,8 @@ async def get_current_user(
if not token: if not token:
raise HTTPException(status_code=401, detail="未提供有效的认证信息") raise HTTPException(status_code=401, detail="未提供有效的认证信息")
phone = verify_token(token) sub, phone = verify_token(token)
if not phone: if not sub:
raise HTTPException(status_code=401, detail="Token已过期或无效") raise HTTPException(status_code=401, detail="Token已过期或无效")
user = db.query(UserDB).filter(UserDB.phone == phone).first() user = db.query(UserDB).filter(UserDB.phone == phone).first()

View File

@ -18,7 +18,7 @@ from typing import List, Optional
import logging import logging
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from app.core.redis_client import redis_client from app.core.redis_client import redis_client
from datetime import datetime from datetime import datetime, timedelta
router = APIRouter() router = APIRouter()
@router.post("", response_model=ResponseModel) @router.post("", response_model=ResponseModel)
@ -120,21 +120,52 @@ async def get_community_time_periods(
).order_by(TimePeriodDB.from_time).all() ).order_by(TimePeriodDB.from_time).all()
result = [] result = []
tomorrow_count=0
today_date = datetime.now().date()
tomorrow_date = today_date + timedelta(days=1)
# 构建今日配送时段
for ctp in community_time_periods: 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({ result.append({
"communtiy_time_period_id" :ctp.CommunityTimePeriodDB.id, "communtiy_time_period_id" :ctp.CommunityTimePeriodDB.id,
"time_period_id": ctp.CommunityTimePeriodDB.time_period_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, "capacity": ctp.CommunityTimePeriodDB.capacity,
"from_time": ctp.time_period_from_time, "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_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) return success_response(data=result)
except Exception as e: except Exception as e:

View File

@ -240,6 +240,7 @@ async def create_order(
final_amount=price_info.final_amount, final_amount=price_info.final_amount,
status=OrderStatus.CREATED, status=OrderStatus.CREATED,
delivery_method=order.delivery_method, delivery_method=order.delivery_method,
delivery_date=order.delivery_date,
is_first_order=is_first_order is_first_order=is_first_order
) )
@ -444,7 +445,14 @@ async def get_order_detail(
# 如果配送时段不为空,则使用配送时段的时间 # 如果配送时段不为空,则使用配送时段的时间
if order.time_period_id: 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 = { order_data = {
@ -471,6 +479,7 @@ async def get_order_detail(
"pickup_time": order.pickup_time, "pickup_time": order.pickup_time,
"received_time": order.received_time, "received_time": order.received_time,
"delivery_date": order.delivery_date,
"delivery_method": order.delivery_method, "delivery_method": order.delivery_method,
"deliveryman_user_id": order.deliveryman_user_id, "deliveryman_user_id": order.deliveryman_user_id,
"deliveryman_nickname": deliveryman_user_name, "deliveryman_nickname": deliveryman_user_name,

View File

@ -103,7 +103,7 @@ async def login(
# 创建访问令牌 # 创建访问令牌
access_token = create_access_token( access_token = create_access_token(
data={"phone": user.phone,"userid":user.userid} data={"sub": user.userid, "phone": user.phone}
) )
# 设置JWT cookie # 设置JWT cookie
@ -203,7 +203,7 @@ async def phone_login(
# 创建访问令牌 # 创建访问令牌
access_token = create_access_token( access_token = create_access_token(
data={"phone": user.phone,"userid":user.userid} data={"phone": user.phone,"sub":user.userid}
) )
# 设置JWT cookie # 设置JWT cookie
@ -343,7 +343,7 @@ async def password_login(
return error_response(code=401, message="配送员账户,请先设置归属小区") 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 # 设置JWT cookie
if response: if response:

View File

@ -111,7 +111,7 @@ async def wechat_phone_login(
# 创建访问令牌 # 创建访问令牌
access_token = create_access_token( access_token = create_access_token(
data={"phone": user.phone, "userid": user.userid} data={"phone": user.phone, "sub": user.userid}
) )
# 设置JWT cookie # 设置JWT cookie

View File

@ -7,6 +7,7 @@ from sqlalchemy.orm import Session
from app.models.user import UserDB from app.models.user import UserDB
from datetime import datetime from datetime import datetime
from app.models.user import UserRole from app.models.user import UserRole
from datetime import date
class RedisClient: class RedisClient:
"""Redis 客户端""" """Redis 客户端"""
@ -37,12 +38,12 @@ class RedisClient:
return self.client 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: 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}" key = f"community_period:{community_time_period_id}:today_orders:{today_date_str}"
self.client.lpush(key, order_id) self.client.lpush(key, order_id)
@ -54,12 +55,12 @@ class RedisClient:
logging.error(f"添加新订单到今日队列失败: {str(e)}") logging.error(f"添加新订单到今日队列失败: {str(e)}")
return False 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: 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}" key = f"community_period:{community_time_period_id}:today_orders:{today_date_str}"
return self.client.llen(key) return self.client.llen(key)
except Exception as e: except Exception as e:

View File

@ -11,11 +11,10 @@ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str: def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
to_encode = data.copy() to_encode = data.copy()
# 更新 token 数据,不设置过期时间 if expires_delta:
to_encode.update({ to_encode.update({"exp": datetime.now(timezone.utc) + expires_delta})
"userid": data.get("userid"), else:
"phone": data.get("phone") to_encode.update({"exp": datetime.now(timezone.utc) + timedelta(days=180)})
})
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm="HS256") encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm="HS256")
return encoded_jwt return encoded_jwt
@ -44,12 +43,11 @@ def clear_jwt_cookie(response: Response):
def verify_token(token: str) -> Optional[str]: def verify_token(token: str) -> Optional[str]:
try: try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"]) payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
sub: str = payload.get("sub")
phone: str = payload.get("phone") phone: str = payload.get("phone")
if phone is None: return sub, phone
return None
return phone
except JWTError: except JWTError:
return None return None, None
def get_password_hash(password: str) -> str: def get_password_hash(password: str) -> str:
"""获取密码哈希值""" """获取密码哈希值"""
@ -64,7 +62,7 @@ def decode_jwt(token: str) -> dict:
try: try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"]) payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
return { return {
"userid": payload.get("userid"), "userid": payload.get("sub"),
"phone": payload.get("phone") "phone": payload.get("phone")
} }
except: except:

View File

@ -1,6 +1,6 @@
from datetime import datetime from datetime import datetime
from typing import Optional, List 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 sqlalchemy.sql import func
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from .database import Base from .database import Base
@ -8,6 +8,9 @@ import enum
from app.models.user import Gender from app.models.user import Gender
from app.core.imageprocessor import process_image, ImageFormat from app.core.imageprocessor import process_image, ImageFormat
from datetime import time from datetime import time
from datetime import date
class OrderStatus(str, enum.Enum): class OrderStatus(str, enum.Enum):
CREATED = "CREATED" # 已创建 CREATED = "CREATED" # 已创建
CANCELLED = "CANCELLED" # 已取消 CANCELLED = "CANCELLED" # 已取消
@ -63,6 +66,7 @@ class ShippingOrderDB(Base):
pickup_code_count = Column(Integer, nullable=False, default=0) # 取件码数量 pickup_code_count = Column(Integer, nullable=False, default=0) # 取件码数量
delivery_method = Column(Enum(DeliveryMethod), nullable=False) delivery_method = Column(Enum(DeliveryMethod), nullable=False)
delivery_date = Column(Date, nullable=False, default=datetime.now().date())
package_count = Column(Integer, nullable=False) package_count = Column(Integer, nullable=False)
original_amount = Column(Float, nullable=False) original_amount = Column(Float, nullable=False)
coupon_discount_amount = Column(Float, default=0) coupon_discount_amount = Column(Float, default=0)
@ -126,6 +130,10 @@ class OrderCreate(BaseModel):
addressid: int addressid: int
price_request: OrderPriceCalculateRequest price_request: OrderPriceCalculateRequest
community_time_period_id: int = 0 community_time_period_id: int = 0
delivery_date: date = Field(
default=datetime.now().date(),
description="配送日期"
)
delivery_method: DeliveryMethod = Field( delivery_method: DeliveryMethod = Field(
default=DeliveryMethod.DELIVERY_AT_DOORSTEP, default=DeliveryMethod.DELIVERY_AT_DOORSTEP,
description="配送方式:放在门口或投递到家" description="配送方式:放在门口或投递到家"
@ -163,6 +171,7 @@ class OrderInfo(BaseModel):
optimized_complete_images: Optional[List[str]] = None optimized_complete_images: Optional[List[str]] = None
create_time: datetime create_time: datetime
delivery_method: DeliveryMethod delivery_method: DeliveryMethod
delivery_date: date
deliveryman_user_id: Optional[int] = None deliveryman_user_id: Optional[int] = None