File size: 5,103 Bytes
bb6d7b4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""
Subscription models for the application.

This module defines database models for subscription management.
"""
from enum import Enum
from sqlalchemy import Column, Integer, String, Float, Boolean, DateTime, ForeignKey, Enum as SQLAlchemyEnum
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func

from src.models.base import Base


class SubscriptionTier(str, Enum):
    """Subscription tier enum."""
    FREE = "FREE"
    BASIC = "BASIC"
    PROFESSIONAL = "PROFESSIONAL"
    ENTERPRISE = "ENTERPRISE"


class BillingPeriod(str, Enum):
    """Billing period enum."""
    MONTHLY = "MONTHLY"
    ANNUALLY = "ANNUALLY"
    CUSTOM = "CUSTOM"


class SubscriptionPlan(Base):
    """Subscription plan model."""
    __tablename__ = "subscription_plans"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(100), nullable=False)
    tier = Column(SQLAlchemyEnum(SubscriptionTier), nullable=False)
    description = Column(String(500))
    price_monthly = Column(Float, nullable=False)
    price_annually = Column(Float, nullable=False)
    is_active = Column(Boolean, default=True)
    
    # Features
    max_alerts = Column(Integer, default=10)
    max_reports = Column(Integer, default=5)
    max_searches_per_day = Column(Integer, default=20)
    max_monitoring_keywords = Column(Integer, default=10)
    max_data_retention_days = Column(Integer, default=30)
    supports_api_access = Column(Boolean, default=False)
    supports_live_feed = Column(Boolean, default=False)
    supports_dark_web_monitoring = Column(Boolean, default=False)
    supports_export = Column(Boolean, default=False)
    supports_advanced_analytics = Column(Boolean, default=False)
    
    # Stripe product ID (for integration with Stripe)
    stripe_product_id = Column(String(100))
    stripe_monthly_price_id = Column(String(100))
    stripe_annual_price_id = Column(String(100))
    
    # Timestamps
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), onupdate=func.now())
    
    # Relationships
    subscriptions = relationship("UserSubscription", back_populates="plan")
    
    def __repr__(self):
        return f"<SubscriptionPlan(id={self.id}, name={self.name}, tier={self.tier})>"


class SubscriptionStatus(str, Enum):
    """Subscription status enum."""
    ACTIVE = "ACTIVE"
    PAST_DUE = "PAST_DUE"
    CANCELED = "CANCELED"
    TRIALING = "TRIALING"
    INCOMPLETE = "INCOMPLETE"
    INCOMPLETE_EXPIRED = "INCOMPLETE_EXPIRED"


class UserSubscription(Base):
    """User subscription model."""
    __tablename__ = "user_subscriptions"

    id = Column(Integer, primary_key=True, index=True)
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
    plan_id = Column(Integer, ForeignKey("subscription_plans.id"), nullable=False)
    status = Column(SQLAlchemyEnum(SubscriptionStatus), nullable=False, default=SubscriptionStatus.ACTIVE)
    
    # Billing details
    billing_period = Column(SQLAlchemyEnum(BillingPeriod), nullable=False, default=BillingPeriod.MONTHLY)
    current_period_start = Column(DateTime(timezone=True))
    current_period_end = Column(DateTime(timezone=True))
    
    # Stripe subscription ID
    stripe_subscription_id = Column(String(100))
    stripe_customer_id = Column(String(100))
    
    # 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))
    
    # Relationships
    user = relationship("User", back_populates="subscriptions")
    plan = relationship("SubscriptionPlan", back_populates="subscriptions")
    payment_history = relationship("PaymentHistory", back_populates="subscription")
    
    def __repr__(self):
        return f"<UserSubscription(id={self.id}, user_id={self.user_id}, plan_id={self.plan_id})>"


class PaymentStatus(str, Enum):
    """Payment status enum."""
    SUCCEEDED = "SUCCEEDED"
    PENDING = "PENDING"
    FAILED = "FAILED"
    REFUNDED = "REFUNDED"


class PaymentHistory(Base):
    """Payment history model."""
    __tablename__ = "payment_history"

    id = Column(Integer, primary_key=True, index=True)
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
    subscription_id = Column(Integer, ForeignKey("user_subscriptions.id"), nullable=False)
    
    amount = Column(Float, nullable=False)
    currency = Column(String(3), default="USD")
    status = Column(SQLAlchemyEnum(PaymentStatus), nullable=False)
    
    # Stripe payment intent ID
    stripe_payment_intent_id = Column(String(100))
    stripe_invoice_id = Column(String(100))
    
    # Timestamps
    payment_date = Column(DateTime(timezone=True), server_default=func.now())
    
    # Relationships
    user = relationship("User")
    subscription = relationship("UserSubscription", back_populates="payment_history")
    
    def __repr__(self):
        return f"<PaymentHistory(id={self.id}, user_id={self.user_id}, amount={self.amount}, status={self.status})>"