fix: send founder email on first paid subscription (#247)

This commit is contained in:
KM Koushik
2025-09-21 06:18:16 +10:00
committed by GitHub
parent 1226e89aaf
commit 5780177d26
3 changed files with 40 additions and 4 deletions

View File

@@ -1,7 +1,9 @@
import Stripe from "stripe"; import Stripe from "stripe";
import { env } from "~/env"; import { env } from "~/env";
import { db } from "../db"; import { db } from "../db";
import { sendSubscriptionConfirmationEmail } from "../mailer";
import { TeamService } from "../service/team-service"; import { TeamService } from "../service/team-service";
import { logger } from "../logger/log";
export function getStripe() { export function getStripe() {
if (!env.STRIPE_SECRET_KEY) { if (!env.STRIPE_SECRET_KEY) {
@@ -123,6 +125,8 @@ export async function syncStripeData(customerId: string) {
return; return;
} }
const wasPaid = team.isActive && team.plan !== "FREE";
const subscriptions = await stripe.subscriptions.list({ const subscriptions = await stripe.subscriptions.list({
customer: customerId, customer: customerId,
limit: 1, limit: 1,
@@ -144,6 +148,10 @@ export async function syncStripeData(customerId: string) {
.map((item) => item.price?.id) .map((item) => item.price?.id)
.filter((id): id is string => Boolean(id)); .filter((id): id is string => Boolean(id));
const nextPlan = getPlanFromPriceIds(priceIds);
const isNowPaid = subscription.status === "active" && nextPlan !== "FREE";
const shouldSendSubscriptionConfirmation = !wasPaid && isNowPaid;
await db.subscription.upsert({ await db.subscription.upsert({
where: { id: subscription.id }, where: { id: subscription.id },
update: { update: {
@@ -182,10 +190,24 @@ export async function syncStripeData(customerId: string) {
}); });
await TeamService.updateTeam(team.id, { await TeamService.updateTeam(team.id, {
plan: plan: subscription.status === "canceled" ? "FREE" : nextPlan,
subscription.status === "canceled"
? "FREE"
: getPlanFromPriceIds(priceIds),
isActive: subscription.status === "active", isActive: subscription.status === "active",
}); });
if (shouldSendSubscriptionConfirmation) {
try {
const teamUsers = await TeamService.getTeamUsers(team.id);
await Promise.all(
teamUsers
.map((tu) => tu.user?.email)
.filter((email): email is string => Boolean(email))
.map((email) => sendSubscriptionConfirmationEmail(email))
);
} catch (err) {
logger.error(
{ err, teamId: team.id },
"[Billing]: Failed sending subscription confirmation email"
);
}
}
} }

View File

@@ -69,6 +69,19 @@ export async function sendTeamInviteEmail(
await sendMail(email, subject, text, html); await sendMail(email, subject, text, html);
} }
export async function sendSubscriptionConfirmationEmail(email: string) {
if (!env.FOUNDER_EMAIL) {
logger.error("FOUNDER_EMAIL not configured");
return;
}
const subject = "Thanks for subscribing to useSend";
const text = `Hey,\n\nThanks for subscribing to useSend, just wanted to let you know you can join the discord server to have a dedicated support channel for your team. So that we can address your queries / bugs asap.\n\nYou can join over using the link: https://discord.com/invite/BU8n8pJv8S\n\nIf you prefer slack, please let me know\n\ncheers,\nkoushik - useSend`;
const html = text.replace(/\n/g, "<br />");
await sendMail(email, subject, text, html, undefined, env.FOUNDER_EMAIL);
}
export async function sendMail( export async function sendMail(
email: string, email: string,
subject: string, subject: string,

View File

@@ -563,6 +563,7 @@ export class TeamService {
"[TeamService]: Set warning notification cooldown" "[TeamService]: Set warning notification cooldown"
); );
} }
} }
async function getLimitReachedEmail( async function getLimitReachedEmail(