lumaspeech-backend / database /models /subscription.py
yasmine hemmati
Initial deployment: LumaSpeech Backend API with GPU support
d646f8a
Raw
History Blame Contribute Delete
3.15 kB
"""
Subscription model - Tracks therapist billing and student limits
"""
from sqlalchemy import Column, Integer, String, Float, DateTime, ForeignKey, Boolean, Enum
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from config.database import Base
import enum
class PlanType(enum.Enum):
FREE = "free"
BASIC = "basic" # e.g., $29/month - up to 5 students
PROFESSIONAL = "professional" # e.g., $79/month - up to 20 students
ENTERPRISE = "enterprise" # Custom pricing - unlimited students
class BillingPeriod(enum.Enum):
MONTHLY = "monthly"
YEARLY = "yearly"
class Subscription(Base):
__tablename__ = "subscriptions"
id = Column(Integer, primary_key=True, index=True)
therapist_id = Column(Integer, ForeignKey("therapists.id"), unique=True, nullable=False)
# Plan details
plan_type = Column(Enum(PlanType), nullable=False, default=PlanType.FREE)
billing_period = Column(Enum(BillingPeriod), nullable=True)
# Pricing
base_price = Column(Float, default=0.0) # Base monthly price
per_student_price = Column(Float, default=0.0) # Additional cost per student over limit
# Limits
included_students = Column(Integer, default=1) # Students included in base price
max_students = Column(Integer, nullable=True) # Hard limit (null = unlimited)
current_student_count = Column(Integer, default=0) # Active students
# Billing
stripe_customer_id = Column(String, nullable=True)
stripe_subscription_id = Column(String, nullable=True)
# Status
is_active = Column(Boolean, default=True)
trial_ends_at = Column(DateTime(timezone=True), nullable=True)
current_period_start = Column(DateTime(timezone=True), nullable=True)
current_period_end = Column(DateTime(timezone=True), nullable=True)
# Timestamps
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
canceled_at = Column(DateTime(timezone=True), nullable=True)
# Relationships
therapist = relationship("Therapist", backref="subscription")
def calculate_monthly_cost(self):
"""Calculate total monthly cost based on current student count"""
base = self.base_price
# If yearly billing, calculate monthly equivalent
if self.billing_period == BillingPeriod.YEARLY:
base = base / 12
# Calculate overage if exceeding included students
if self.current_student_count > self.included_students:
overage = self.current_student_count - self.included_students
additional = overage * self.per_student_price
return base + additional
return base
def can_add_student(self):
"""Check if therapist can add another student"""
if self.max_students is None:
return True
return self.current_student_count < self.max_students
def __repr__(self):
return f"<Subscription {self.plan_type.value} for therapist {self.therapist_id}>"