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)