158 lines
4.9 KiB
Python
158 lines
4.9 KiB
Python
from django.conf import settings
|
|
from django.db import models
|
|
|
|
from infrasynth.shared.enums import BillingInterval, InvoiceStatus, SubscriptionStatus
|
|
|
|
|
|
class PaymentGateway(models.Model):
|
|
slug = models.SlugField(max_length=100, primary_key=True)
|
|
display_name = models.CharField(max_length=200)
|
|
gateway_class = models.CharField(max_length=500)
|
|
config = models.JSONField(default=dict)
|
|
is_active = models.BooleanField(default=True)
|
|
supported_currencies = models.JSONField(default=list)
|
|
webhook_secret = models.CharField(max_length=500, blank=True)
|
|
|
|
class Meta:
|
|
db_table = "billing_gateway"
|
|
|
|
def __str__(self):
|
|
return self.display_name
|
|
|
|
|
|
class BillingPlan(models.Model):
|
|
slug = models.SlugField(max_length=100, unique=True)
|
|
name = models.CharField(max_length=200)
|
|
description = models.TextField(blank=True)
|
|
price_amount = models.DecimalField(max_digits=12, decimal_places=2)
|
|
price_currency = models.CharField(max_length=3, default="USD")
|
|
interval = models.CharField(max_length=20, choices=BillingInterval.choices)
|
|
trial_days = models.IntegerField(default=0)
|
|
features = models.JSONField(default=list)
|
|
is_active = models.BooleanField(default=True)
|
|
gateway = models.ForeignKey(
|
|
PaymentGateway,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="+",
|
|
)
|
|
external_id = models.CharField(max_length=255, blank=True)
|
|
|
|
class Meta:
|
|
db_table = "billing_plan"
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
class Subscription(models.Model):
|
|
user = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
on_delete=models.CASCADE,
|
|
related_name="+",
|
|
)
|
|
plan = models.ForeignKey(
|
|
BillingPlan,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="+",
|
|
)
|
|
gateway = models.ForeignKey(
|
|
PaymentGateway,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="+",
|
|
)
|
|
external_id = models.CharField(max_length=255, blank=True)
|
|
status = models.CharField(max_length=20, choices=SubscriptionStatus.choices)
|
|
current_period_start = models.DateTimeField(null=True, blank=True)
|
|
current_period_end = models.DateTimeField(null=True, blank=True)
|
|
cancel_at_period_end = models.BooleanField(default=False)
|
|
cancelled_at = models.DateTimeField(null=True, blank=True)
|
|
trial_end = models.DateTimeField(null=True, blank=True)
|
|
metadata = models.JSONField(default=dict)
|
|
|
|
class Meta:
|
|
db_table = "billing_subscription"
|
|
|
|
def __str__(self):
|
|
return f"{self.user}#{self.plan}"
|
|
|
|
|
|
class Invoice(models.Model):
|
|
subscription = models.ForeignKey(
|
|
Subscription,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="+",
|
|
)
|
|
user = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
on_delete=models.CASCADE,
|
|
related_name="+",
|
|
)
|
|
gateway = models.ForeignKey(
|
|
PaymentGateway,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="+",
|
|
)
|
|
external_id = models.CharField(max_length=255, blank=True)
|
|
invoice_number = models.CharField(max_length=100, unique=True)
|
|
amount = models.DecimalField(max_digits=12, decimal_places=2)
|
|
currency = models.CharField(max_length=3, default="USD")
|
|
tax_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0)
|
|
tax_name = models.CharField(max_length=100, blank=True)
|
|
status = models.CharField(max_length=20, choices=InvoiceStatus.choices)
|
|
due_date = models.DateTimeField(null=True, blank=True)
|
|
paid_at = models.DateTimeField(null=True, blank=True)
|
|
line_items = models.JSONField(default=list)
|
|
pdf_file = models.ForeignKey(
|
|
"infrasynth_files.StoredFile",
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="+",
|
|
)
|
|
metadata = models.JSONField(default=dict)
|
|
|
|
class Meta:
|
|
db_table = "billing_invoice"
|
|
|
|
def __str__(self):
|
|
return self.invoice_number
|
|
|
|
|
|
class PaymentTransaction(models.Model):
|
|
invoice = models.ForeignKey(
|
|
Invoice,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="+",
|
|
)
|
|
gateway = models.ForeignKey(
|
|
PaymentGateway,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="+",
|
|
)
|
|
external_id = models.CharField(max_length=255, blank=True)
|
|
amount = models.DecimalField(max_digits=12, decimal_places=2)
|
|
currency = models.CharField(max_length=3, default="USD")
|
|
status = models.CharField(max_length=50, blank=True)
|
|
payment_method = models.CharField(max_length=100, blank=True)
|
|
metadata = models.JSONField(default=dict)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
db_table = "billing_transaction"
|
|
|
|
def __str__(self):
|
|
return f"txn_{self.pk}"
|