2025-11-10 15:46:40 +01:00
|
|
|
from tortoise import fields, models
|
|
|
|
|
from decimal import Decimal
|
|
|
|
|
|
|
|
|
|
class SubscriptionPlan(models.Model):
|
|
|
|
|
id = fields.IntField(pk=True)
|
|
|
|
|
name = fields.CharField(max_length=100, unique=True)
|
|
|
|
|
display_name = fields.CharField(max_length=255)
|
|
|
|
|
description = fields.TextField(null=True)
|
|
|
|
|
storage_gb = fields.IntField()
|
|
|
|
|
bandwidth_gb = fields.IntField()
|
|
|
|
|
price_monthly = fields.DecimalField(max_digits=10, decimal_places=2)
|
|
|
|
|
price_yearly = fields.DecimalField(max_digits=10, decimal_places=2, null=True)
|
|
|
|
|
stripe_price_id = fields.CharField(max_length=255, null=True)
|
|
|
|
|
is_active = fields.BooleanField(default=True)
|
|
|
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
|
|
|
updated_at = fields.DatetimeField(auto_now=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
table = "subscription_plans"
|
|
|
|
|
|
|
|
|
|
class UserSubscription(models.Model):
|
|
|
|
|
id = fields.IntField(pk=True)
|
|
|
|
|
user = fields.ForeignKeyField("models.User", related_name="subscription")
|
|
|
|
|
plan = fields.ForeignKeyField("billing.SubscriptionPlan", related_name="subscriptions", null=True)
|
|
|
|
|
billing_type = fields.CharField(max_length=20, default="pay_as_you_go")
|
|
|
|
|
stripe_customer_id = fields.CharField(max_length=255, unique=True, null=True)
|
|
|
|
|
stripe_subscription_id = fields.CharField(max_length=255, unique=True, null=True)
|
|
|
|
|
status = fields.CharField(max_length=50, default="active")
|
|
|
|
|
current_period_start = fields.DatetimeField(null=True)
|
|
|
|
|
current_period_end = fields.DatetimeField(null=True)
|
|
|
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
|
|
|
updated_at = fields.DatetimeField(auto_now=True)
|
|
|
|
|
canceled_at = fields.DatetimeField(null=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
table = "user_subscriptions"
|
|
|
|
|
|
|
|
|
|
class UsageRecord(models.Model):
|
|
|
|
|
id = fields.BigIntField(pk=True)
|
|
|
|
|
user = fields.ForeignKeyField("models.User", related_name="usage_records")
|
2025-11-11 01:05:13 +01:00
|
|
|
record_type = fields.CharField(max_length=50, index=True)
|
2025-11-10 15:46:40 +01:00
|
|
|
amount_bytes = fields.BigIntField()
|
|
|
|
|
resource_type = fields.CharField(max_length=50, null=True)
|
|
|
|
|
resource_id = fields.IntField(null=True)
|
2025-11-11 01:05:13 +01:00
|
|
|
timestamp = fields.DatetimeField(auto_now_add=True, index=True)
|
2025-11-10 15:46:40 +01:00
|
|
|
idempotency_key = fields.CharField(max_length=255, unique=True, null=True)
|
|
|
|
|
metadata = fields.JSONField(null=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
table = "usage_records"
|
2025-11-11 01:05:13 +01:00
|
|
|
indexes = [("user_id", "record_type", "timestamp")]
|
2025-11-10 15:46:40 +01:00
|
|
|
|
|
|
|
|
class UsageAggregate(models.Model):
|
|
|
|
|
id = fields.IntField(pk=True)
|
|
|
|
|
user = fields.ForeignKeyField("models.User", related_name="usage_aggregates")
|
|
|
|
|
date = fields.DateField()
|
|
|
|
|
storage_bytes_avg = fields.BigIntField(default=0)
|
|
|
|
|
storage_bytes_peak = fields.BigIntField(default=0)
|
|
|
|
|
bandwidth_up_bytes = fields.BigIntField(default=0)
|
|
|
|
|
bandwidth_down_bytes = fields.BigIntField(default=0)
|
|
|
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
table = "usage_aggregates"
|
|
|
|
|
unique_together = (("user", "date"),)
|
|
|
|
|
|
|
|
|
|
class Invoice(models.Model):
|
|
|
|
|
id = fields.IntField(pk=True)
|
|
|
|
|
user = fields.ForeignKeyField("models.User", related_name="invoices")
|
|
|
|
|
invoice_number = fields.CharField(max_length=50, unique=True)
|
|
|
|
|
stripe_invoice_id = fields.CharField(max_length=255, unique=True, null=True)
|
2025-11-13 23:05:26 +01:00
|
|
|
period_start = fields.DateField(db_index=True)
|
2025-11-10 15:46:40 +01:00
|
|
|
period_end = fields.DateField()
|
|
|
|
|
subtotal = fields.DecimalField(max_digits=10, decimal_places=4)
|
|
|
|
|
tax = fields.DecimalField(max_digits=10, decimal_places=4, default=0)
|
|
|
|
|
total = fields.DecimalField(max_digits=10, decimal_places=4)
|
|
|
|
|
currency = fields.CharField(max_length=3, default="USD")
|
2025-11-11 01:05:13 +01:00
|
|
|
status = fields.CharField(max_length=50, default="draft", index=True)
|
2025-11-10 15:46:40 +01:00
|
|
|
due_date = fields.DateField(null=True)
|
|
|
|
|
paid_at = fields.DatetimeField(null=True)
|
2025-11-11 01:05:13 +01:00
|
|
|
created_at = fields.DatetimeField(auto_now_add=True, index=True)
|
2025-11-10 15:46:40 +01:00
|
|
|
updated_at = fields.DatetimeField(auto_now=True)
|
|
|
|
|
metadata = fields.JSONField(null=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
table = "invoices"
|
2025-11-11 01:05:13 +01:00
|
|
|
indexes = [("user_id", "status", "created_at")]
|
2025-11-10 15:46:40 +01:00
|
|
|
|
|
|
|
|
class InvoiceLineItem(models.Model):
|
|
|
|
|
id = fields.IntField(pk=True)
|
|
|
|
|
invoice = fields.ForeignKeyField("billing.Invoice", related_name="line_items")
|
|
|
|
|
description = fields.TextField()
|
|
|
|
|
quantity = fields.DecimalField(max_digits=15, decimal_places=6)
|
|
|
|
|
unit_price = fields.DecimalField(max_digits=10, decimal_places=6)
|
|
|
|
|
amount = fields.DecimalField(max_digits=10, decimal_places=4)
|
|
|
|
|
item_type = fields.CharField(max_length=50, null=True)
|
|
|
|
|
metadata = fields.JSONField(null=True)
|
|
|
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
table = "invoice_line_items"
|
|
|
|
|
|
|
|
|
|
class PricingConfig(models.Model):
|
|
|
|
|
id = fields.IntField(pk=True)
|
|
|
|
|
config_key = fields.CharField(max_length=100, unique=True)
|
|
|
|
|
config_value = fields.DecimalField(max_digits=10, decimal_places=6)
|
|
|
|
|
description = fields.TextField(null=True)
|
|
|
|
|
unit = fields.CharField(max_length=50, null=True)
|
|
|
|
|
updated_by = fields.ForeignKeyField("models.User", related_name="pricing_updates", null=True)
|
|
|
|
|
updated_at = fields.DatetimeField(auto_now=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
table = "pricing_config"
|
|
|
|
|
|
|
|
|
|
class PaymentMethod(models.Model):
|
|
|
|
|
id = fields.IntField(pk=True)
|
|
|
|
|
user = fields.ForeignKeyField("models.User", related_name="payment_methods")
|
|
|
|
|
stripe_payment_method_id = fields.CharField(max_length=255)
|
|
|
|
|
type = fields.CharField(max_length=50)
|
|
|
|
|
is_default = fields.BooleanField(default=False)
|
|
|
|
|
last4 = fields.CharField(max_length=4, null=True)
|
|
|
|
|
brand = fields.CharField(max_length=50, null=True)
|
|
|
|
|
exp_month = fields.IntField(null=True)
|
|
|
|
|
exp_year = fields.IntField(null=True)
|
|
|
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
|
|
|
updated_at = fields.DatetimeField(auto_now=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
table = "payment_methods"
|
|
|
|
|
|
|
|
|
|
class BillingEvent(models.Model):
|
|
|
|
|
id = fields.BigIntField(pk=True)
|
|
|
|
|
user = fields.ForeignKeyField("models.User", related_name="billing_events", null=True)
|
|
|
|
|
event_type = fields.CharField(max_length=100)
|
|
|
|
|
stripe_event_id = fields.CharField(max_length=255, unique=True, null=True)
|
|
|
|
|
data = fields.JSONField(null=True)
|
|
|
|
|
processed = fields.BooleanField(default=False)
|
|
|
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
table = "billing_events"
|