Skip to content

feat(mailers): thank coaches when they reach an attendance milestone - #2985

Draft
jabawack81 wants to merge 5 commits into
codebar:masterfrom
jabawack81:feature/coach-milestone-thank-you-emails
Draft

jabawack81 wants to merge 5 commits into
codebar:masterfrom
jabawack81:feature/coach-milestone-thank-you-emails

Conversation

@jabawack81

Copy link
Copy Markdown
Contributor

Closes #2386

Problem

Coaches never hear from us for showing up. Kimberley wants a thank-you email once a coach has attended 5 workshops, possibly again at 10, 15, 20.

Change

Same shape as the three-month chaser: a daily rake task enqueues a job, the job calls a service, the service picks members and hands them to MemberMailer.

  • CoachMilestoneEmailService counts attended coach invitations for past workshops in one grouped query (it hits the partial index from Speed up /coaches: partial index and database-side coach count #2900), keeps coaches at or past a milestone who are not banned and have accepted the ToC, and sends each the highest milestone they have reached. Anyone already logged for that milestone or a higher one is skipped.
  • MemberMailer#coach_milestone renders Kimberley's copy with the number filled in.
  • EmailDelivery logs through a new email_type_for_log hook, default action_name, so existing callers are unchanged. The mailer overrides it to coach_milestone_<n> so several milestones can share one action without hitting the (member_id, email_type) unique index.
  • MILESTONES = [5]. Adding more is a one-line change.

I did not use a callback on attended: attendance is set from check-in and the admin toggle and gets corrected after the fact. A daily sweep handles that; a callback would not.

Verification

  • Service spec covers eligible at 5 and 7, below 5, future workshop, invited but absent, student role, already thanked, thanked for a higher milestone, banned, no ToC, idempotency, and highest-only with MILESTONES stubbed to [5, 10].
  • Mailer, job and rake task specs. Existing chaser and nudge specs unchanged.
  • Ran it by hand against six seeded members: two emails, right people, right copy. Second run sent nothing.
  • Full suite green apart from the 12 :js specs, which fail locally for lack of Chromium's system libraries. RuboCop clean.

Review notes

Post-deploy

The morning after the first run, MemberEmailDelivery.where("email_type LIKE 'coach_milestone_%'").count should match the number of coaches at 5 or more, with no failed jobs. The day after, it should not have moved.

One action serves every milestone; the delivery log is keyed as
coach_milestone_<n> so each milestone is sent once per member.
Picks coaches at or past a milestone in one grouped query, sends only
the highest milestone reached, and skips anyone already logged for it.
@jabawack81

jabawack81 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

@KimberleyCook The PR is almost ready. I have a couple of questions that should not change the code much, but I think they need answering before merge.

  1. Dormant coaches. The count is all-time, so a coach whose 5 workshops were all years ago gets thanked on launch night. Options: send anyway, or require at least one attended workshop in the last X weeks. Not sure what X should be.
  2. CC to hello@codebar.io. Copied from the chaser. On launch night that inbox gets one copy per coach past 5, which could be a lot.
  3. Multiple milestones. Kimberley mentioned 10, 15, 20. The code supports a list already, so do we set them now? If so, on the first run a coach receives only the biggest milestone they have unlocked. Also need to know whether the same wording with the number swapped is fine.

@mroderick

Copy link
Copy Markdown
Collaborator

2. CC to hello@codebar.io. Copied from the chaser. On launch night that inbox gets one copy per coach past 5, which could be a lot.

I am running a Grafana instance on my homelab, which consumes log lines from the planner app. If sending out these emails produces log lines, then we can monitor things there and won't need to overwhelm hello@codebar.io with emails.

If you're going to add log lines, it would be cool if they would carry the member_id, but not any personally identifiable information.

I'm happy to give a demo of the Grafana dashboards and access for the maintainers.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New automated thank you email to coaches who have attended 5 workshops

2 participants