""" 订单模型 """ 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'' 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'' 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''