account, schduels, timezone profile and many imporant updates

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-19 15:37:03 +00:00
parent 618ed8b8c6
commit e7219a2390
28 changed files with 919 additions and 358 deletions

View File

@@ -155,55 +155,27 @@ def _calculate_available_slots(settings: 'PublishingSettings', site: 'Site') ->
allowed_days = [day_map.get(d.lower(), -1) for d in publish_days]
allowed_days = [d for d in allowed_days if d >= 0]
# Calculate limits
daily_limit = settings.daily_publish_limit
weekly_limit = settings.weekly_publish_limit
monthly_limit = settings.monthly_publish_limit
# Calculate limits from configured publish days/slots
daily_limit = settings.daily_capacity
weekly_limit = settings.weekly_capacity
monthly_limit = settings.monthly_capacity
queue_limit = getattr(settings, 'queue_limit', 100) or 100
# Count existing scheduled/published content
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
week_start = today_start - timedelta(days=now.weekday())
month_start = today_start.replace(day=1)
daily_count = Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__gte=today_start
).count()
weekly_count = Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__gte=week_start
).count()
monthly_count = Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__gte=month_start
).count()
# Route to appropriate slot generator
if settings.scheduling_mode == 'stagger':
return _generate_stagger_slots(
settings, site, now, allowed_days,
daily_limit, weekly_limit, monthly_limit, queue_limit,
daily_count, weekly_count, monthly_count
)
else:
# Default to time_slots mode
return _generate_time_slot_slots(
settings, site, now, allowed_days,
daily_limit, weekly_limit, monthly_limit, queue_limit,
daily_count, weekly_count, monthly_count
)
# Always use time_slots mode for scheduling
account_timezone = getattr(site.account, 'account_timezone', 'UTC') if hasattr(site, 'account') else 'UTC'
return _generate_time_slot_slots(
settings, site, now, allowed_days,
daily_limit, weekly_limit, monthly_limit, queue_limit,
account_timezone
)
def _generate_time_slot_slots(
settings, site, now, allowed_days,
daily_limit, weekly_limit, monthly_limit, queue_limit,
daily_count, weekly_count, monthly_count
account_timezone: str
) -> list:
"""Generate slots based on specific time slots (original mode)."""
from igny8_core.business.content.models import Content
@@ -226,41 +198,87 @@ def _generate_time_slot_slots(
current_date = now.date()
slots_per_day = {}
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
week_start = today_start - timedelta(days=now.weekday())
from zoneinfo import ZoneInfo
tzinfo = ZoneInfo(account_timezone or 'UTC')
for day_offset in range(90): # Look 90 days ahead
check_date = current_date + timedelta(days=day_offset)
if check_date.weekday() not in allowed_days:
continue
# Existing scheduled times for this day to avoid conflicts
existing_times = set(
Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__date=check_date
).values_list('scheduled_publish_at', flat=True)
)
for hour, minute in time_slots:
slot_time = timezone.make_aware(
datetime.combine(check_date, datetime.min.time().replace(hour=hour, minute=minute))
)
slot_time = datetime.combine(check_date, datetime.min.time().replace(hour=hour, minute=minute))
slot_time = slot_time.replace(tzinfo=tzinfo)
# Skip if in the past
if slot_time <= now:
continue
# Skip if slot already occupied
if slot_time in existing_times:
continue
# Count existing scheduled/published content for this day/week/month
day_start = timezone.make_aware(datetime.combine(check_date, datetime.min.time()))
day_end = day_start + timedelta(days=1)
existing_day_count = Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__gte=day_start,
scheduled_publish_at__lt=day_end
).count()
week_start = day_start - timedelta(days=day_start.weekday())
week_end = week_start + timedelta(days=7)
existing_week_count = Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__gte=week_start,
scheduled_publish_at__lt=week_end
).count()
month_start = day_start.replace(day=1)
if month_start.month == 12:
next_month_start = month_start.replace(year=month_start.year + 1, month=1)
else:
next_month_start = month_start.replace(month=month_start.month + 1)
existing_month_count = Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__gte=month_start,
scheduled_publish_at__lt=next_month_start
).count()
# Check daily limit
day_key = check_date.isoformat()
slots_this_day = slots_per_day.get(day_key, 0)
if daily_limit and (daily_count + slots_this_day) >= daily_limit:
if daily_limit and (existing_day_count + slots_this_day) >= daily_limit:
continue
# Check weekly limit
slot_week_start = slot_time - timedelta(days=slot_time.weekday())
if slot_week_start.date() == week_start.date():
scheduled_in_week = weekly_count + len([s for s in slots if s >= week_start])
if weekly_limit and scheduled_in_week >= weekly_limit:
continue
scheduled_in_week = existing_week_count + len([
s for s in slots if s >= week_start and s < week_end
])
if weekly_limit and scheduled_in_week >= weekly_limit:
continue
# Check monthly limit
if slot_time.month == now.month and slot_time.year == now.year:
scheduled_in_month = monthly_count + len([s for s in slots if s.month == now.month])
if monthly_limit and scheduled_in_month >= monthly_limit:
continue
scheduled_in_month = existing_month_count + len([
s for s in slots if s >= month_start and s < next_month_start
])
if monthly_limit and scheduled_in_month >= monthly_limit:
continue
slots.append(slot_time)
slots_per_day[day_key] = slots_per_day.get(day_key, 0) + 1
@@ -274,8 +292,7 @@ def _generate_time_slot_slots(
def _generate_stagger_slots(
settings, site, now, allowed_days,
daily_limit, weekly_limit, monthly_limit, queue_limit,
daily_count, weekly_count, monthly_count
daily_limit, weekly_limit, monthly_limit, queue_limit
) -> list:
"""
Generate slots spread evenly throughout the publishing window.
@@ -305,7 +322,6 @@ def _generate_stagger_slots(
current_date = now.date()
slots_per_day = {}
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
week_start = today_start - timedelta(days=now.weekday())
for day_offset in range(90): # Look 90 days ahead
check_date = current_date + timedelta(days=day_offset)
@@ -329,6 +345,37 @@ def _generate_stagger_slots(
scheduled_publish_at__date=check_date
).values_list('scheduled_publish_at', flat=True)
)
# Count existing scheduled/published content for this day/week/month
day_start = timezone.make_aware(datetime.combine(check_date, datetime.min.time()))
day_end = day_start + timedelta(days=1)
existing_day_count = Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__gte=day_start,
scheduled_publish_at__lt=day_end
).count()
week_start = day_start - timedelta(days=day_start.weekday())
week_end = week_start + timedelta(days=7)
existing_week_count = Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__gte=week_start,
scheduled_publish_at__lt=week_end
).count()
month_start = day_start.replace(day=1)
if month_start.month == 12:
next_month_start = month_start.replace(year=month_start.year + 1, month=1)
else:
next_month_start = month_start.replace(month=month_start.month + 1)
existing_month_count = Content.objects.filter(
site=site,
site_status__in=['scheduled', 'publishing', 'published'],
scheduled_publish_at__gte=month_start,
scheduled_publish_at__lt=next_month_start
).count()
# Start slot calculation
current_slot = day_start
@@ -343,23 +390,24 @@ def _generate_stagger_slots(
while current_slot <= day_end:
# Check daily limit
slots_this_day = slots_per_day.get(day_key, 0)
if daily_limit and (daily_count + slots_this_day) >= daily_limit:
if daily_limit and (existing_day_count + slots_this_day) >= daily_limit:
break # Move to next day
# Check weekly limit
slot_week_start = current_slot - timedelta(days=current_slot.weekday())
if slot_week_start.date() == week_start.date():
scheduled_in_week = weekly_count + len([s for s in slots if s >= week_start])
if weekly_limit and scheduled_in_week >= weekly_limit:
current_slot += interval
continue
scheduled_in_week = existing_week_count + len([
s for s in slots if s >= week_start and s < week_end
])
if weekly_limit and scheduled_in_week >= weekly_limit:
current_slot += interval
continue
# Check monthly limit
if current_slot.month == now.month and current_slot.year == now.year:
scheduled_in_month = monthly_count + len([s for s in slots if s.month == now.month])
if monthly_limit and scheduled_in_month >= monthly_limit:
current_slot += interval
continue
scheduled_in_month = existing_month_count + len([
s for s in slots if s >= month_start and s < next_month_start
])
if monthly_limit and scheduled_in_month >= monthly_limit:
current_slot += interval
continue
# Avoid existing scheduled times
if current_slot not in existing_times: