This commit is contained in:
2025-06-24 11:25:10 +02:00
parent 6412d9f01a
commit 996adb4bce
15 changed files with 1695 additions and 4 deletions

View File

@@ -586,4 +586,92 @@ class HelpArticle(db.Model):
if article.category not in grouped:
grouped[article.category] = []
grouped[article.category].append(article)
return grouped
return grouped
class PricingPlan(db.Model):
__tablename__ = 'pricing_plans'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text)
monthly_price = db.Column(db.Float, nullable=False)
annual_price = db.Column(db.Float, nullable=False)
features = db.Column(db.JSON, nullable=False) # List of feature strings
is_popular = db.Column(db.Boolean, default=False)
is_custom = db.Column(db.Boolean, default=False)
button_text = db.Column(db.String(50), default='Get Started')
button_url = db.Column(db.String(200), default='#')
order_index = db.Column(db.Integer, default=0)
is_active = db.Column(db.Boolean, default=True)
# Quota fields
room_quota = db.Column(db.Integer, default=0) # 0 = unlimited
conversation_quota = db.Column(db.Integer, default=0) # 0 = unlimited
storage_quota_gb = db.Column(db.Integer, default=0) # 0 = unlimited, stored in GB
manager_quota = db.Column(db.Integer, default=0) # 0 = unlimited
admin_quota = db.Column(db.Integer, default=0) # 0 = unlimited
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
created_by = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
# Relationships
creator = db.relationship('User', backref=db.backref('created_pricing_plans', cascade='all, delete-orphan'), foreign_keys=[created_by])
def __repr__(self):
return f'<PricingPlan {self.name}>'
@classmethod
def get_active_plans(cls):
"""Get all active pricing plans ordered by order_index"""
return cls.query.filter_by(is_active=True).order_by(cls.order_index).all()
@classmethod
def get_popular_plan(cls):
"""Get the plan marked as most popular"""
return cls.query.filter_by(is_active=True, is_popular=True).first()
def get_storage_quota_bytes(self):
"""Get storage quota in bytes"""
if self.storage_quota_gb == 0:
return 0 # Unlimited
return self.storage_quota_gb * 1024 * 1024 * 1024 # Convert GB to bytes
def format_quota_display(self, quota_type):
"""Format quota for display"""
if quota_type == 'room_quota':
return 'Unlimited' if self.room_quota == 0 else f'{self.room_quota} rooms'
elif quota_type == 'conversation_quota':
return 'Unlimited' if self.conversation_quota == 0 else f'{self.conversation_quota} conversations'
elif quota_type == 'storage_quota_gb':
return 'Unlimited' if self.storage_quota_gb == 0 else f'{self.storage_quota_gb}GB'
elif quota_type == 'manager_quota':
return 'Unlimited' if self.manager_quota == 0 else f'{self.manager_quota} managers'
elif quota_type == 'admin_quota':
return 'Unlimited' if self.admin_quota == 0 else f'{self.admin_quota} admins'
return 'Unknown'
def check_quota(self, quota_type, current_count):
"""Check if a quota would be exceeded"""
if quota_type == 'room_quota':
return self.room_quota == 0 or current_count < self.room_quota
elif quota_type == 'conversation_quota':
return self.conversation_quota == 0 or current_count < self.conversation_quota
elif quota_type == 'storage_quota_gb':
return self.storage_quota_gb == 0 or current_count < self.storage_quota_gb
elif quota_type == 'manager_quota':
return self.manager_quota == 0 or current_count < self.manager_quota
elif quota_type == 'admin_quota':
return self.admin_quota == 0 or current_count < self.admin_quota
return True
def get_quota_remaining(self, quota_type, current_count):
"""Get remaining quota"""
if quota_type == 'room_quota':
return float('inf') if self.room_quota == 0 else max(0, self.room_quota - current_count)
elif quota_type == 'conversation_quota':
return float('inf') if self.conversation_quota == 0 else max(0, self.conversation_quota - current_count)
elif quota_type == 'storage_quota_gb':
return float('inf') if self.storage_quota_gb == 0 else max(0, self.storage_quota_gb - current_count)
elif quota_type == 'manager_quota':
return float('inf') if self.manager_quota == 0 else max(0, self.manager_quota - current_count)
elif quota_type == 'admin_quota':
return float('inf') if self.admin_quota == 0 else max(0, self.admin_quota - current_count)
return 0