85 lines
3.6 KiB
Python
85 lines
3.6 KiB
Python
from django.db import models
|
|
|
|
from apps.common.models import TimeStampedModel
|
|
|
|
|
|
class CreditAccount(TimeStampedModel):
|
|
team = models.OneToOneField("accounts.Team", on_delete=models.CASCADE, related_name="credit_account")
|
|
balance = models.DecimalField(max_digits=14, decimal_places=4, default=0)
|
|
reserved_balance = models.DecimalField(max_digits=14, decimal_places=4, default=0)
|
|
currency = models.CharField(max_length=16, default="CNY")
|
|
|
|
def __str__(self) -> str:
|
|
return f"{self.team} / {self.balance}"
|
|
|
|
|
|
class CreditLedger(TimeStampedModel):
|
|
class Type(models.TextChoices):
|
|
RECHARGE = "recharge", "Recharge"
|
|
RESERVE = "reserve", "Reserve"
|
|
RELEASE = "release", "Release"
|
|
CHARGE = "charge", "Charge"
|
|
ADJUSTMENT = "adjustment", "Adjustment"
|
|
REFUND = "refund", "Refund"
|
|
|
|
team = models.ForeignKey("accounts.Team", on_delete=models.CASCADE, related_name="credit_ledgers")
|
|
user = models.ForeignKey("accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="credit_ledgers")
|
|
project = models.ForeignKey(
|
|
"projects.Project",
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="credit_ledgers",
|
|
)
|
|
task = models.ForeignKey("ai.AITask", on_delete=models.SET_NULL, null=True, blank=True, related_name="credit_ledgers")
|
|
ledger_type = models.CharField(max_length=32, choices=Type.choices)
|
|
amount = models.DecimalField(max_digits=14, decimal_places=4)
|
|
balance_after = models.DecimalField(max_digits=14, decimal_places=4)
|
|
reason = models.CharField(max_length=255, blank=True)
|
|
metadata = models.JSONField(default=dict, blank=True)
|
|
|
|
class Meta:
|
|
indexes = [
|
|
models.Index(fields=["team", "ledger_type"]),
|
|
models.Index(fields=["project", "task"]),
|
|
]
|
|
|
|
|
|
class CreditReservation(TimeStampedModel):
|
|
class Status(models.TextChoices):
|
|
ACTIVE = "active", "Active"
|
|
RELEASED = "released", "Released"
|
|
CHARGED = "charged", "Charged"
|
|
CANCELLED = "cancelled", "Cancelled"
|
|
|
|
team = models.ForeignKey("accounts.Team", on_delete=models.CASCADE, related_name="credit_reservations")
|
|
user = models.ForeignKey("accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="credit_reservations")
|
|
project = models.ForeignKey(
|
|
"projects.Project",
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="credit_reservations",
|
|
)
|
|
task = models.OneToOneField("ai.AITask", on_delete=models.CASCADE, related_name="credit_reservation")
|
|
amount = models.DecimalField(max_digits=14, decimal_places=4)
|
|
status = models.CharField(max_length=32, choices=Status.choices, default=Status.ACTIVE)
|
|
expires_at = models.DateTimeField(null=True, blank=True)
|
|
|
|
|
|
class QuotaPolicy(TimeStampedModel):
|
|
team = models.ForeignKey("accounts.Team", on_delete=models.CASCADE, related_name="quota_policies")
|
|
user = models.ForeignKey("accounts.User", on_delete=models.CASCADE, null=True, blank=True, related_name="quota_policies")
|
|
project = models.ForeignKey(
|
|
"projects.Project",
|
|
on_delete=models.CASCADE,
|
|
null=True,
|
|
blank=True,
|
|
related_name="quota_policies",
|
|
)
|
|
monthly_limit = models.DecimalField(max_digits=14, decimal_places=4, null=True, blank=True)
|
|
project_limit = models.DecimalField(max_digits=14, decimal_places=4, null=True, blank=True)
|
|
per_task_limit = models.DecimalField(max_digits=14, decimal_places=4, null=True, blank=True)
|
|
is_active = models.BooleanField(default=True)
|
|
|