Files
igny8/docs/90-REFERENCE/MODELS.md
IGNY8 VPS (Salman) 4bffede052 docs & ux improvmeents
2025-12-25 20:31:58 +00:00

13 KiB

Database Models Reference

Last Verified: December 25, 2025


Auth Models (igny8_core/auth/models/)

User

class User(AbstractBaseUser, PermissionsMixin):
    id = UUIDField(primary_key=True)
    email = EmailField(unique=True)
    first_name = CharField(max_length=150)
    last_name = CharField(max_length=150)
    
    account = ForeignKey(Account, related_name='users')
    role = ForeignKey(Group, null=True)
    
    is_active = BooleanField(default=True)
    is_staff = BooleanField(default=False)
    created_at = DateTimeField(auto_now_add=True)
    updated_at = DateTimeField(auto_now=True)

Relations: Account (many-to-one)


Account

class Account(models.Model):
    id = UUIDField(primary_key=True)
    name = CharField(max_length=255)
    
    plan = ForeignKey(Plan, null=True)
    owner = ForeignKey(User, related_name='owned_accounts')
    
    is_active = BooleanField(default=True)
    created_at = DateTimeField(auto_now_add=True)

Relations: Plan (many-to-one), Users (one-to-many), Sites (one-to-many)


Site

class Site(models.Model):
    id = UUIDField(primary_key=True)
    name = CharField(max_length=255)
    domain = CharField(max_length=255, blank=True)
    
    account = ForeignKey(Account, related_name='sites')
    industry = ForeignKey(Industry, null=True)
    
    is_active = BooleanField(default=True)
    created_at = DateTimeField(auto_now_add=True)

Relations: Account (many-to-one), Sectors (one-to-many), Industries (many-to-one)


Sector

class Sector(models.Model):
    id = UUIDField(primary_key=True)
    name = CharField(max_length=255)
    description = TextField(blank=True)
    
    site = ForeignKey(Site, related_name='sectors')
    
    is_active = BooleanField(default=True)
    created_at = DateTimeField(auto_now_add=True)

Relations: Site (many-to-one)


Industry

class Industry(models.Model):
    id = UUIDField(primary_key=True)
    name = CharField(max_length=255)
    description = TextField(blank=True)

Used for: Default seed keywords, industry-specific prompts


Planner Models (igny8_core/modules/planner/models.py)

Keyword

class Keyword(models.Model):
    id = UUIDField(primary_key=True)
    keyword = CharField(max_length=255)
    
    site = ForeignKey(Site, related_name='keywords')
    sector = ForeignKey(Sector, null=True, related_name='keywords')
    cluster = ForeignKey(Cluster, null=True, related_name='keywords')
    
    search_volume = IntegerField(null=True)
    difficulty = IntegerField(null=True)
    cpc = DecimalField(null=True)
    
    status = CharField(choices=KEYWORD_STATUS)  # pending, clustered, used, archived
    
    created_by = ForeignKey(User)
    created_at = DateTimeField(auto_now_add=True)

Status Values:

  • pending - New, awaiting clustering
  • clustered - Assigned to a cluster
  • used - Used in content idea
  • archived - No longer active

Cluster

class Cluster(models.Model):
    id = UUIDField(primary_key=True)
    name = CharField(max_length=255)
    description = TextField(blank=True)
    
    site = ForeignKey(Site, related_name='clusters')
    sector = ForeignKey(Sector, null=True, related_name='clusters')
    
    created_by = ForeignKey(User)
    created_at = DateTimeField(auto_now_add=True)

Relations: Site, Sector, Keywords (one-to-many), ContentIdeas (one-to-many)


ContentIdea

class ContentIdea(models.Model):
    id = UUIDField(primary_key=True)
    title = CharField(max_length=255)
    description = TextField(blank=True)
    
    site = ForeignKey(Site, related_name='ideas')
    sector = ForeignKey(Sector, null=True)
    cluster = ForeignKey(Cluster, related_name='ideas')
    
    primary_keyword = ForeignKey(Keyword, related_name='primary_ideas')
    secondary_keywords = ManyToManyField(Keyword, related_name='secondary_ideas')
    
    status = CharField(choices=IDEA_STATUS)  # pending, approved, used, archived
    
    created_at = DateTimeField(auto_now_add=True)

Writer Models (igny8_core/modules/writer/models.py)

Task

