2026-03-17 13:17:02 +08:00

96 lines
3.8 KiB
Python

from django.utils.translation import gettext_lazy as _
from django.db import models
from django.utils import timezone
from datetime import timedelta
from userapp.models import ParadiseUser
class SubscriptionPlan(models.Model):
"""订阅计划"""
PLAN_CHOICES = (
('monthly', 'Monthly'),
('quarterly', 'Quarterly'),
('yearly', 'Yearly'),
)
name = models.CharField(_('name'), max_length=100)
price = models.DecimalField(_('price'), max_digits=10, decimal_places=2)
duration = models.CharField(_('duration'), max_length=10, choices=PLAN_CHOICES)
def __str__(self):
return f"{self.name} ({self.get_duration_display()})"
class Meta:
verbose_name = _('SubscriptionPlan')
verbose_name_plural = _('SubscriptionPlan')
class Subscription(models.Model):
"""租户订阅"""
user = models.ForeignKey(ParadiseUser, default=0, on_delete=models.CASCADE, verbose_name=_('user'))
plan = models.ForeignKey(SubscriptionPlan, on_delete=models.CASCADE, verbose_name=_('plan'))
start_date = models.DateTimeField(_('start_date'), default=timezone.now)
end_date = models.DateTimeField(_('end_date'))
last_billed = models.DateTimeField(_('last_billed'), null=True, blank=True) # 上次账单生成日期
def save(self, *args, **kwargs):
if not self.end_date:
if self.plan.duration == 'monthly':
self.end_date = self.start_date + timedelta(days=30)
elif self.plan.duration == 'quarterly':
self.end_date = self.start_date + timedelta(days=90)
elif self.plan.duration == 'yearly':
self.end_date = self.start_date + timedelta(days=365)
super().save(*args, **kwargs)
def __str__(self):
return f"Subscription for {self.tenant} ({self.plan.name})"
class Meta:
verbose_name = _('User Subscription')
verbose_name_plural = _('User Subscription')
class AddOnPackage(models.Model):
"""加油包"""
name = models.CharField(_('name'), max_length=100)
description = models.TextField(_('description'))
price = models.DecimalField(_('price'), max_digits=10, decimal_places=2)
class Meta:
verbose_name = _('AddOnPackage')
verbose_name_plural = _('AddOnPackage')
class SubscriptionAddOn(models.Model):
"""租户订阅加油包"""
subscription = models.ForeignKey(Subscription, on_delete=models.CASCADE, verbose_name=_('subscription'))
add_on = models.ForeignKey(AddOnPackage, on_delete=models.CASCADE, verbose_name=_('add_on'))
quantity = models.PositiveIntegerField(_('quantity'), default=1)
added_on = models.DateTimeField(_('added_on'), auto_now_add=True)
def total_price(self):
return self.add_on.price * self.quantity
def __str__(self):
return f"{self.add_on.name} for {self.subscription.tenant}"
class Meta:
verbose_name = _('TenantSubscriptionAddOn')
verbose_name_plural = _('TenantSubscriptionAddOn')
class TenantBilling(models.Model):
"""租户账单"""
user = models.ForeignKey(ParadiseUser, default=0, on_delete=models.CASCADE, verbose_name=_('user'))
subscription = models.ForeignKey(Subscription, on_delete=models.CASCADE, verbose_name=_('subscription'))
total_price = models.DecimalField(_('total_price'), max_digits=10, decimal_places=2, default=0)
billing_date = models.DateTimeField(_('billing_date'), auto_now_add=True)
def calculate_total_price(self):
# 基础订阅费用
subscription_price = self.subscription.plan.price
# 加油包费用
add_on_price = sum([addon.total_price() for addon in self.subscription.subscriptionaddon_set.all()])
self.total_price = subscription_price + add_on_price
self.save()
class Meta:
verbose_name = _('TenantBilling')
verbose_name_plural = _('TenantBilling')