account, schduels, timezone profile and many imporant updates
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user