Template
Populate the client website template with catalog feature flags.
Extract always-on public/portal/UTM plus optional email_sms, directmail, blog, payments, social, and social_ai so new client sites can be bootstrapped from this seed. Refs #1 Refs #2 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
"""Register portal nav, dashboard widgets, and due-work dispatch."""
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
from core.registry import (
|
||||
register_dashboard_collector,
|
||||
register_dispatcher,
|
||||
register_feature,
|
||||
register_portal_nav,
|
||||
)
|
||||
|
||||
|
||||
def register() -> None:
|
||||
register_feature("email_sms")
|
||||
register_portal_nav(
|
||||
section="campaigns",
|
||||
label="Campaigns",
|
||||
url_name="email_sms:campaign_list",
|
||||
group="Outreach",
|
||||
order=20,
|
||||
)
|
||||
register_dashboard_collector(_dashboard)
|
||||
register_dispatcher(_dispatch_due)
|
||||
|
||||
|
||||
def _dashboard(request) -> dict:
|
||||
from email_sms.models import Campaign
|
||||
|
||||
upcoming = Campaign.objects.exclude(
|
||||
status__in=[Campaign.Status.COMPLETED, Campaign.Status.CANCELLED]
|
||||
).order_by("scheduled_for", "-created_at")[:5]
|
||||
return {"upcoming_campaigns": upcoming}
|
||||
|
||||
|
||||
def _dispatch_due() -> int:
|
||||
from email_sms.models import Message
|
||||
from email_sms.tasks import send_campaign_message
|
||||
|
||||
now = timezone.now()
|
||||
enqueued = 0
|
||||
for message in Message.objects.filter(
|
||||
status=Message.Status.SCHEDULED,
|
||||
scheduled_for__lte=now,
|
||||
).iterator():
|
||||
message.status = Message.Status.QUEUED
|
||||
message.save(update_fields=["status", "updated_at"])
|
||||
send_campaign_message.enqueue(message_id=str(message.pk))
|
||||
enqueued += 1
|
||||
return enqueued
|
||||
Reference in New Issue
Block a user