2025-07-04 19:07:35 +08:00

183 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
订单模型
"""
from datetime import datetime, timedelta
import json
from config.database import db
from app.models.user import User
from app.models.product import Product
class Order(db.Model):
"""订单模型"""
__tablename__ = 'orders'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
order_sn = db.Column(db.String(50), unique=True, nullable=False)
total_amount = db.Column(db.Numeric(10, 2), nullable=False)
actual_amount = db.Column(db.Numeric(10, 2), nullable=False)
shipping_fee = db.Column(db.Numeric(10, 2), default=0)
status = db.Column(db.Integer, default=1) # 1-待支付 2-待发货 3-待收货 4-待评价 5-已完成 6-已取消 7-退款中
payment_method = db.Column(db.String(20))
shipping_method = db.Column(db.String(50))
receiver_info = db.Column(db.Text) # JSON格式存储收货人信息
remark = db.Column(db.Text)
shipped_at = db.Column(db.DateTime)
received_at = db.Column(db.DateTime)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# 关联关系
user = db.relationship('User', backref='orders')
order_items = db.relationship('OrderItem', backref='order', cascade='all, delete-orphan')
# 状态常量
STATUS_PENDING_PAYMENT = 1 # 待支付
STATUS_PENDING_SHIPMENT = 2 # 待发货
STATUS_SHIPPED = 3 # 待收货
STATUS_PENDING_REVIEW = 4 # 待评价
STATUS_COMPLETED = 5 # 已完成
STATUS_CANCELLED = 6 # 已取消
STATUS_REFUNDING = 7 # 退款中
STATUS_CHOICES = {
STATUS_PENDING_PAYMENT: '待支付',
STATUS_PENDING_SHIPMENT: '待发货',
STATUS_SHIPPED: '待收货',
STATUS_PENDING_REVIEW: '待评价',
STATUS_COMPLETED: '已完成',
STATUS_CANCELLED: '已取消',
STATUS_REFUNDING: '退款中'
}
def get_status_text(self):
"""获取状态文本"""
return self.STATUS_CHOICES.get(self.status, '未知状态')
def get_receiver_info(self):
"""获取收货人信息"""
if self.receiver_info:
try:
return json.loads(self.receiver_info)
except:
return {}
return {}
def set_receiver_info(self, info):
"""设置收货人信息"""
if isinstance(info, dict):
self.receiver_info = json.dumps(info, ensure_ascii=False)
def is_expired(self):
"""检查订单是否已过期15分钟未支付"""
if self.status == self.STATUS_PENDING_PAYMENT:
expire_time = self.created_at + timedelta(minutes=15)
return datetime.utcnow() > expire_time
return False
def can_cancel(self):
"""检查是否可以取消"""
return self.status in [self.STATUS_PENDING_PAYMENT, self.STATUS_PENDING_SHIPMENT]
def can_pay(self):
"""检查是否可以支付"""
return self.status == self.STATUS_PENDING_PAYMENT and not self.is_expired()
def can_confirm_receipt(self):
"""检查是否可以确认收货"""
return self.status == self.STATUS_SHIPPED
def to_dict(self):
"""转换为字典"""
return {
'id': self.id,
'order_sn': self.order_sn,
'total_amount': float(self.total_amount),
'actual_amount': float(self.actual_amount),
'shipping_fee': float(self.shipping_fee),
'status': self.status,
'status_text': self.get_status_text(),
'payment_method': self.payment_method,
'shipping_method': self.shipping_method,
'receiver_info': self.get_receiver_info(),
'remark': self.remark,
'can_cancel': self.can_cancel(),
'can_pay': self.can_pay(),
'can_confirm_receipt': self.can_confirm_receipt(),
'is_expired': self.is_expired(),
'created_at': self.created_at.isoformat() if self.created_at else None,
'shipped_at': self.shipped_at.isoformat() if self.shipped_at else None,
'received_at': self.received_at.isoformat() if self.received_at else None
}
@classmethod
def generate_order_sn(cls):
"""生成订单号"""
import time
import random
timestamp = str(int(time.time()))
random_str = str(random.randint(100000, 999999))
return f"TB{timestamp}{random_str}"
def __repr__(self):
return f'<Order {self.order_sn}>'
class OrderItem(db.Model):
"""订单商品明细模型"""
__tablename__ = 'order_items'
id = db.Column(db.Integer, primary_key=True)
order_id = db.Column(db.Integer, db.ForeignKey('orders.id'), nullable=False)
product_id = db.Column(db.Integer, db.ForeignKey('products.id'), nullable=False)
sku_code = db.Column(db.String(100))
product_name = db.Column(db.String(200), nullable=False)
product_image = db.Column(db.String(255))
spec_combination = db.Column(db.String(255))
price = db.Column(db.Numeric(10, 2), nullable=False)
quantity = db.Column(db.Integer, nullable=False)
total_price = db.Column(db.Numeric(10, 2), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
# 关联关系
product = db.relationship('Product', backref='order_items')
def to_dict(self):
"""转换为字典"""
return {
'id': self.id,
'product_id': self.product_id,
'product_name': self.product_name,
'product_image': self.product_image,
'spec_combination': self.spec_combination,
'price': float(self.price),
'quantity': self.quantity,
'total_price': float(self.total_price)
}
def __repr__(self):
return f'<OrderItem {self.product_name}>'
class ShippingInfo(db.Model):
"""物流信息模型"""
__tablename__ = 'shipping_info'
id = db.Column(db.Integer, primary_key=True)
order_id = db.Column(db.Integer, db.ForeignKey('orders.id'), nullable=False)
shipping_company = db.Column(db.String(50))
tracking_number = db.Column(db.String(100))
shipping_status = db.Column(db.Integer, default=1) # 1-已发货 2-运输中 3-已送达
shipping_address = db.Column(db.Text)
estimated_delivery = db.Column(db.DateTime)
actual_delivery = db.Column(db.DateTime)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# 关联关系
order = db.relationship('Order', backref='shipping_info')
def __repr__(self):
return f'<ShippingInfo {self.tracking_number}>'