django admin Groups reorg, Frontend udpates for site settings, #Migration runs
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# Generated by Django 5.2.9 on 2026-01-04 06:11
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('billing', '0024_update_image_models_v2'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='aimodelconfig',
|
||||
name='credits_per_image',
|
||||
field=models.IntegerField(blank=True, help_text='Fixed credits per image generated. For image models only. (e.g., 1, 5, 15)', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aimodelconfig',
|
||||
name='quality_tier',
|
||||
field=models.CharField(blank=True, choices=[('basic', 'Basic'), ('quality', 'Quality'), ('premium', 'Premium')], help_text='Quality tier for frontend UI display (Basic/Quality/Premium). For image models.', max_length=20, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aimodelconfig',
|
||||
name='tokens_per_credit',
|
||||
field=models.IntegerField(blank=True, help_text='Number of tokens that equal 1 credit. For text models only. (e.g., 1000, 10000)', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='credits_per_image',
|
||||
field=models.IntegerField(blank=True, help_text='Fixed credits per image generated. For image models only. (e.g., 1, 5, 15)', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='quality_tier',
|
||||
field=models.CharField(blank=True, choices=[('basic', 'Basic'), ('quality', 'Quality'), ('premium', 'Premium')], help_text='Quality tier for frontend UI display (Basic/Quality/Premium). For image models.', max_length=20, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='tokens_per_credit',
|
||||
field=models.IntegerField(blank=True, help_text='Number of tokens that equal 1 credit. For text models only. (e.g., 1000, 10000)', null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,63 @@
|
||||
# Generated manually for data migration
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def populate_aimodel_credit_fields(apps, schema_editor):
|
||||
"""
|
||||
Populate credit calculation fields in AIModelConfig.
|
||||
- Text models: tokens_per_credit (how many tokens = 1 credit)
|
||||
- Image models: credits_per_image (fixed credits per image) + quality_tier
|
||||
"""
|
||||
AIModelConfig = apps.get_model('billing', 'AIModelConfig')
|
||||
|
||||
# Text models: tokens_per_credit
|
||||
text_model_credits = {
|
||||
'gpt-4o-mini': 10000, # Cheap model: 10k tokens = 1 credit
|
||||
'gpt-4o': 1000, # Premium model: 1k tokens = 1 credit
|
||||
'gpt-5.1': 1000, # Default model: 1k tokens = 1 credit
|
||||
'gpt-5.2': 1000, # Future model
|
||||
'gpt-4.1': 1000, # Legacy
|
||||
'gpt-4-turbo-preview': 500, # Expensive
|
||||
}
|
||||
|
||||
for model_name, tokens_per_credit in text_model_credits.items():
|
||||
AIModelConfig.objects.filter(
|
||||
model_name=model_name,
|
||||
model_type='text'
|
||||
).update(tokens_per_credit=tokens_per_credit)
|
||||
|
||||
# Image models: credits_per_image + quality_tier
|
||||
image_model_credits = {
|
||||
'runware:97@1': {'credits_per_image': 1, 'quality_tier': 'basic'}, # Basic - cheap
|
||||
'dall-e-3': {'credits_per_image': 5, 'quality_tier': 'quality'}, # Quality - mid
|
||||
'google:4@2': {'credits_per_image': 15, 'quality_tier': 'premium'}, # Premium - expensive
|
||||
'dall-e-2': {'credits_per_image': 2, 'quality_tier': 'basic'}, # Legacy
|
||||
}
|
||||
|
||||
for model_name, credits_data in image_model_credits.items():
|
||||
AIModelConfig.objects.filter(
|
||||
model_name=model_name,
|
||||
model_type='image'
|
||||
).update(**credits_data)
|
||||
|
||||
|
||||
def reverse_migration(apps, schema_editor):
|
||||
"""Clear credit fields"""
|
||||
AIModelConfig = apps.get_model('billing', 'AIModelConfig')
|
||||
AIModelConfig.objects.all().update(
|
||||
tokens_per_credit=None,
|
||||
credits_per_image=None,
|
||||
quality_tier=None
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('billing', '0025_add_aimodel_credit_fields'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(populate_aimodel_credit_fields, reverse_migration),
|
||||
]
|
||||
@@ -0,0 +1,356 @@
|
||||
# Generated by Django 5.2.9 on 2026-01-04 10:40
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('billing', '0026_populate_aimodel_credits'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='aimodelconfig',
|
||||
options={'ordering': ['model_type', 'model_name'], 'verbose_name': 'AI Model Configuration', 'verbose_name_plural': 'AI Model Configurations'},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='cost_per_image',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='deprecation_date',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='description',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='input_cost_per_1m',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='max_output_tokens',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='output_cost_per_1m',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='release_date',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='sort_order',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='supports_function_calling',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='supports_json_mode',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='supports_vision',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='updated_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='aimodelconfig',
|
||||
name='valid_sizes',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='creditcostconfig',
|
||||
name='created_at',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='creditcostconfig',
|
||||
name='id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='creditcostconfig',
|
||||
name='min_credits',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='creditcostconfig',
|
||||
name='previous_tokens_per_credit',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='creditcostconfig',
|
||||
name='price_per_credit_usd',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='creditcostconfig',
|
||||
name='tokens_per_credit',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='creditcostconfig',
|
||||
name='updated_at',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='creditcostconfig',
|
||||
name='updated_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='cost_per_image',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='deprecation_date',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='description',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='input_cost_per_1m',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='max_output_tokens',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='output_cost_per_1m',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='release_date',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='sort_order',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='supports_function_calling',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='supports_json_mode',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='supports_vision',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='updated_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='valid_sizes',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='created_at',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='id',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='min_credits',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='previous_tokens_per_credit',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='price_per_credit_usd',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='tokens_per_credit',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='updated_at',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='updated_by',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aimodelconfig',
|
||||
name='capabilities',
|
||||
field=models.JSONField(blank=True, default=dict, help_text='Capabilities: vision, function_calling, json_mode, etc.'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aimodelconfig',
|
||||
name='cost_per_1k_input',
|
||||
field=models.DecimalField(blank=True, decimal_places=6, help_text='Provider cost per 1K input tokens (USD) - text models', max_digits=10, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aimodelconfig',
|
||||
name='cost_per_1k_output',
|
||||
field=models.DecimalField(blank=True, decimal_places=6, help_text='Provider cost per 1K output tokens (USD) - text models', max_digits=10, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='aimodelconfig',
|
||||
name='max_tokens',
|
||||
field=models.IntegerField(blank=True, help_text='Model token limit', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='creditcostconfig',
|
||||
name='base_credits',
|
||||
field=models.IntegerField(default=1, help_text='Fixed credits per operation', validators=[django.core.validators.MinValueValidator(0)]),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='capabilities',
|
||||
field=models.JSONField(blank=True, default=dict, help_text='Capabilities: vision, function_calling, json_mode, etc.'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='cost_per_1k_input',
|
||||
field=models.DecimalField(blank=True, decimal_places=6, help_text='Provider cost per 1K input tokens (USD) - text models', max_digits=10, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='cost_per_1k_output',
|
||||
field=models.DecimalField(blank=True, decimal_places=6, help_text='Provider cost per 1K output tokens (USD) - text models', max_digits=10, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='max_tokens',
|
||||
field=models.IntegerField(blank=True, help_text='Model token limit', null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='base_credits',
|
||||
field=models.IntegerField(default=1, help_text='Fixed credits per operation', validators=[django.core.validators.MinValueValidator(0)]),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='context_window',
|
||||
field=models.IntegerField(blank=True, help_text='Model context size', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='credits_per_image',
|
||||
field=models.IntegerField(blank=True, help_text='Image: credits per image (e.g., 1, 5, 15)', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='display_name',
|
||||
field=models.CharField(help_text='Human-readable name', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='is_active',
|
||||
field=models.BooleanField(db_index=True, default=True, help_text='Enable/disable'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='is_default',
|
||||
field=models.BooleanField(db_index=True, default=False, help_text='One default per type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='model_name',
|
||||
field=models.CharField(db_index=True, help_text="Model identifier (e.g., 'gpt-5.1', 'dall-e-3', 'runware:97@1')", max_length=100, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='model_type',
|
||||
field=models.CharField(choices=[('text', 'Text Generation'), ('image', 'Image Generation')], db_index=True, help_text='text / image', max_length=20),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='provider',
|
||||
field=models.CharField(choices=[('openai', 'OpenAI'), ('anthropic', 'Anthropic'), ('runware', 'Runware'), ('google', 'Google')], db_index=True, help_text='Links to IntegrationProvider', max_length=50),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='quality_tier',
|
||||
field=models.CharField(blank=True, choices=[('basic', 'Basic'), ('quality', 'Quality'), ('premium', 'Premium')], help_text='basic / quality / premium - for image models', max_length=20, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aimodelconfig',
|
||||
name='tokens_per_credit',
|
||||
field=models.IntegerField(blank=True, help_text='Text: tokens per 1 credit (e.g., 1000, 10000)', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='creditcostconfig',
|
||||
name='description',
|
||||
field=models.TextField(blank=True, help_text='Admin notes about this operation'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='creditcostconfig',
|
||||
name='operation_type',
|
||||
field=models.CharField(help_text="Unique operation ID (e.g., 'article_generation', 'image_generation')", max_length=50, primary_key=True, serialize=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='context_window',
|
||||
field=models.IntegerField(blank=True, help_text='Model context size', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='credits_per_image',
|
||||
field=models.IntegerField(blank=True, help_text='Image: credits per image (e.g., 1, 5, 15)', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='display_name',
|
||||
field=models.CharField(help_text='Human-readable name', max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='is_active',
|
||||
field=models.BooleanField(db_index=True, default=True, help_text='Enable/disable'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='is_default',
|
||||
field=models.BooleanField(db_index=True, default=False, help_text='One default per type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='model_name',
|
||||
field=models.CharField(db_index=True, help_text="Model identifier (e.g., 'gpt-5.1', 'dall-e-3', 'runware:97@1')", max_length=100),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='model_type',
|
||||
field=models.CharField(choices=[('text', 'Text Generation'), ('image', 'Image Generation')], db_index=True, help_text='text / image', max_length=20),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='provider',
|
||||
field=models.CharField(choices=[('openai', 'OpenAI'), ('anthropic', 'Anthropic'), ('runware', 'Runware'), ('google', 'Google')], db_index=True, help_text='Links to IntegrationProvider', max_length=50),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='quality_tier',
|
||||
field=models.CharField(blank=True, choices=[('basic', 'Basic'), ('quality', 'Quality'), ('premium', 'Premium')], help_text='basic / quality / premium - for image models', max_length=20, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaimodelconfig',
|
||||
name='tokens_per_credit',
|
||||
field=models.IntegerField(blank=True, help_text='Text: tokens per 1 credit (e.g., 1000, 10000)', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='description',
|
||||
field=models.TextField(blank=True, help_text='Admin notes about this operation'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalcreditcostconfig',
|
||||
name='operation_type',
|
||||
field=models.CharField(db_index=True, help_text="Unique operation ID (e.g., 'article_generation', 'image_generation')", max_length=50),
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user