-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Add program payout thank you email template #3132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Introduces a new React email template for thanking programs after making a payout to partners. The template displays the program name, payout amount, number of partners, and includes a link to view invoices.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds batched email dispatch and a new ProgramPayoutThankYou email template to the payouts workflow; modifies payout processing to include workspace slug and payout fields, fetch user emails via Prisma, and queue batch emails after booking payouts; updates payout email subjects to include formatted amounts. Changes
Sequence Diagram(s)sequenceDiagram
actor Cron
participant Processor as process-payouts.ts
participant DB as Prisma
participant EmailQueue as queueBatchEmail
Cron->>Processor: trigger payout processing
Processor->>DB: update/process payouts (include users.emails)
DB-->>Processor: payouts + users
Processor->>DB: book payout / update payoutsUsage (include users)
DB-->>Processor: updated workspace + users
rect rgb(200,230,201)
note right of Processor: New — batch email dispatch
Processor->>EmailQueue: queueBatchEmail(ProgramPayoutThankYou, recipients[], payload)
EmailQueue-->>Processor: queued ack
end
Processor-->>Cron: finished
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/email/src/templates/program-payout-thankyou.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
📚 Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
packages/email/src/templates/program-payout-thankyou.tsx
🧬 Code graph analysis (1)
packages/email/src/templates/program-payout-thankyou.tsx (3)
packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter(7-22)packages/email/src/react-email.d.ts (11)
Html(4-4)Head(5-5)Preview(18-18)Tailwind(19-19)Body(6-6)Container(7-7)Section(8-8)Img(13-13)Heading(16-16)Text(15-15)Link(14-14)packages/email/src/templates/program-payout-reminder.tsx (1)
ProgramPayoutReminder(19-106)
🪛 Biome (2.1.2)
packages/email/src/templates/program-payout-thankyou.tsx
[error] 118-119: Unexpected token. Did you mean {'}'} or }?
(parse)
[error] 119-119: expected < but instead the file ends
the file ends here
(parse)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (2)
packages/email/src/templates/program-payout-thankyou.tsx (2)
17-45: Overall template structure and responsive styling look solidProps typing, sensible defaults, preview line, heading hierarchy, Tailwind classes, and the small-screen media query for the amount/heading all align well with the existing email templates in this repo. No additional issues from my side here.
Also applies to: 50-101, 111-113
102-108: URL is correct and consistent across the codebaseThe invoices URL in the email is properly formatted and matches the app's routing. The invoices page defines
partnerPayoutas a valid invoice type, and the API endpoint validates this type in its enum. The same link pattern is used consistently in other parts of the app (e.g., payout-stats.tsx and success pages), confirming this is the intended destination for the partner payout invoices view.
| return ( | ||
| <Html> | ||
| <Html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove duplicate <Html> wrapper causing JSX parse error
There are two opening <Html> tags but only one closing </Html>, which is exactly what Biome is flagging and will prevent this file from compiling.
Apply this minimal fix:
- return (
- <Html>
- <Html>
+ return (
+ <Html>Also applies to: 117-118
🤖 Prompt for AI Agents
In packages/email/src/templates/program-payout-thankyou.tsx around lines 47-49
(and also at lines 117-118), there are duplicated opening <Html> tags with only
one closing </Html>, causing a JSX parse error; remove the extra opening <Html>
tag(s) so each <Html> has a matching closing tag (i.e., leave a single <Html>
wrapper at the top and remove the duplicate(s) at the noted lines) and re-run
the build to confirm the file compiles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts (1)
282-299: Consider adding an idempotency key for email batching.The email batching implementation looks correct and properly constructs the template props. However, unlike the Stripe payment intent (line 238), no idempotency key is provided to
queueBatchEmail. If the function is retried after the payment intent succeeds but before/during email sending, duplicate thank you emails could be sent to workspace users.Consider adding an idempotency key based on the invoice ID:
await queueBatchEmail<typeof ProgramPayoutThankYou>( users.map(({ user }) => ({ to: user.email!, subject: `Thank you for your ${currencyFormatter(totalPayoutAmount)} payout to ${res.count} partners`, templateName: "ProgramPayoutThankYou", templateProps: { email: user.email!, workspace, program: { name: program.name, }, payout: { amount: totalPayoutAmount, partnersCount: res.count, }, }, })), + { + idempotencyKey: `payout-thank-you/${invoice.id}`, + }, );packages/email/src/templates/program-payout-thank-you.tsx (1)
26-26: Consider a more realistic default preview amount.The default amount of
450000000cents equals $4,500,000, which is quite high for preview purposes. Consider using a more typical amount like450000cents ($4,500) or4500000cents ($45,000) for easier preview testing.payout = { - amount: 450000000, + amount: 4500000, // $45,000 partnersCount: 12, },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts(5 hunks)apps/web/lib/email/email-templates-map.ts(1 hunks)packages/email/src/templates/program-payout-thank-you.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/lib/email/email-templates-map.tspackages/email/src/templates/program-payout-thank-you.tsx
📚 Learning: 2025-11-17T05:19:11.961Z
Learnt from: devkiran
Repo: dubinc/dub PR: 3113
File: apps/web/app/(ee)/api/cron/payouts/charge-succeeded/send-paypal-payouts.ts:65-75
Timestamp: 2025-11-17T05:19:11.961Z
Learning: In the Dub codebase, `sendBatchEmail` (implemented in packages/email/src/send-via-resend.ts) handles filtering of emails with invalid `to` addresses internally. Call sites can safely use non-null assertions on email addresses because the email sending layer will filter out any entries with null/undefined `to` values before sending. This centralized validation pattern is intentional and removes the need for filtering at individual call sites.
Applied to files:
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts
🧬 Code graph analysis (2)
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts (4)
packages/prisma/index.ts (1)
prisma(3-9)apps/web/lib/email/queue-batch-email.ts (1)
queueBatchEmail(18-87)packages/email/src/templates/program-payout-thank-you.tsx (1)
ProgramPayoutThankYou(17-118)packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter(7-22)
packages/email/src/templates/program-payout-thank-you.tsx (2)
packages/utils/src/functions/currency-formatter.ts (1)
currencyFormatter(7-22)packages/email/src/templates/program-payout-reminder.tsx (1)
ProgramPayoutReminder(19-106)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (7)
apps/web/lib/email/email-templates-map.ts (1)
6-6: LGTM!The new email template is properly imported and registered in the templates map, following the same pattern as existing templates.
Also applies to: 14-14
apps/web/app/(ee)/api/cron/payouts/process/process-payouts.ts (3)
4-4: LGTM!The imports for
queueBatchEmailandProgramPayoutThankYouare correct and necessary for the new email notification feature.Also applies to: 12-12
26-26: LGTM!Adding
slugto the workspace type is necessary for constructing the invoice link in the email template.
242-262: Verify email recipients: all workspace users vs. payout initiator only.The update now fetches all workspace users and their emails. This means the thank you email will be sent to all users in the workspace, not just the user who initiated the payout (
userIdparameter). Confirm this is the intended behavior.If you want to send the email only to the initiating user, you'll need to filter or fetch that specific user instead:
include: { users: { where: { userId: userId, }, select: { user: { select: { email: true, }, }, }, }, },packages/email/src/templates/program-payout-thank-you.tsx (3)
1-15: LGTM!All necessary imports are present for the email template, including utility functions (
currencyFormatter,pluralize), React Email components, and theFootercomponent.
42-45: LGTM!The amount formatting correctly removes decimal places for a cleaner display in the thank you message. The formatter defaults to USD, which aligns with the payout processing logic where amounts are always stored in USD cents.
47-117: LGTM!The email template structure is well-designed:
- Responsive styles handle mobile layouts appropriately
- The clamp-based font sizing provides smooth responsiveness for the amount display
- Pluralization is correctly applied to "partner"/"partners"
- The invoice link properly uses
workspace.slugand includes thetype=partnerPayoutquery parameter- Footer component is correctly integrated
The hardcoded
app.dub.codomain is consistent with other email templates in the codebase (e.g.,program-payout-reminder.tsx).
Introduces a new React email template for thanking programs after making a payout to partners. The template displays the program name, payout amount, number of partners, and includes a link to view invoices.
Summary by CodeRabbit
New Features
User Communication