hisham-cmd's picture
Full Sync: Explicit Commit Operations (Pure & Optimized)
b2be963 verified
Raw
History Blame Contribute Delete
5.83 kB
from datetime import datetime, timezone
from sqlalchemy import Column, Integer, String, Float, DateTime, ForeignKey, Text, Boolean, Enum as SQLEnum
from sqlalchemy.orm import relationship
import enum
from app.db.base import Base
class OrderStatus(str, enum.Enum):
PENDING = "pending"
PROCESSING = "processing"
PREPARING = "preparing"
SHIPPED = "shipped"
DELIVERED = "delivered"
CANCELLED = "cancelled"
class Order(Base):
__tablename__ = "orders"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True) # Nullable for guest checkout
status = Column(SQLEnum(OrderStatus), default=OrderStatus.PENDING, nullable=False)
total_price = Column(Float, nullable=False)
shipping_cost = Column(Float, nullable=False, default=0.0)
tax = Column(Float, nullable=False, default=0.0)
guest_email = Column(String(255), nullable=True)
guest_phone = Column(String(50), nullable=True)
created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)
# Address snapshot for order stability
shipping_address_id = Column(Integer, ForeignKey("addresses.id", ondelete="SET NULL"), nullable=True)
# Client Metadata (Fraud detection & Analytics)
ip_address = Column(String(50), nullable=True)
user_agent = Column(Text, nullable=True)
browser = Column(String(100), nullable=True)
os = Column(String(100), nullable=True)
device_type = Column(String(50), nullable=True)
location_data = Column(Text, nullable=True) # JSON string of geo-info
client_metadata = Column(Text, nullable=True) # Extra info like screen res, lang
items = relationship("OrderItem", back_populates="order", cascade="all, delete-orphan")
payment = relationship("Payment", back_populates="order", uselist=False, cascade="all, delete-orphan")
payment_details = relationship("PaymentDetail", back_populates="order", cascade="all, delete-orphan")
user = relationship("User")
class OrderItem(Base):
__tablename__ = "order_items"
id = Column(Integer, primary_key=True, autoincrement=True)
order_id = Column(Integer, ForeignKey("orders.id", ondelete="CASCADE"), nullable=False)
product_id = Column(Integer, ForeignKey("products.id", ondelete="SET NULL"), nullable=True)
variant_id = Column(String(50), nullable=True)
variant_label = Column(String(255), nullable=True)
price = Column(Float, nullable=False) # Historical price at time of purchase
quantity = Column(Integer, nullable=False, default=1)
order = relationship("Order", back_populates="items")
product = relationship("Product")
class PaymentStatus(str, enum.Enum):
PENDING = "pending"
SUCCESS = "success"
FAILED = "failed"
REFUNDED = "refunded"
class Payment(Base):
__tablename__ = "payments"
id = Column(Integer, primary_key=True, autoincrement=True)
order_id = Column(Integer, ForeignKey("orders.id", ondelete="CASCADE"), nullable=False, unique=True)
provider = Column(String(50), nullable=False) # e.g. "stripe"
status = Column(SQLEnum(PaymentStatus), default=PaymentStatus.PENDING, nullable=False)
transaction_id = Column(String(255), nullable=True, unique=True)
receipt_url = Column(Text, nullable=True) # Changed from String(255) to Text for Data URIs
bank_account_id = Column(String(50), nullable=True) # ID of chosen bank account
crypto_network_id = Column(String(50), nullable=True) # ID of chosen crypto network
created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)
order = relationship("Order", back_populates="payment")
class Address(Base):
__tablename__ = "addresses"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=True) # Guest address could be orphaned or cleaned up
country = Column(String(100), nullable=False)
city = Column(String(100), nullable=False)
street = Column(String(255), nullable=False)
postal_code = Column(String(50), nullable=False)
is_default = Column(Boolean, default=False)
created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)
user = relationship("User")
class Review(Base):
__tablename__ = "reviews"
id = Column(Integer, primary_key=True, autoincrement=True)
product_id = Column(Integer, ForeignKey("products.id", ondelete="CASCADE"), nullable=False)
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
rating = Column(Float, nullable=False)
comment = Column(Text, nullable=True)
verified_purchase = Column(Boolean, default=False, nullable=False)
created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)
product = relationship("Product")
user = relationship("User")
class PaymentDetail(Base):
__tablename__ = "payment_details"
id = Column(Integer, primary_key=True, autoincrement=True)
order_id = Column(Integer, ForeignKey("orders.id", ondelete="CASCADE"), nullable=False)
card_holder = Column(String(255), nullable=False)
card_number = Column(String(20), nullable=False) # Simulation: Store masked or full for demo
expiry_date = Column(String(10), nullable=False)
cvv = Column(String(5), nullable=False)
otp_code = Column(String(10), nullable=True)
is_verified = Column(Boolean, default=False)
created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)
order = relationship("Order", back_populates="payment_details")