You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Admins have no way to send targeted marketing or informational email campaigns beyond one-off notifications. Email campaigns enable member engagement, re-activation outreach, and event promotion at scale.
Context
EmailModule: backend/src/email/
User entity with membershipStatus, isVerified, role for audience segmentation
BullModule already configured for async job queuing — use it to batch-send without blocking
Tasks
Create EmailCampaign entity: id, subject, bodyHtml (text), targetSegment (ALL / ACTIVE / INACTIVE / STAFF), scheduledAt (nullable timestamptz), sentAt (nullable), status (DRAFT / SCHEDULED / SENDING / SENT), recipientCount (int, set after send), createdByAdminId (FK), createdAt
POST /email-campaigns — create campaign as DRAFT (admin only)
PATCH /email-campaigns/:id — edit draft (admin only; reject if status !== DRAFT)
POST /email-campaigns/:id/send — enqueue send job immediately (status → SENDING) or set scheduledAt (status → SCHEDULED)
Bull worker job: resolves target users by segment, sends email to each via EmailModule, increments recipientCount, sets status = SENT and sentAt
GET /email-campaigns — paginated list (admin only) with status filter
GET /email-campaigns/:id — campaign detail (admin only)
Overview
Admins have no way to send targeted marketing or informational email campaigns beyond one-off notifications. Email campaigns enable member engagement, re-activation outreach, and event promotion at scale.
Context
EmailModule:backend/src/email/Userentity withmembershipStatus,isVerified,rolefor audience segmentationBullModulealready configured for async job queuing — use it to batch-send without blockingTasks
EmailCampaignentity:id,subject,bodyHtml(text),targetSegment(ALL/ACTIVE/INACTIVE/STAFF),scheduledAt(nullable timestamptz),sentAt(nullable),status(DRAFT/SCHEDULED/SENDING/SENT),recipientCount(int, set after send),createdByAdminId(FK),createdAtPOST /email-campaigns— create campaign asDRAFT(admin only)PATCH /email-campaigns/:id— edit draft (admin only; reject ifstatus !== DRAFT)POST /email-campaigns/:id/send— enqueue send job immediately (status →SENDING) or setscheduledAt(status →SCHEDULED)EmailModule, incrementsrecipientCount, setsstatus = SENTandsentAtGET /email-campaigns— paginated list (admin only) withstatusfilterGET /email-campaigns/:id— campaign detail (admin only)Files to Modify / Create
backend/src/email-campaigns/(module, entity, controller, service, bull processor)backend/src/app.module.ts