From 6d8e25091d4ef95880f518ded96b5848fc4443ad Mon Sep 17 00:00:00 2001 From: Steven Tey Date: Mon, 28 Jul 2025 15:43:37 -0700 Subject: [PATCH 1/5] Improve payout emails --- .../connect/webhook/balance-available.ts | 7 ++ .../api/stripe/connect/webhook/payout-paid.ts | 19 ++++ .../partner-payout-withdrawal-completed.tsx | 97 +++++++++++++++++++ .../partner-payout-withdrawal-initiated.tsx | 9 +- 4 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 packages/email/src/templates/partner-payout-withdrawal-completed.tsx diff --git a/apps/web/app/(ee)/api/stripe/connect/webhook/balance-available.ts b/apps/web/app/(ee)/api/stripe/connect/webhook/balance-available.ts index 71cf193f105..b9971aa0344 100644 --- a/apps/web/app/(ee)/api/stripe/connect/webhook/balance-available.ts +++ b/apps/web/app/(ee)/api/stripe/connect/webhook/balance-available.ts @@ -130,6 +130,13 @@ export async function balanceAvailable(event: Stripe.Event) { react: PartnerPayoutWithdrawalInitiated({ email: partner.email, amount: payout.amount, + expectedDate: new Date(payout.arrival_date * 1000).toLocaleDateString( + "en-US", + { + month: "long", + day: "numeric", + }, + ), }), }); diff --git a/apps/web/app/(ee)/api/stripe/connect/webhook/payout-paid.ts b/apps/web/app/(ee)/api/stripe/connect/webhook/payout-paid.ts index dd97cf58538..cd84a17ea2c 100644 --- a/apps/web/app/(ee)/api/stripe/connect/webhook/payout-paid.ts +++ b/apps/web/app/(ee)/api/stripe/connect/webhook/payout-paid.ts @@ -1,3 +1,5 @@ +import { sendEmail } from "@dub/email"; +import PartnerPayoutWithdrawalCompleted from "@dub/email/templates/partner-payout-withdrawal-completed"; import { prisma } from "@dub/prisma"; import Stripe from "stripe"; @@ -39,4 +41,21 @@ export async function payoutPaid(event: Stripe.Event) { console.log( `Updated ${updatedPayouts.count} payouts for partner ${partner.email} (${stripeAccount}) to "completed" status`, ); + + if (partner.email) { + const sentEmail = await sendEmail({ + variant: "notifications", + subject: "Your funds have been transferred to your bank account", + email: partner.email, + react: PartnerPayoutWithdrawalCompleted({ + email: partner.email, + amount: stripePayout.amount, + traceId: stripePayout.id, + }), + }); + + console.log( + `Sent email to partner ${partner.email} (${stripeAccount}): ${JSON.stringify(sentEmail, null, 2)}`, + ); + } } diff --git a/packages/email/src/templates/partner-payout-withdrawal-completed.tsx b/packages/email/src/templates/partner-payout-withdrawal-completed.tsx new file mode 100644 index 00000000000..7602e2129f5 --- /dev/null +++ b/packages/email/src/templates/partner-payout-withdrawal-completed.tsx @@ -0,0 +1,97 @@ +import { currencyFormatter, DUB_WORDMARK } from "@dub/utils"; +import { + Body, + Container, + Head, + Heading, + Html, + Img, + Link, + Preview, + Section, + Tailwind, + Text, +} from "@react-email/components"; +import { Footer } from "../components/footer"; + +// Send this email after payout.paid webhook is received +export default function PartnerPayoutWithdrawalCompleted({ + email = "panic@thedis.co", + amount = 45590, + traceId = "DUB PARTN-XYZ", +}: { + email: string; + amount: number; + traceId?: string; +}) { + const amountInDollars = currencyFormatter(amount / 100, { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }); + + const fiveBusinessDaysFromNow = (() => { + let date = new Date(); + let businessDays = 0; + while (businessDays < 5) { + date.setDate(date.getDate() + 1); + // Skip weekends (0 = Sunday, 6 = Saturday) + if (date.getDay() !== 0 && date.getDay() !== 6) { + businessDays++; + } + } + return date.toLocaleDateString("en-US", { + month: "long", + day: "numeric", + }); + })(); + + return ( + + + Your funds have been transferred to your bank account + + + +
+ Dub +
+ + + Your funds have been transferred to your bank account + + + + + {amountInDollars} + {" "} + has been transferred from your Stripe Express account to your + connected bank account. + + + + Banks can take up to 5 business days to process payouts. Wait + until{" "} + + {fiveBusinessDaysFromNow} + {" "} + and then contact your bank using the trace ID{" "} + {traceId}. + + + + If you still have any questions, contact{" "} + + Stripe support + + . + +