From a46d56aa2896474096c42fbb61a1ff716da8f416 Mon Sep 17 00:00:00 2001 From: Steven Tey Date: Wed, 12 Nov 2025 16:58:40 -0800 Subject: [PATCH 1/2] Remove programEnrollment dependency on notify-partner/program --- .../api/cron/messages/notify-partner/route.ts | 73 +++++++++--------- .../api/cron/messages/notify-program/route.ts | 76 +++++++++---------- 2 files changed, 72 insertions(+), 77 deletions(-) diff --git a/apps/web/app/(ee)/api/cron/messages/notify-partner/route.ts b/apps/web/app/(ee)/api/cron/messages/notify-partner/route.ts index 50093915ca7..ab6f60fa6dc 100644 --- a/apps/web/app/(ee)/api/cron/messages/notify-partner/route.ts +++ b/apps/web/app/(ee)/api/cron/messages/notify-partner/route.ts @@ -33,44 +33,43 @@ export async function POST(req: Request) { JSON.parse(rawBody), ); - const programEnrollment = await prisma.programEnrollment.findUniqueOrThrow({ + const partner = await prisma.partner.findUniqueOrThrow({ where: { - partnerId_programId: { - partnerId, - programId, - }, - status: "approved", + id: partnerId, }, include: { - program: true, - partner: { - include: { - messages: { - where: { - programId, - createdAt: { - gt: subDays(new Date(), 3), // sent in the last 3 days - }, - senderPartnerId: null, // not sent by the partner - readInApp: null, // unread messages only - readInEmail: null, // unread messages only - }, - orderBy: { - createdAt: "desc", - }, - include: { - senderUser: true, - }, + programs: { + where: { + programId, + }, + select: { + program: true, + }, + }, + messages: { + where: { + programId, + createdAt: { + gt: subDays(new Date(), 3), // sent in the last 3 days }, - users: { - include: { - user: true, - }, - where: { - notificationPreferences: { - newMessageFromProgram: true, - }, - }, + senderPartnerId: null, // not sent by the partner + readInApp: null, // unread messages only + readInEmail: null, // unread messages only + }, + orderBy: { + createdAt: "desc", + }, + include: { + senderUser: true, + }, + }, + users: { + include: { + user: true, + }, + where: { + notificationPreferences: { + newMessageFromProgram: true, }, }, }, @@ -78,7 +77,7 @@ export async function POST(req: Request) { }); // unread messages are already sorted by latest message first - const unreadMessages = programEnrollment.partner.messages; + const unreadMessages = partner.messages; if (unreadMessages.length === 0) return logAndRespond( @@ -91,7 +90,7 @@ export async function POST(req: Request) { `There is a more recent unread message than ${lastMessageId}. Skipping...`, ); - const partnerUsersToNotify = programEnrollment.partner.users + const partnerUsersToNotify = partner.users .map(({ user }) => user) .filter(Boolean) as { email: string; id: string }[]; @@ -100,7 +99,7 @@ export async function POST(req: Request) { `No partner emails to notify for partner ${partnerId}. Skipping...`, ); - const program = programEnrollment.program; + const program = partner.programs[0].program; const { data, error } = await sendBatchEmail( partnerUsersToNotify.map(({ email }) => ({ diff --git a/apps/web/app/(ee)/api/cron/messages/notify-program/route.ts b/apps/web/app/(ee)/api/cron/messages/notify-program/route.ts index 03b9e2e38eb..4a6b8bf1026 100644 --- a/apps/web/app/(ee)/api/cron/messages/notify-program/route.ts +++ b/apps/web/app/(ee)/api/cron/messages/notify-program/route.ts @@ -33,52 +33,48 @@ export async function POST(req: Request) { JSON.parse(rawBody), ); - const programEnrollment = await prisma.programEnrollment.findUniqueOrThrow({ + const program = await prisma.program.findUniqueOrThrow({ where: { - partnerId_programId: { - partnerId, - programId, - }, - status: "approved", + id: programId, }, include: { - program: { - include: { - workspace: { - include: { - users: { - include: { - user: true, - }, - where: { - notificationPreference: { - newMessageFromPartner: true, - }, - }, - }, - }, + partners: { + where: { + partnerId, + }, + select: { + partner: true, + }, + }, + messages: { + where: { + partnerId, + senderPartnerId: { + not: null, // Sent by the partner + }, + createdAt: { + gt: subDays(new Date(), 3), // Sent in the last 3 days }, + readInApp: null, // Unread + readInEmail: null, // Unread + }, + orderBy: { + createdAt: "desc", + }, + include: { + senderPartner: true, }, }, - partner: { + workspace: { include: { - messages: { + users: { + include: { + user: true, + }, where: { - programId, - senderPartnerId: { - not: null, // Sent by the partner + notificationPreference: { + newMessageFromPartner: true, }, - createdAt: { - gt: subDays(new Date(), 3), // Sent in the last 3 days - }, - readInApp: null, // Unread - readInEmail: null, // Unread - }, - orderBy: { - createdAt: "desc", - }, - include: { - senderPartner: true, }, }, }, @@ -86,7 +82,7 @@ export async function POST(req: Request) { }, }); - const unreadMessages = programEnrollment.partner.messages; + const unreadMessages = program.messages; // unread messages are already sorted by latest message first if (unreadMessages.length === 0) @@ -100,7 +96,7 @@ export async function POST(req: Request) { `There is a more recent unread message than ${lastMessageId}. Skipping...`, ); - const usersToNotify = programEnrollment.program.workspace.users + const usersToNotify = program.workspace.users .map(({ user }) => user) .filter(Boolean) as { email: string; id: string }[]; @@ -109,7 +105,7 @@ export async function POST(req: Request) { `No program user emails to notify from partner ${partnerId}. Skipping...`, ); - const { program, partner } = programEnrollment; + const partner = program.partners[0].partner; const { data, error } = await sendBatchEmail( usersToNotify.map(({ email }) => ({ From 4dfeb98499cb12ed342216fc43b048e3225e81e3 Mon Sep 17 00:00:00 2001 From: Steven Tey Date: Wed, 12 Nov 2025 17:05:21 -0800 Subject: [PATCH 2/2] remove dependency --- .../api/cron/messages/notify-partner/route.ts | 73 ++++++++--------- .../api/cron/messages/notify-program/route.ts | 79 +++++++++---------- 2 files changed, 73 insertions(+), 79 deletions(-) diff --git a/apps/web/app/(ee)/api/cron/messages/notify-partner/route.ts b/apps/web/app/(ee)/api/cron/messages/notify-partner/route.ts index ab6f60fa6dc..50592a03769 100644 --- a/apps/web/app/(ee)/api/cron/messages/notify-partner/route.ts +++ b/apps/web/app/(ee)/api/cron/messages/notify-partner/route.ts @@ -33,48 +33,47 @@ export async function POST(req: Request) { JSON.parse(rawBody), ); - const partner = await prisma.partner.findUniqueOrThrow({ - where: { - id: partnerId, - }, - include: { - programs: { - where: { - programId, - }, - select: { - program: true, - }, + const [partner, program] = await Promise.all([ + prisma.partner.findUniqueOrThrow({ + where: { + id: partnerId, }, - messages: { - where: { - programId, - createdAt: { - gt: subDays(new Date(), 3), // sent in the last 3 days + include: { + messages: { + where: { + programId, + createdAt: { + gt: subDays(new Date(), 3), // sent in the last 3 days + }, + senderPartnerId: null, // not sent by the partner + readInApp: null, // unread messages only + readInEmail: null, // unread messages only + }, + orderBy: { + createdAt: "desc", + }, + include: { + senderUser: true, }, - senderPartnerId: null, // not sent by the partner - readInApp: null, // unread messages only - readInEmail: null, // unread messages only - }, - orderBy: { - createdAt: "desc", - }, - include: { - senderUser: true, - }, - }, - users: { - include: { - user: true, }, - where: { - notificationPreferences: { - newMessageFromProgram: true, + users: { + include: { + user: true, + }, + where: { + notificationPreferences: { + newMessageFromProgram: true, + }, }, }, }, - }, - }); + }), + prisma.program.findUniqueOrThrow({ + where: { + id: programId, + }, + }), + ]); // unread messages are already sorted by latest message first const unreadMessages = partner.messages; @@ -99,8 +98,6 @@ export async function POST(req: Request) { `No partner emails to notify for partner ${partnerId}. Skipping...`, ); - const program = partner.programs[0].program; - const { data, error } = await sendBatchEmail( partnerUsersToNotify.map(({ email }) => ({ subject: `${program.name} sent ${unreadMessages.length === 1 ? "a message" : `${unreadMessages.length} messages`}`, diff --git a/apps/web/app/(ee)/api/cron/messages/notify-program/route.ts b/apps/web/app/(ee)/api/cron/messages/notify-program/route.ts index 4a6b8bf1026..b96b8ed15e2 100644 --- a/apps/web/app/(ee)/api/cron/messages/notify-program/route.ts +++ b/apps/web/app/(ee)/api/cron/messages/notify-program/route.ts @@ -33,54 +33,53 @@ export async function POST(req: Request) { JSON.parse(rawBody), ); - const program = await prisma.program.findUniqueOrThrow({ - where: { - id: programId, - }, - include: { - partners: { - where: { - partnerId, - }, - select: { - partner: true, - }, + const [program, partner] = await Promise.all([ + prisma.program.findUniqueOrThrow({ + where: { + id: programId, }, - messages: { - where: { - partnerId, - senderPartnerId: { - not: null, // Sent by the partner + include: { + messages: { + where: { + partnerId, + senderPartnerId: { + not: null, // Sent by the partner + }, + createdAt: { + gt: subDays(new Date(), 3), // Sent in the last 3 days + }, + readInApp: null, // Unread + readInEmail: null, // Unread }, - createdAt: { - gt: subDays(new Date(), 3), // Sent in the last 3 days + orderBy: { + createdAt: "desc", + }, + include: { + senderPartner: true, }, - readInApp: null, // Unread - readInEmail: null, // Unread - }, - orderBy: { - createdAt: "desc", - }, - include: { - senderPartner: true, }, - }, - workspace: { - include: { - users: { - include: { - user: true, - }, - where: { - notificationPreference: { - newMessageFromPartner: true, + workspace: { + include: { + users: { + include: { + user: true, + }, + where: { + notificationPreference: { + newMessageFromPartner: true, + }, }, }, }, }, }, - }, - }); + }), + prisma.partner.findUniqueOrThrow({ + where: { + id: partnerId, + }, + }), + ]); const unreadMessages = program.messages; @@ -105,8 +104,6 @@ export async function POST(req: Request) { `No program user emails to notify from partner ${partnerId}. Skipping...`, ); - const partner = program.partners[0].partner; - const { data, error } = await sendBatchEmail( usersToNotify.map(({ email }) => ({ subject: `${unreadMessages.length === 1 ? "New message from" : `${unreadMessages.length} new messages from`} ${partner.name}`,