lot of messs

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-23 14:35:41 +00:00
parent edb64824be
commit 38bc015d96
17 changed files with 2448 additions and 303 deletions

View File

@@ -0,0 +1,106 @@
# Generated by Django 5.2.9 on 2025-12-23 08:40
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('system', '0003_globalmodulesettings'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='GlobalAIPrompt',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('prompt_type', models.CharField(choices=[('clustering', 'Clustering'), ('ideas', 'Ideas Generation'), ('content_generation', 'Content Generation'), ('image_prompt_extraction', 'Image Prompt Extraction'), ('image_prompt_template', 'Image Prompt Template'), ('negative_prompt', 'Negative Prompt'), ('site_structure_generation', 'Site Structure Generation'), ('product_generation', 'Product Content Generation'), ('service_generation', 'Service Page Generation'), ('taxonomy_generation', 'Taxonomy Generation')], help_text='Type of AI operation this prompt is for', max_length=50, unique=True)),
('prompt_value', models.TextField(help_text='Default prompt template')),
('description', models.TextField(blank=True, help_text='Description of what this prompt does')),
('variables', models.JSONField(blank=True, default=list, help_text='Optional: List of variables used in the prompt (e.g., {keyword}, {industry})')),
('is_active', models.BooleanField(db_index=True, default=True)),
('version', models.IntegerField(default=1, help_text='Prompt version for tracking changes')),
('last_updated', models.DateTimeField(auto_now=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
],
options={
'verbose_name': 'Global AI Prompt',
'verbose_name_plural': 'Global AI Prompts',
'db_table': 'igny8_global_ai_prompts',
'ordering': ['prompt_type'],
},
),
migrations.CreateModel(
name='GlobalAuthorProfile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text="Profile name (e.g., 'SaaS B2B Professional')", max_length=255, unique=True)),
('description', models.TextField(help_text='Description of the writing style')),
('tone', models.CharField(help_text="Writing tone (e.g., 'Professional', 'Casual', 'Technical')", max_length=100)),
('language', models.CharField(default='en', help_text='Language code', max_length=50)),
('structure_template', models.JSONField(default=dict, help_text='Structure template defining content sections')),
('category', models.CharField(choices=[('saas', 'SaaS/B2B'), ('ecommerce', 'E-commerce'), ('blog', 'Blog/Publishing'), ('technical', 'Technical'), ('creative', 'Creative'), ('news', 'News/Media'), ('academic', 'Academic')], help_text='Profile category', max_length=50)),
('is_active', models.BooleanField(db_index=True, default=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
options={
'verbose_name': 'Global Author Profile',
'verbose_name_plural': 'Global Author Profiles',
'db_table': 'igny8_global_author_profiles',
'ordering': ['category', 'name'],
},
),
migrations.CreateModel(
name='GlobalStrategy',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Strategy name', max_length=255, unique=True)),
('description', models.TextField(help_text='Description of the content strategy')),
('prompt_types', models.JSONField(default=list, help_text='List of prompt types to use')),
('section_logic', models.JSONField(default=dict, help_text='Section logic configuration')),
('category', models.CharField(choices=[('blog', 'Blog Content'), ('ecommerce', 'E-commerce'), ('saas', 'SaaS/B2B'), ('news', 'News/Media'), ('technical', 'Technical Documentation'), ('marketing', 'Marketing Content')], help_text='Strategy category', max_length=50)),
('is_active', models.BooleanField(db_index=True, default=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
options={
'verbose_name': 'Global Strategy',
'verbose_name_plural': 'Global Strategies',
'db_table': 'igny8_global_strategies',
'ordering': ['category', 'name'],
},
),
migrations.CreateModel(
name='GlobalIntegrationSettings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('openai_api_key', models.CharField(blank=True, help_text='Platform OpenAI API key - used by ALL accounts', max_length=500)),
('openai_model', models.CharField(choices=[('gpt-4.1', 'GPT-4.1 - $2.00 / $8.00 per 1M tokens'), ('gpt-4o-mini', 'GPT-4o mini - $0.15 / $0.60 per 1M tokens'), ('gpt-4o', 'GPT-4o - $2.50 / $10.00 per 1M tokens'), ('gpt-4-turbo-preview', 'GPT-4 Turbo Preview - $10.00 / $30.00 per 1M tokens'), ('gpt-5.1', 'GPT-5.1 - $1.25 / $10.00 per 1M tokens (16K)'), ('gpt-5.2', 'GPT-5.2 - $1.75 / $14.00 per 1M tokens (16K)')], default='gpt-4o-mini', help_text='Default text generation model (accounts can override if plan allows)', max_length=100)),
('openai_temperature', models.FloatField(default=0.7, help_text='Default temperature 0.0-2.0 (accounts can override if plan allows)')),
('openai_max_tokens', models.IntegerField(default=8192, help_text='Default max tokens for responses (accounts can override if plan allows)')),
('dalle_api_key', models.CharField(blank=True, help_text='Platform DALL-E API key - used by ALL accounts (can be same as OpenAI)', max_length=500)),
('dalle_model', models.CharField(choices=[('dall-e-3', 'DALL·E 3 - $0.040 per image'), ('dall-e-2', 'DALL·E 2 - $0.020 per image')], default='dall-e-3', help_text='Default DALL-E model (accounts can override if plan allows)', max_length=100)),
('dalle_size', models.CharField(choices=[('1024x1024', '1024x1024 (Square)'), ('1792x1024', '1792x1024 (Landscape)'), ('1024x1792', '1024x1792 (Portrait)'), ('512x512', '512x512 (Small Square)')], default='1024x1024', help_text='Default image size (accounts can override if plan allows)', max_length=20)),
('runware_api_key', models.CharField(blank=True, help_text='Platform Runware API key - used by ALL accounts', max_length=500)),
('runware_model', models.CharField(choices=[('runware:97@1', 'Runware 97@1 - Versatile Model'), ('runware:100@1', 'Runware 100@1 - High Quality'), ('runware:101@1', 'Runware 101@1 - Fast Generation')], default='runware:97@1', help_text='Default Runware model (accounts can override if plan allows)', max_length=100)),
('default_image_service', models.CharField(choices=[('openai', 'OpenAI DALL-E'), ('runware', 'Runware')], default='openai', help_text='Default image generation service for all accounts (openai=DALL-E, runware=Runware)', max_length=20)),
('image_quality', models.CharField(choices=[('standard', 'Standard'), ('hd', 'HD')], default='standard', help_text='Default image quality for all providers (accounts can override if plan allows)', max_length=20)),
('image_style', models.CharField(choices=[('vivid', 'Vivid'), ('natural', 'Natural'), ('realistic', 'Realistic'), ('artistic', 'Artistic'), ('cartoon', 'Cartoon')], default='realistic', help_text='Default image style for all providers (accounts can override if plan allows)', max_length=20)),
('max_in_article_images', models.IntegerField(default=2, help_text='Default maximum images to generate per article (1-5, accounts can override if plan allows)')),
('desktop_image_size', models.CharField(default='1024x1024', help_text='Default desktop image size (accounts can override if plan allows)', max_length=20)),
('mobile_image_size', models.CharField(default='512x512', help_text='Default mobile image size (accounts can override if plan allows)', max_length=20)),
('is_active', models.BooleanField(default=True)),
('last_updated', models.DateTimeField(auto_now=True)),
('updated_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='global_settings_updates', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Global Integration Settings',
'verbose_name_plural': 'Global Integration Settings',
'db_table': 'igny8_global_integration_settings',
},
),
]

View File

@@ -0,0 +1,183 @@
# Generated by Django 5.2.9 on 2025-12-23 (custom data migration)
import django.db.models.deletion
from django.db import migrations, models
def migrate_model_strings_to_fks(apps, schema_editor):
"""Convert CharField model identifiers to ForeignKey references"""
GlobalIntegrationSettings = apps.get_model('system', 'GlobalIntegrationSettings')
AIModelConfig = apps.get_model('billing', 'AIModelConfig')
# Get the singleton GlobalIntegrationSettings instance
try:
settings = GlobalIntegrationSettings.objects.first()
if not settings:
print(" No GlobalIntegrationSettings found, skipping data migration")
return
# Map openai_model string to AIModelConfig FK
if settings.openai_model_old:
model_name = settings.openai_model_old
# Try to find matching model
openai_model = AIModelConfig.objects.filter(
model_name=model_name,
provider='openai',
model_type='text'
).first()
if openai_model:
settings.openai_model_new = openai_model
print(f" ✓ Mapped openai_model: {model_name}{openai_model.id}")
else:
# Try gpt-4o-mini as fallback
openai_model = AIModelConfig.objects.filter(
model_name='gpt-4o-mini',
provider='openai',
model_type='text'
).first()
if openai_model:
settings.openai_model_new = openai_model
print(f" ⚠ Could not find {model_name}, using fallback: gpt-4o-mini")
# Map dalle_model string to AIModelConfig FK
if settings.dalle_model_old:
model_name = settings.dalle_model_old
dalle_model = AIModelConfig.objects.filter(
model_name=model_name,
provider='openai',
model_type='image'
).first()
if dalle_model:
settings.dalle_model_new = dalle_model
print(f" ✓ Mapped dalle_model: {model_name}{dalle_model.id}")
else:
# Try dall-e-3 as fallback
dalle_model = AIModelConfig.objects.filter(
model_name='dall-e-3',
provider='openai',
model_type='image'
).first()
if dalle_model:
settings.dalle_model_new = dalle_model
print(f" ⚠ Could not find {model_name}, using fallback: dall-e-3")
# Map runware_model string to AIModelConfig FK
if settings.runware_model_old:
model_name = settings.runware_model_old
# Runware models might have different naming
runware_model = AIModelConfig.objects.filter(
provider='runware',
model_type='image'
).first() # Just get first active Runware model
if runware_model:
settings.runware_model_new = runware_model
print(f" ✓ Mapped runware_model: {model_name}{runware_model.id}")
settings.save()
print(" ✅ Data migration complete")
except Exception as e:
print(f" ⚠ Error during data migration: {e}")
# Don't fail the migration, let admin fix it manually
class Migration(migrations.Migration):
dependencies = [
('billing', '0019_add_ai_model_config'),
('system', '0004_add_global_integration_models'),
]
operations = [
# Step 1: Add new FK fields with temporary names
migrations.AddField(
model_name='globalintegrationsettings',
name='openai_model_new',
field=models.ForeignKey(
blank=True,
null=True,
help_text='Default text generation model (accounts can override if plan allows)',
limit_choices_to={'is_active': True, 'model_type': 'text', 'provider': 'openai'},
on_delete=django.db.models.deletion.PROTECT,
related_name='global_openai_text_model_new',
to='billing.aimodelconfig'
),
),
migrations.AddField(
model_name='globalintegrationsettings',
name='dalle_model_new',
field=models.ForeignKey(
blank=True,
null=True,
help_text='Default DALL-E model (accounts can override if plan allows)',
limit_choices_to={'is_active': True, 'model_type': 'image', 'provider': 'openai'},
on_delete=django.db.models.deletion.PROTECT,
related_name='global_dalle_model_new',
to='billing.aimodelconfig'
),
),
migrations.AddField(
model_name='globalintegrationsettings',
name='runware_model_new',
field=models.ForeignKey(
blank=True,
null=True,
help_text='Default Runware model (accounts can override if plan allows)',
limit_choices_to={'is_active': True, 'model_type': 'image', 'provider': 'runware'},
on_delete=django.db.models.deletion.PROTECT,
related_name='global_runware_model_new',
to='billing.aimodelconfig'
),
),
# Step 2: Rename old CharField fields
migrations.RenameField(
model_name='globalintegrationsettings',
old_name='openai_model',
new_name='openai_model_old',
),
migrations.RenameField(
model_name='globalintegrationsettings',
old_name='dalle_model',
new_name='dalle_model_old',
),
migrations.RenameField(
model_name='globalintegrationsettings',
old_name='runware_model',
new_name='runware_model_old',
),
# Step 3: Run data migration
migrations.RunPython(migrate_model_strings_to_fks, migrations.RunPython.noop),
# Step 4: Remove old CharField fields
migrations.RemoveField(
model_name='globalintegrationsettings',
name='openai_model_old',
),
migrations.RemoveField(
model_name='globalintegrationsettings',
name='dalle_model_old',
),
migrations.RemoveField(
model_name='globalintegrationsettings',
name='runware_model_old',
),
# Step 5: Rename new FK fields to final names
migrations.RenameField(
model_name='globalintegrationsettings',
old_name='openai_model_new',
new_name='openai_model',
),
migrations.RenameField(
model_name='globalintegrationsettings',
old_name='dalle_model_new',
new_name='dalle_model',
),
migrations.RenameField(
model_name='globalintegrationsettings',
old_name='runware_model_new',
new_name='runware_model',
),
]

View File

@@ -0,0 +1,50 @@
# Generated by Django 5.2.9 on 2025-12-23 14:24
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('billing', '0020_add_optimizer_publisher_timestamps'),
('system', '0005_link_global_settings_to_aimodelconfig'),
]
operations = [
migrations.AddField(
model_name='globalmodulesettings',
name='created_at',
field=models.DateTimeField(auto_now_add=True, null=True),
),
migrations.AddField(
model_name='globalmodulesettings',
name='optimizer_enabled',
field=models.BooleanField(default=True, help_text='Enable Optimizer module platform-wide'),
),
migrations.AddField(
model_name='globalmodulesettings',
name='publisher_enabled',
field=models.BooleanField(default=True, help_text='Enable Publisher module platform-wide'),
),
migrations.AddField(
model_name='globalmodulesettings',
name='updated_at',
field=models.DateTimeField(auto_now=True, null=True),
),
migrations.AlterField(
model_name='globalintegrationsettings',
name='dalle_model',
field=models.ForeignKey(blank=True, help_text='Default DALL-E model (accounts can override if plan allows)', limit_choices_to={'is_active': True, 'model_type': 'image', 'provider': 'openai'}, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='global_dalle_model', to='billing.aimodelconfig'),
),
migrations.AlterField(
model_name='globalintegrationsettings',
name='openai_model',
field=models.ForeignKey(blank=True, help_text='Default text generation model (accounts can override if plan allows)', limit_choices_to={'is_active': True, 'model_type': 'text', 'provider': 'openai'}, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='global_openai_text_model', to='billing.aimodelconfig'),
),
migrations.AlterField(
model_name='globalintegrationsettings',
name='runware_model',
field=models.ForeignKey(blank=True, help_text='Default Runware model (accounts can override if plan allows)', limit_choices_to={'is_active': True, 'model_type': 'image', 'provider': 'runware'}, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='global_runware_model', to='billing.aimodelconfig'),
),
]