class Task(models.Model):
    id = UUIDField(primary_key=True)
    title = CharField(max_length=255)
    brief = TextField(blank=True)
    
    site = ForeignKey(Site, related_name='tasks')
    sector = ForeignKey(Sector, null=True)
    idea = ForeignKey(ContentIdea, null=True, related_name='tasks')
    
    primary_keyword = CharField(max_length=255)
    secondary_keywords = JSONField(default=list)
    
    status = CharField(choices=TASK_STATUS)  # pending, in_progress, completed, cancelled
    priority = CharField(choices=PRIORITY)   # low, medium, high
    
    assigned_to = ForeignKey(User, null=True)
    due_date = DateField(null=True)
    
    created_by = ForeignKey(User)
    created_at = DateTimeField(auto_now_add=True)

Content

class Content(models.Model):
    id = UUIDField(primary_key=True)
    title = CharField(max_length=255)
    body = TextField()  # HTML content
    excerpt = TextField(blank=True)
    
    site = ForeignKey(Site, related_name='content')
    sector = ForeignKey(Sector, null=True)
    task = ForeignKey(Task, related_name='content')
    
    meta_title = CharField(max_length=255, blank=True)
    meta_description = TextField(blank=True)
    
    status = CharField(choices=CONTENT_STATUS)  # draft, review, approved, published
    
    word_count = IntegerField(default=0)
    
    created_by = ForeignKey(User)
    created_at = DateTimeField(auto_now_add=True)
    updated_at = DateTimeField(auto_now=True)

Status Values:

  • draft - Initial state after generation
  • review - Pending human review
  • approved - Ready for publishing
  • published - Published to WordPress

ContentImage

class ContentImage(models.Model):
    id = UUIDField(primary_key=True)
    content = ForeignKey(Content, related_name='images')
    
    url = URLField()
    thumbnail_url = URLField(blank=True)
    alt_text = CharField(max_length=255)
    caption = TextField(blank=True)
    
    is_featured = BooleanField(default=False)
    position = IntegerField(default=0)
    
    # AI generation metadata
    prompt = TextField(blank=True)
    provider = CharField(max_length=50)  # dalle, runware
    
    created_at = DateTimeField(auto_now_add=True)

Integration Models (igny8_core/modules/integration/models.py)

SiteIntegration

class SiteIntegration(models.Model):
    id = UUIDField(primary_key=True)
    name = CharField(max_length=255)
    
    site = ForeignKey(Site, related_name='integrations')
    integration_type = CharField(max_length=50)  # wordpress
    
    # Credentials (encrypted)
    url = URLField()
    username = CharField(max_length=255)
    api_key = CharField(max_length=255)  # Application password
    
    # Cached structure
    categories = JSONField(default=list)
    tags = JSONField(default=list)
    authors = JSONField(default=list)
    post_types = JSONField(default=list)
    
    # Status
    is_active = BooleanField(default=True)
    last_sync_at = DateTimeField(null=True)
    structure_updated_at = DateTimeField(null=True)
    
    created_at = DateTimeField(auto_now_add=True)

Billing Models (igny8_core/modules/billing/models.py)

Plan

class Plan(models.Model):
    id = UUIDField(primary_key=True)
    name = CharField(max_length=100)
    slug = SlugField(unique=True)
    
    idea_credits = IntegerField(default=0)
    content_credits = IntegerField(default=0)
    image_credits = IntegerField(default=0)
    optimization_credits = IntegerField(default=0)
    
    max_sites = IntegerField(default=1)
    max_users = IntegerField(default=1)
    
    price_monthly = DecimalField(max_digits=10, decimal_places=2)
    price_yearly = DecimalField(max_digits=10, decimal_places=2)
    
    is_active = BooleanField(default=True)
    is_internal = BooleanField(default=False)

CreditBalance

class CreditBalance(models.Model):
    account = ForeignKey(Account, related_name='credit_balances')
    site = ForeignKey(Site, null=True, related_name='credit_balances')
    
    idea_credits = IntegerField(default=0)
    content_credits = IntegerField(default=0)
    image_credits = IntegerField(default=0)
    optimization_credits = IntegerField(default=0)
    
    period_start = DateField()
    period_end = DateField()
    
    created_at = DateTimeField(auto_now_add=True)
    updated_at = DateTimeField(auto_now=True)

CreditUsage

class CreditUsage(models.Model):
    account = ForeignKey(Account, related_name='credit_usage')
    site = ForeignKey(Site, null=True)
    user = ForeignKey(User)
    
    credit_type = CharField(max_length=50)  # idea, content, image, optimization
    amount = IntegerField()
    operation = CharField(max_length=100)  # generate_content, etc.
    
    related_content_type = ForeignKey(ContentType, null=True)
    related_object_id = UUIDField(null=True)
    
    created_at = DateTimeField(auto_now_add=True)

