Skip to content

feat: Email campaigns module, VAT on invoices, and churn risk tracking#1256

Open
NteinPrecious wants to merge 1 commit into
DistinctCodes:mainfrom
NteinPrecious:feature/nteinprecious-issues-1210-1211-1212-1213
Open

feat: Email campaigns module, VAT on invoices, and churn risk tracking#1256
NteinPrecious wants to merge 1 commit into
DistinctCodes:mainfrom
NteinPrecious:feature/nteinprecious-issues-1210-1211-1212-1213

Conversation

@NteinPrecious

Copy link
Copy Markdown
Contributor

Summary

This PR implements four features assigned to NteinPrecious:

[BE-31] Tax / VAT on Invoices: Backend (#1210)

  • Added subtotalKobo (int), taxRatePercent (decimal, default 7.5), and taxAmountKobo (int) fields to Invoice entity
  • Existing invoices maintain backward compatibility via column defaults
  • Tax rate is configurable via VAT_RATE_PERCENT env var (implemented in GenerateInvoiceProvider)
  • Invoice entity now stores full tax breakdown: subtotal, VAT rate, VAT amount, and grand total

[BE-32] Email Campaigns to Member Segments: Backend (#1211)

  • New EmailCampaign entity: subject, bodyHtml, targetSegment (ALL/ACTIVE/INACTIVE/STAFF), scheduledAt, sentAt, status (DRAFT/SCHEDULED/SENDING/SENT), recipientCount, createdByAdminId
  • POST /email-campaigns — create campaign as DRAFT (admin only)
  • PATCH /email-campaigns/:id — edit draft (rejects if not DRAFT)
  • POST /email-campaigns/:id/send — trigger send immediately (status → SENDING → SENT)
  • GET /email-campaigns — paginated list with optional status filter
  • GET /email-campaigns/:id — campaign detail
  • EmailCampaignsModule registered in AppModule

[FE-29] Email Campaigns: Frontend (#1212)

  • /admin/campaigns page listing campaigns with subject, segment badge, status badge, created date
  • New Campaign button → modal composer with: subject input, audience segment dropdown (ALL/ACTIVE/INACTIVE/STAFF), body textarea
  • Draft campaigns show a Send button; sent campaigns are read-only in the list
  • useGetEmailCampaigns, useCreateEmailCampaign, useSendEmailCampaign React Query hooks

[BE-33] Churn Risk Tracking: Backend (#1213)

  • GET /dashboard/admin/churn-risk — returns paginated list of at-risk members
  • At-risk criteria: (a) no booking in past 30 days but ≥1 booking in 31–90 day window, OR (b) membershipStatus === 'inactive'
  • Response per member: userId, fullName, email, lastBookingDate, totalBookingsAllTime, riskScore
  • riskScore heuristic: 100 - (daysSinceLastBooking / 90) * 100, capped at 0–100; sorted descending
  • Supports ?page= and ?limit= pagination

Closes #1211
Closes #1212
Closes #1210
Closes #1213

@vercel

vercel Bot commented Jun 27, 2026

Copy link
Copy Markdown

@NteinPrecious is attempting to deploy a commit to the naijabuz's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jun 27, 2026

Copy link
Copy Markdown

@NteinPrecious Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant