Date: Wed, 5 Nov 2025 16:35:44 -0500
Subject: [PATCH 09/13] Update campaign-email.tsx
---
packages/email/src/templates/campaign-email.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/email/src/templates/campaign-email.tsx b/packages/email/src/templates/campaign-email.tsx
index 9ec9eaaea00..5fb1e5e42e5 100644
--- a/packages/email/src/templates/campaign-email.tsx
+++ b/packages/email/src/templates/campaign-email.tsx
@@ -23,7 +23,7 @@ export default function CampaignEmail({
campaign = {
type: "marketing",
preview: "Test Preview",
- body: `Hi {{PartnerName}},
Thrilled to have you officially join the Acme Ambassador Program!
As a Acme Ambassador, you're joining the front line of change. You're freeing people from broken healthcare and giving them back control of their health.
Your 3 quick steps to get started:
Activate your membership with your 50% off code: ACME50OFF
Open your dashboard and copy your referral link
Share Acme with your loved ones! Use our Ambassador Hub for all the information you need like message templates, images, and information about Acme.
And a bonus: make your first referral within 7 days and you'll also receive a limited-edition Acme hoodie.

We're here with you every step of the way.
To your health,
The Acme team
`,
+ body: `Hi {{PartnerName}},
Thrilled to have you officially join the Acme Ambassador Program!
As a Acme Ambassador, you're joining the front line of change. You're freeing people from broken healthcare and giving them back control of their health.
Your 3 quick steps to get started:
Activate your membership with your 50% off code: ACME50OFF
Open your dashboard and copy your referral link
Share Acme with your loved ones! Use our Ambassador Hub for all the information you need like message templates, images, and information about Acme.
And a bonus: make your first referral within 7 days and you'll also receive a limited-edition Acme hoodie.

We're here with you every step of the way.
To your health,
The Acme team
`,
},
}: {
program?: {
From dafcc715a529a95d04213ad9101b76379525f17f Mon Sep 17 00:00:00 2001
From: Tim Wilson
Date: Wed, 5 Nov 2025 16:36:16 -0500
Subject: [PATCH 10/13] Update campaign-email.tsx
---
packages/email/src/templates/campaign-email.tsx | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/packages/email/src/templates/campaign-email.tsx b/packages/email/src/templates/campaign-email.tsx
index 5fb1e5e42e5..5aa632b745e 100644
--- a/packages/email/src/templates/campaign-email.tsx
+++ b/packages/email/src/templates/campaign-email.tsx
@@ -75,10 +75,7 @@ export default function CampaignEmail({
{program?.messagingEnabledAt &&
From d94c418b8a0e163a2e5c8e54dedc51adcb82ceed Mon Sep 17 00:00:00 2001
From: Tim Wilson
Date: Wed, 5 Nov 2025 16:45:40 -0500
Subject: [PATCH 11/13] Update campaigns.ts
---
apps/web/lib/zod/schemas/campaigns.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/web/lib/zod/schemas/campaigns.ts b/apps/web/lib/zod/schemas/campaigns.ts
index c21c705d5bf..b4bc8c694f5 100644
--- a/apps/web/lib/zod/schemas/campaigns.ts
+++ b/apps/web/lib/zod/schemas/campaigns.ts
@@ -50,7 +50,7 @@ export const CampaignSchema = z.object({
id: z.string(),
name: z.string(),
subject: z.string(),
- preview: z.string().nullable().default(null),
+ preview: z.string().nullish(),
from: z.string().nullable(),
bodyJson: z.record(z.string(), z.any()),
type: z.nativeEnum(CampaignType),
From 7e66ad140c1f76dccae5f005ec64b3eb266573ca Mon Sep 17 00:00:00 2001
From: Tim Wilson
Date: Wed, 5 Nov 2025 16:46:04 -0500
Subject: [PATCH 12/13] Update campaigns.ts
---
apps/web/lib/zod/schemas/campaigns.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/web/lib/zod/schemas/campaigns.ts b/apps/web/lib/zod/schemas/campaigns.ts
index b4bc8c694f5..d2c0f86835a 100644
--- a/apps/web/lib/zod/schemas/campaigns.ts
+++ b/apps/web/lib/zod/schemas/campaigns.ts
@@ -50,7 +50,7 @@ export const CampaignSchema = z.object({
id: z.string(),
name: z.string(),
subject: z.string(),
- preview: z.string().nullish(),
+ preview: z.string().nullable().default(null),
from: z.string().nullable(),
bodyJson: z.record(z.string(), z.any()),
type: z.nativeEnum(CampaignType),
@@ -85,7 +85,7 @@ export const updateCampaignSchema = z
.string()
.trim()
.max(100, "Subject must be less than 100 characters."),
- preview: z.string().nullable().default(null),
+ preview: z.string().nullish(),
from: z.string().email().trim().toLowerCase(),
bodyJson: z.record(z.string(), z.any()),
triggerCondition: workflowConditionSchema.nullish(),
From 938af45d20a714add9aea20d4e9cfdfad116ec45 Mon Sep 17 00:00:00 2001
From: Steven Tey
Date: Wed, 5 Nov 2025 14:22:11 -0800
Subject: [PATCH 13/13] update schema to db.Text, fix test
---
apps/web/scripts/perplexity/ban-partners.ts | 9 +++++++--
apps/web/tests/campaigns/index.test.ts | 1 +
packages/prisma/schema/campaign.prisma | 2 +-
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/apps/web/scripts/perplexity/ban-partners.ts b/apps/web/scripts/perplexity/ban-partners.ts
index e18d6e69848..0a7672a9ace 100644
--- a/apps/web/scripts/perplexity/ban-partners.ts
+++ b/apps/web/scripts/perplexity/ban-partners.ts
@@ -1,4 +1,3 @@
-import { syncTotalCommissions } from "@/lib/api/partners/sync-total-commissions";
import { BAN_PARTNER_REASONS } from "@/lib/zod/schemas/partners";
import PartnerBanned from "@dub/email/templates/partner-banned";
import { prisma } from "@dub/prisma";
@@ -6,6 +5,7 @@ import "dotenv-flow/config";
import * as fs from "fs";
import * as Papa from "papaparse";
import { linkCache } from "../../lib/api/links/cache";
+import { syncTotalCommissions } from "../../lib/api/partners/sync-total-commissions";
import { queueBatchEmail } from "../../lib/email/queue-batch-email";
let partnersToBan: string[] = [];
@@ -38,12 +38,15 @@ async function main() {
partnerId: {
in: partnersToBan,
},
+ status: {
+ not: "banned",
+ },
},
include: {
links: true,
partner: true,
},
- take: 100,
+ take: 200,
});
if (programEnrollments.length === 0) {
@@ -127,6 +130,8 @@ async function main() {
),
);
+ console.log("commissionsRes", commissionsRes);
+
const qstashRes = await queueBatchEmail(
programEnrollments
.filter((p) => p.partner.email)
diff --git a/apps/web/tests/campaigns/index.test.ts b/apps/web/tests/campaigns/index.test.ts
index 226f0685586..1a668d668cc 100644
--- a/apps/web/tests/campaigns/index.test.ts
+++ b/apps/web/tests/campaigns/index.test.ts
@@ -33,6 +33,7 @@ const expectedCampaign: Partial = {
...campaign,
type: "transactional",
status: expect.any(String),
+ preview: null,
from: null,
scheduledAt: null,
groups: [{ id: E2E_PARTNER_GROUP.id }],
diff --git a/packages/prisma/schema/campaign.prisma b/packages/prisma/schema/campaign.prisma
index a67441e0e52..32e5ad7988d 100644
--- a/packages/prisma/schema/campaign.prisma
+++ b/packages/prisma/schema/campaign.prisma
@@ -27,7 +27,7 @@ model Campaign {
status CampaignStatus @default(draft)
name String
subject String
- preview String?
+ preview String? @db.Text
from String?
bodyJson Json @db.Json
scheduledAt DateTime?