""" SQLAlchemy models for coupon system """ from datetime import datetime from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, JSON, Index from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import UUID import uuid from shared.database import Base class CouponModel(Base): """Coupon configuration table""" __tablename__ = "coupons" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) code = Column(String(50), unique=True, nullable=False, index=True) discount_type = Column(String(20), nullable=False) # trial_extension, percentage, fixed_amount discount_value = Column(Integer, nullable=False) # Days/percentage/cents depending on type max_redemptions = Column(Integer, nullable=True) # None = unlimited current_redemptions = Column(Integer, nullable=False, default=0) valid_from = Column(DateTime(timezone=True), nullable=False) valid_until = Column(DateTime(timezone=True), nullable=True) # None = no expiry active = Column(Boolean, nullable=False, default=True) created_at = Column(DateTime(timezone=True), nullable=False, default=datetime.utcnow) extra_data = Column(JSON, nullable=True) # Renamed from metadata to avoid SQLAlchemy reserved name # Relationships redemptions = relationship("CouponRedemptionModel", back_populates="coupon") # Indexes for performance __table_args__ = ( Index('idx_coupon_code_active', 'code', 'active'), Index('idx_coupon_valid_dates', 'valid_from', 'valid_until'), ) def __repr__(self): return f"" class CouponRedemptionModel(Base): """Coupon redemption history table""" __tablename__ = "coupon_redemptions" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) tenant_id = Column(String(255), nullable=False, index=True) coupon_code = Column(String(50), ForeignKey('coupons.code'), nullable=False) redeemed_at = Column(DateTime(timezone=True), nullable=False, default=datetime.utcnow) discount_applied = Column(JSON, nullable=False) # Details of discount applied extra_data = Column(JSON, nullable=True) # Renamed from metadata to avoid SQLAlchemy reserved name # Relationships coupon = relationship("CouponModel", back_populates="redemptions") # Constraints __table_args__ = ( Index('idx_redemption_tenant', 'tenant_id'), Index('idx_redemption_coupon', 'coupon_code'), Index('idx_redemption_tenant_coupon', 'tenant_id', 'coupon_code'), # Prevent duplicate redemptions ) def __repr__(self): return f""