120 lines
4.2 KiB
Python
120 lines
4.2 KiB
Python
from datetime import datetime
|
||
from typing import Optional, List
|
||
from sqlalchemy import Column, String, Integer, Float, DateTime, ForeignKey, Enum
|
||
from sqlalchemy.sql import func
|
||
from pydantic import BaseModel, Field
|
||
from .database import Base
|
||
import enum
|
||
|
||
class OrderStatus(str, enum.Enum):
|
||
CREATED = "created" # 已下单
|
||
ACCEPTED = "accepted" # 已接单
|
||
UNPAID = "unpaid" # 未支付
|
||
COMPLETED = "completed" # 已完成
|
||
CANCELLED = "cancelled" # 已取消
|
||
|
||
class DeliveryMethod(str, enum.Enum):
|
||
DELIVERY_TO_DOOR = "delivery_to_door" # 放在门口
|
||
DELIVERY_TO_ROOM = "delivery_to_room" # 投递到家
|
||
|
||
# 数据库模型
|
||
class ShippingOrderDB(Base):
|
||
__tablename__ = "shipping_orders"
|
||
|
||
orderid = Column(String(32), primary_key=True)
|
||
userid = Column(Integer, ForeignKey("users.userid"), index=True)
|
||
addressid = Column(Integer, ForeignKey("delivery_addresses.id"), index=True)
|
||
package_count = Column(Integer, nullable=False)
|
||
original_amount = Column(Float, nullable=False)
|
||
coupon_discount_amount = Column(Float, default=0)
|
||
coupon_id = Column(Integer, ForeignKey("user_coupons.id"), nullable=True)
|
||
final_amount = Column(Float, nullable=False)
|
||
status = Column(Enum(OrderStatus), nullable=False, default=OrderStatus.CREATED)
|
||
cancel_reason = Column(String(200), nullable=True) # 取消原因
|
||
complete_images = Column(String(1000), nullable=True) # 完成订单的图片URL,多个URL用逗号分隔
|
||
create_time = Column(DateTime(timezone=True), server_default=func.now())
|
||
delivery_method = Column(Enum(DeliveryMethod), nullable=False, default=DeliveryMethod.DELIVERY_TO_DOOR)
|
||
|
||
class ShippingOrderPackageDB(Base):
|
||
__tablename__ = "shipping_order_packages"
|
||
|
||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
orderid = Column(String(32), ForeignKey("shipping_orders.orderid"), index=True)
|
||
station_id = Column(Integer, ForeignKey("stations.id"), index=True)
|
||
pickup_codes = Column(String(100), nullable=False)
|
||
create_time = Column(DateTime(timezone=True), server_default=func.now())
|
||
|
||
# Pydantic 模型
|
||
class OrderPackage(BaseModel):
|
||
station_id: int
|
||
pickup_codes: str = Field(..., max_length=100)
|
||
|
||
# 先定义 OrderPriceCalculateRequest
|
||
class OrderPriceCalculateRequest(BaseModel):
|
||
packages: List[OrderPackage]
|
||
|
||
# 然后再定义 OrderCreate
|
||
class OrderCreate(BaseModel):
|
||
addressid: int
|
||
price_request: OrderPriceCalculateRequest
|
||
delivery_method: DeliveryMethod = Field(
|
||
default=DeliveryMethod.DELIVERY_TO_DOOR,
|
||
description="配送方式:放在门口或投递到家"
|
||
)
|
||
|
||
class OrderInfo(BaseModel):
|
||
orderid: str
|
||
userid: int
|
||
addressid: int
|
||
package_count: int
|
||
original_amount: float
|
||
coupon_discount_amount: float
|
||
coupon_id: Optional[int]
|
||
final_amount: float
|
||
status: OrderStatus
|
||
complete_images: Optional[List[str]] = None
|
||
create_time: datetime
|
||
delivery_method: DeliveryMethod
|
||
|
||
def __init__(self, **data):
|
||
super().__init__(**data)
|
||
# 将逗号分隔的图片URL字符串转换为列表
|
||
if self.complete_images and isinstance(self.complete_images, str):
|
||
self.complete_images = self.complete_images.split(",")
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
class OrderPackageInfo(BaseModel):
|
||
id: int
|
||
orderid: str
|
||
station_id: int
|
||
pickup_codes: str
|
||
create_time: datetime
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
def generate_order_id() -> str:
|
||
"""生成订单号:日期+时间戳"""
|
||
now = datetime.now()
|
||
# 生成8位日期 + 6位序号,共14位
|
||
date_str = now.strftime('%Y%m%d') # 8位日期
|
||
# 生成6位序号(毫秒级时间戳后6位)
|
||
timestamp = str(int(now.timestamp() * 1000))[-6:]
|
||
return f"{date_str}{timestamp}"
|
||
|
||
class OrderPriceInfo(BaseModel):
|
||
package_count: int
|
||
original_amount: float
|
||
coupon_discount_amount: float
|
||
coupon_id: Optional[int] = None
|
||
final_amount: float
|
||
|
||
# 添加取消订单请求模型
|
||
class OrderCancel(BaseModel):
|
||
reason: str = Field(..., max_length=200, description="取消原因")
|
||
|
||
# 完成订单请求模型
|
||
class OrderComplete(BaseModel):
|
||
images: Optional[List[str]] = Field(None, max_items=5) # 最多5张图片,可选 |