autmation final reaftocrs and setitgns dafautls
This commit is contained in:
@@ -7,6 +7,117 @@ from django.utils import timezone
|
||||
from igny8_core.auth.models import Account, Site
|
||||
|
||||
|
||||
class DefaultAutomationConfig(models.Model):
|
||||
"""
|
||||
Singleton model for default automation settings.
|
||||
Used when creating new sites - copies these defaults to the new AutomationConfig.
|
||||
Also tracks the next scheduled hour to auto-increment for each new site.
|
||||
"""
|
||||
|
||||
FREQUENCY_CHOICES = [
|
||||
('daily', 'Daily'),
|
||||
('weekly', 'Weekly'),
|
||||
('monthly', 'Monthly'),
|
||||
]
|
||||
|
||||
# Singleton - only one row allowed
|
||||
singleton_key = models.CharField(max_length=1, default='X', unique=True, editable=False)
|
||||
|
||||
# Default scheduling settings
|
||||
is_enabled = models.BooleanField(default=False, help_text="Default: Enable scheduled automation for new sites")
|
||||
frequency = models.CharField(max_length=20, choices=FREQUENCY_CHOICES, default='daily')
|
||||
base_scheduled_hour = models.IntegerField(default=2, help_text="Starting hour (0-23) for auto-assignment. Each new site gets next hour.")
|
||||
next_scheduled_hour = models.IntegerField(default=2, help_text="Next hour to assign (auto-increments, wraps at 24)")
|
||||
|
||||
# Stage processing toggles
|
||||
stage_1_enabled = models.BooleanField(default=True, help_text="Process Stage 1: Keywords → Clusters")
|
||||
stage_2_enabled = models.BooleanField(default=True, help_text="Process Stage 2: Clusters → Ideas")
|
||||
stage_3_enabled = models.BooleanField(default=True, help_text="Process Stage 3: Ideas → Tasks")
|
||||
stage_4_enabled = models.BooleanField(default=True, help_text="Process Stage 4: Tasks → Content")
|
||||
stage_5_enabled = models.BooleanField(default=True, help_text="Process Stage 5: Content → Image Prompts")
|
||||
stage_6_enabled = models.BooleanField(default=True, help_text="Process Stage 6: Image Prompts → Images")
|
||||
stage_7_enabled = models.BooleanField(default=True, help_text="Process Stage 7: Review → Published")
|
||||
|
||||
# Batch sizes per stage
|
||||
stage_1_batch_size = models.IntegerField(default=50, help_text="Keywords per batch")
|
||||
stage_2_batch_size = models.IntegerField(default=1, help_text="Clusters at a time")
|
||||
stage_3_batch_size = models.IntegerField(default=20, help_text="Ideas per batch")
|
||||
stage_4_batch_size = models.IntegerField(default=1, help_text="Tasks - sequential")
|
||||
stage_5_batch_size = models.IntegerField(default=1, help_text="Content at a time")
|
||||
stage_6_batch_size = models.IntegerField(default=1, help_text="Images - sequential")
|
||||
|
||||
# Use testing model per stage
|
||||
stage_1_use_testing = models.BooleanField(default=False, help_text="Use testing model for Stage 1")
|
||||
stage_2_use_testing = models.BooleanField(default=False, help_text="Use testing model for Stage 2")
|
||||
stage_4_use_testing = models.BooleanField(default=False, help_text="Use testing model for Stage 4")
|
||||
stage_5_use_testing = models.BooleanField(default=False, help_text="Use testing model for Stage 5")
|
||||
stage_6_use_testing = models.BooleanField(default=False, help_text="Use testing model for Stage 6")
|
||||
|
||||
# Budget percentage per stage
|
||||
stage_1_budget_pct = models.IntegerField(default=15, help_text="Budget percentage for Stage 1")
|
||||
stage_2_budget_pct = models.IntegerField(default=10, help_text="Budget percentage for Stage 2")
|
||||
stage_4_budget_pct = models.IntegerField(default=40, help_text="Budget percentage for Stage 4")
|
||||
stage_5_budget_pct = models.IntegerField(default=5, help_text="Budget percentage for Stage 5")
|
||||
stage_6_budget_pct = models.IntegerField(default=30, help_text="Budget percentage for Stage 6")
|
||||
|
||||
# Delay configuration
|
||||
within_stage_delay = models.IntegerField(default=3, help_text="Delay between batches within a stage (seconds)")
|
||||
between_stage_delay = models.IntegerField(default=5, help_text="Delay between stage transitions (seconds)")
|
||||
|
||||
# Per-run item limits
|
||||
max_keywords_per_run = models.IntegerField(default=0, help_text="Max keywords to process in stage 1 (0=unlimited)")
|
||||
max_clusters_per_run = models.IntegerField(default=0, help_text="Max clusters to process in stage 2 (0=unlimited)")
|
||||
max_ideas_per_run = models.IntegerField(default=0, help_text="Max ideas to process in stage 3 (0=unlimited)")
|
||||
max_tasks_per_run = models.IntegerField(default=0, help_text="Max tasks to process in stage 4 (0=unlimited)")
|
||||
max_content_per_run = models.IntegerField(default=0, help_text="Max content pieces for image prompts in stage 5 (0=unlimited)")
|
||||
max_images_per_run = models.IntegerField(default=0, help_text="Max images to generate in stage 6 (0=unlimited)")
|
||||
max_approvals_per_run = models.IntegerField(default=0, help_text="Max content pieces to auto-approve in stage 7 (0=unlimited)")
|
||||
max_credits_per_run = models.IntegerField(default=0, help_text="Max credits to use per run (0=unlimited)")
|
||||
|
||||
# ===== PUBLISHING DEFAULTS =====
|
||||
# Content publishing settings for new sites
|
||||
auto_approval_enabled = models.BooleanField(default=False, help_text="Auto-approve content after review")
|
||||
auto_publish_enabled = models.BooleanField(default=False, help_text="Auto-publish approved content to site")
|
||||
daily_publish_limit = models.IntegerField(default=3, help_text="Max posts per day")
|
||||
weekly_publish_limit = models.IntegerField(default=15, help_text="Max posts per week")
|
||||
monthly_publish_limit = models.IntegerField(default=50, help_text="Max posts per month")
|
||||
publish_days = models.JSONField(default=list, help_text="Days to publish (e.g., ['mon', 'tue', 'wed', 'thu', 'fri'])")
|
||||
publish_time_slots = models.JSONField(default=list, help_text="Time slots to publish (e.g., ['09:00', '14:00', '18:00'])")
|
||||
|
||||
# ===== IMAGE DEFAULTS =====
|
||||
# Image generation settings for new sites
|
||||
image_style = models.CharField(max_length=50, default='photorealistic', help_text="Default image style")
|
||||
max_images_per_article = models.IntegerField(default=4, help_text="Images per article (1-8)")
|
||||
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'igny8_default_automation_config'
|
||||
verbose_name = 'Default Automation Config'
|
||||
verbose_name_plural = 'Default Automation Config'
|
||||
|
||||
def __str__(self):
|
||||
return f"Default Automation Config (next hour: {self.next_scheduled_hour}:00)"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# Ensure singleton
|
||||
self.singleton_key = 'X'
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def get_instance(cls):
|
||||
"""Get or create the singleton instance"""
|
||||
obj, created = cls.objects.get_or_create(singleton_key='X')
|
||||
return obj
|
||||
|
||||
def get_next_hour_and_increment(self):
|
||||
"""Get the next scheduled hour and increment for the next site"""
|
||||
current_hour = self.next_scheduled_hour
|
||||
self.next_scheduled_hour = (self.next_scheduled_hour + 1) % 24
|
||||
self.save(update_fields=['next_scheduled_hour'])
|
||||
return current_hour
|
||||
|
||||
|
||||
class AutomationConfig(models.Model):
|
||||
"""Per-site automation configuration"""
|
||||
|
||||
@@ -74,6 +185,10 @@ class AutomationConfig(models.Model):
|
||||
last_run_at = models.DateTimeField(null=True, blank=True)
|
||||
next_run_at = models.DateTimeField(null=True, blank=True, help_text="Calculated based on frequency")
|
||||
|
||||
# Test mode fields (for admin testing without waiting for hourly schedule)
|
||||
test_mode_enabled = models.BooleanField(default=False, help_text="Enable test mode - allows test triggers")
|
||||
test_trigger_at = models.DateTimeField(null=True, blank=True, help_text="Set datetime to trigger a test run (auto-clears after trigger)")
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
@@ -84,10 +199,40 @@ class AutomationConfig(models.Model):
|
||||
indexes = [
|
||||
models.Index(fields=['is_enabled', 'next_run_at']),
|
||||
models.Index(fields=['account', 'site']),
|
||||
models.Index(fields=['test_mode_enabled', 'test_trigger_at']),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"Automation Config: {self.site.domain} ({self.frequency})"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""
|
||||
On first save (new config), auto-assign scheduled_time from DefaultAutomationConfig.
|
||||
- Gets next_scheduled_hour from DefaultAutomationConfig
|
||||
- Assigns it to this config
|
||||
- Increments next_scheduled_hour in DefaultAutomationConfig for future configs
|
||||
"""
|
||||
is_new = self.pk is None
|
||||
|
||||
if is_new:
|
||||
# Check if scheduled_time is still the default (not explicitly set by user)
|
||||
default_time_str = '02:00'
|
||||
current_time_str = self.scheduled_time.strftime('%H:%M') if hasattr(self.scheduled_time, 'strftime') else str(self.scheduled_time)
|
||||
|
||||
# Only auto-assign if using default time (user didn't explicitly set it)
|
||||
if current_time_str == default_time_str:
|
||||
try:
|
||||
# Get the tracked next hour from DefaultAutomationConfig and increment it
|
||||
default_config = DefaultAutomationConfig.get_instance()
|
||||
next_hour = default_config.get_next_hour_and_increment()
|
||||
|
||||
# Set the scheduled time to next_hour:00
|
||||
from datetime import time
|
||||
self.scheduled_time = time(hour=next_hour, minute=0)
|
||||
except Exception:
|
||||
pass # Keep default if something fails
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class AutomationRun(models.Model):
|
||||
@@ -96,6 +241,7 @@ class AutomationRun(models.Model):
|
||||
TRIGGER_TYPE_CHOICES = [
|
||||
('manual', 'Manual'),
|
||||
('scheduled', 'Scheduled'),
|
||||
('test', 'Test'),
|
||||
]
|
||||
|
||||
STATUS_CHOICES = [
|
||||
|
||||
Reference in New Issue
Block a user