System Models (igny8_core/modules/system/)

ModuleEnableSettings

class ModuleEnableSettings(models.Model):
    account = OneToOneField(Account, primary_key=True)
    
    planner_enabled = BooleanField(default=True)
    writer_enabled = BooleanField(default=True)
    linker_enabled = BooleanField(default=False)
    optimizer_enabled = BooleanField(default=False)
    automation_enabled = BooleanField(default=True)
    integration_enabled = BooleanField(default=True)
    publisher_enabled = BooleanField(default=True)

AIIntegrationSettings

class AIIntegrationSettings(models.Model):
    account = ForeignKey(Account, related_name='ai_settings')
    
    # OpenAI
    openai_api_key = CharField(max_length=255, blank=True)
    openai_model = CharField(max_length=50, default='gpt-4')
    
    # Image generation
    image_provider = CharField(max_length=50, default='dalle')  # dalle, runware
    dalle_api_key = CharField(max_length=255, blank=True)
    runware_api_key = CharField(max_length=255, blank=True)
    
    is_validated = BooleanField(default=False)
    validated_at = DateTimeField(null=True)

PromptTemplate

class PromptTemplate(models.Model):
    account = ForeignKey(Account, null=True)  # null = system default
    
    prompt_type = CharField(max_length=100)  # auto_cluster, generate_ideas, etc.
    template = TextField()
    variables = JSONField(default=list)
    
    is_active = BooleanField(default=True)
    
    created_at = DateTimeField(auto_now_add=True)
    updated_at = DateTimeField(auto_now=True)

Publisher Models (igny8_core/modules/publisher/models.py)

PublishingRecord

class PublishingRecord(models.Model):
    id = UUIDField(primary_key=True)
    content = ForeignKey(Content, related_name='publishing_records')
    integration = ForeignKey(SiteIntegration, related_name='publishing_records')
    
    external_id = CharField(max_length=255)  # WordPress post ID
    external_url = URLField(blank=True)
    
    status = CharField(max_length=50)  # pending, published, failed
    
    published_at = DateTimeField(null=True)
    created_at = DateTimeField(auto_now_add=True)

Automation Models (igny8_core/modules/automation/models.py)

AutomationConfig

class AutomationConfig(models.Model):
    site = ForeignKey(Site, related_name='automation_configs')
    
    # Stage limits
    clustering_limit = IntegerField(default=10)
    ideas_limit = IntegerField(default=10)
    content_limit = IntegerField(default=5)
    image_limit = IntegerField(default=10)
    publish_limit = IntegerField(default=5)
    
    # Timing
    delay_between_operations = IntegerField(default=5)  # seconds
    max_runtime = IntegerField(default=3600)  # 1 hour
    
    # Behavior
    auto_approve = BooleanField(default=False)
    auto_publish = BooleanField(default=False)
    stop_on_error = BooleanField(default=True)
    
    is_active = BooleanField(default=True)

AutomationRun

class AutomationRun(models.Model):
    id = UUIDField(primary_key=True)
    site = ForeignKey(Site, related_name='automation_runs')
    config = ForeignKey(AutomationConfig)
    
    status = CharField(max_length=50)  # pending, running, paused, completed, failed, cancelled
    
    # Progress tracking
    current_stage = CharField(max_length=50, blank=True)
    items_processed = IntegerField(default=0)
    items_total = IntegerField(default=0)
    
    # Timing
    started_at = DateTimeField(null=True)
    completed_at = DateTimeField(null=True)
    
    # Results
    error_message = TextField(blank=True)
    
    started_by = ForeignKey(User)
    created_at = DateTimeField(auto_now_add=True)

Entity Relationship Overview

Account
├── Users (many)
├── Sites (many)
│   ├── Sectors (many)
│   ├── Keywords (many)
│   ├── Clusters (many)
│   ├── ContentIdeas (many)
│   ├── Tasks (many)
│   ├── Content (many)
│   │   └── ContentImages (many)
│   ├── SiteIntegrations (many)
│   │   └── PublishingRecords (many)
│   └── AutomationConfigs (many)
│       └── AutomationRuns (many)
├── Plan (one)
├── CreditBalances (many)
├── CreditUsage (many)
├── ModuleEnableSettings (one)
├── AIIntegrationSettings (many)
└── PromptTemplates (many)