From 5854aa37a914a57074a1a8d736c5408f8e370ad7 Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 4 Mar 2026 00:32:14 +0100 Subject: [PATCH] feat: prevent duplicate award pool notifications Add notifiedAt field to AwardEligibility. notifyEligibleProjects now skips already-notified entries and stamps notifiedAt after sending, so re-clicking "Notify Pool" only emails newly added projects. Co-Authored-By: Claude Opus 4.6 --- .../migration.sql | 2 ++ prisma/schema.prisma | 3 +++ src/server/routers/specialAward.ts | 13 +++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 prisma/migrations/20260303232956_add_award_eligibility_notified_at/migration.sql diff --git a/prisma/migrations/20260303232956_add_award_eligibility_notified_at/migration.sql b/prisma/migrations/20260303232956_add_award_eligibility_notified_at/migration.sql new file mode 100644 index 0000000..350f800 --- /dev/null +++ b/prisma/migrations/20260303232956_add_award_eligibility_notified_at/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "AwardEligibility" ADD COLUMN "notifiedAt" TIMESTAMP(3); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 1feea7b..a5355c4 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1622,6 +1622,9 @@ model AwardEligibility { confirmedAt DateTime? confirmedBy String? + // Pool notification tracking + notifiedAt DateTime? + createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/src/server/routers/specialAward.ts b/src/server/routers/specialAward.ts index d1816cb..5558d9a 100644 --- a/src/server/routers/specialAward.ts +++ b/src/server/routers/specialAward.ts @@ -1269,9 +1269,9 @@ export const specialAwardRouter = router({ select: { id: true, name: true, description: true, status: true }, }) - // Get eligible projects with submitter + team members + // Get eligible projects that haven't been notified yet const eligibilities = await ctx.prisma.awardEligibility.findMany({ - where: { awardId: input.awardId, eligible: true }, + where: { awardId: input.awardId, eligible: true, notifiedAt: null }, select: { id: true, projectId: true, @@ -1365,6 +1365,15 @@ export const specialAwardRouter = router({ } } + // Stamp notifiedAt on all processed eligibilities to prevent re-notification + const notifiedIds = eligibilities.map((e) => e.id) + if (notifiedIds.length > 0) { + await ctx.prisma.awardEligibility.updateMany({ + where: { id: { in: notifiedIds } }, + data: { notifiedAt: new Date() }, + }) + } + await logAudit({ prisma: ctx.prisma, userId: ctx.user.id,