payemnt billing and credits refactoring

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-20 07:39:51 +00:00
parent a97c72640a
commit bc50b022f1
34 changed files with 3028 additions and 307 deletions

View File

@@ -0,0 +1,34 @@
# Generated by Django 5.2.10 on 2026-01-20 06:11
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('igny8_core_auth', '0034_add_user_phone'),
]
operations = [
migrations.AddField(
model_name='account',
name='bonus_credits',
field=models.IntegerField(default=0, help_text='Purchased/bonus credits (never expire, never reset)', validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AddField(
model_name='historicalaccount',
name='bonus_credits',
field=models.IntegerField(default=0, help_text='Purchased/bonus credits (never expire, never reset)', validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='account',
name='credits',
field=models.IntegerField(default=0, help_text='Plan credits (reset on renewal)', validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='historicalaccount',
name='credits',
field=models.IntegerField(default=0, help_text='Plan credits (reset on renewal)', validators=[django.core.validators.MinValueValidator(0)]),
),
]

View File

@@ -83,7 +83,8 @@ class Account(SoftDeletableModel):
)
stripe_customer_id = models.CharField(max_length=255, blank=True, null=True)
plan = models.ForeignKey('igny8_core_auth.Plan', on_delete=models.PROTECT, related_name='accounts')
credits = models.IntegerField(default=0, validators=[MinValueValidator(0)])
credits = models.IntegerField(default=0, validators=[MinValueValidator(0)], help_text="Plan credits (reset on renewal)")
bonus_credits = models.IntegerField(default=0, validators=[MinValueValidator(0)], help_text="Purchased/bonus credits (never expire, never reset)")
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='trial')
payment_method = models.CharField(
max_length=30,
@@ -143,6 +144,11 @@ class Account(SoftDeletableModel):
def __str__(self):
return self.name
@property
def total_credits(self):
"""Total available credits (plan + bonus). Use this for balance checks."""
return self.credits + self.bonus_credits
@property
def default_payment_method(self):
"""Get default payment method from AccountPaymentMethod table"""

View File

@@ -41,6 +41,11 @@ class AccountSerializer(serializers.ModelSerializer):
plan = PlanSerializer(read_only=True)
plan_id = serializers.PrimaryKeyRelatedField(queryset=Plan.objects.filter(is_active=True), write_only=True, source='plan', required=False)
subscription = SubscriptionSerializer(read_only=True, allow_null=True)
total_credits = serializers.SerializerMethodField()
def get_total_credits(self, obj):
"""Return total available credits (plan + bonus)."""
return obj.credits + obj.bonus_credits
def validate_plan_id(self, value):
"""Validate plan_id is provided during creation."""
@@ -52,7 +57,7 @@ class AccountSerializer(serializers.ModelSerializer):
model = Account
fields = [
'id', 'name', 'slug', 'owner', 'plan', 'plan_id',
'credits', 'status', 'payment_method',
'credits', 'bonus_credits', 'total_credits', 'status', 'payment_method',
'subscription', 'billing_country',
'account_timezone', 'timezone_mode', 'timezone_offset',
'created_at'