Improve public pages
This commit is contained in:
@@ -13,6 +13,7 @@ AuditLog = create_audit_log_model(Base)
|
||||
|
||||
# Import all models to register them with the Base metadata
|
||||
from .tenants import Tenant, TenantMember, Subscription
|
||||
from .coupon import CouponModel, CouponRedemptionModel
|
||||
|
||||
# List all models for easier access
|
||||
__all__ = [
|
||||
@@ -20,4 +21,6 @@ __all__ = [
|
||||
"TenantMember",
|
||||
"Subscription",
|
||||
"AuditLog",
|
||||
"CouponModel",
|
||||
"CouponRedemptionModel",
|
||||
]
|
||||
|
||||
64
services/tenant/app/models/coupon.py
Normal file
64
services/tenant/app/models/coupon.py
Normal file
@@ -0,0 +1,64 @@
|
||||
"""
|
||||
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"<Coupon(code='{self.code}', type='{self.discount_type}', value={self.discount_value})>"
|
||||
|
||||
|
||||
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"<CouponRedemption(tenant_id='{self.tenant_id}', code='{self.coupon_code}')>"
|
||||
Reference in New Issue
Block a user