add export contact book option (#318)
This commit is contained in:
@@ -129,7 +129,7 @@ export const contactsRouter = createTRPCRouter({
|
||||
subscribed: z.boolean().optional(),
|
||||
}),
|
||||
)
|
||||
.max(10000),
|
||||
.max(50000),
|
||||
}),
|
||||
)
|
||||
.mutation(async ({ ctx: { contactBook, team }, input }) => {
|
||||
@@ -161,4 +161,47 @@ export const contactsRouter = createTRPCRouter({
|
||||
.mutation(async ({ input }) => {
|
||||
return contactService.deleteContact(input.contactId);
|
||||
}),
|
||||
|
||||
exportContacts: contactBookProcedure
|
||||
.input(
|
||||
z.object({
|
||||
subscribed: z.boolean().optional(),
|
||||
search: z.string().optional(),
|
||||
}),
|
||||
)
|
||||
.query(async ({ ctx: { db }, input }) => {
|
||||
const whereConditions: Prisma.ContactFindManyArgs["where"] = {
|
||||
contactBookId: input.contactBookId,
|
||||
...(input.subscribed !== undefined
|
||||
? { subscribed: input.subscribed }
|
||||
: {}),
|
||||
...(input.search
|
||||
? {
|
||||
OR: [
|
||||
{ email: { contains: input.search, mode: "insensitive" } },
|
||||
{ firstName: { contains: input.search, mode: "insensitive" } },
|
||||
{ lastName: { contains: input.search, mode: "insensitive" } },
|
||||
],
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
const contacts = await db.contact.findMany({
|
||||
where: whereConditions,
|
||||
select: {
|
||||
email: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
subscribed: true,
|
||||
unsubscribeReason: true,
|
||||
createdAt: true,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
},
|
||||
take: 100000, // Limit to 100k contacts to prevent memory issues
|
||||
});
|
||||
|
||||
return contacts;
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -11,8 +11,32 @@ export type ContactInput = {
|
||||
|
||||
export async function addOrUpdateContact(
|
||||
contactBookId: string,
|
||||
contact: ContactInput
|
||||
contact: ContactInput,
|
||||
) {
|
||||
// Check if contact exists to handle subscribed logic
|
||||
const existingContact = await db.contact.findUnique({
|
||||
where: {
|
||||
contactBookId_email: {
|
||||
contactBookId,
|
||||
email: contact.email,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
subscribed: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Determine subscribed value for update
|
||||
// Only allow Yes→No transitions (allow unsubscribe, prevent re-subscribe)
|
||||
let subscribedValue: boolean | undefined = contact.subscribed;
|
||||
if (existingContact && contact.subscribed !== undefined) {
|
||||
// Block No→Yes (prevent re-subscribe via CSV), allow all other transitions
|
||||
if (!existingContact.subscribed && contact.subscribed) {
|
||||
subscribedValue = undefined; // Block re-subscribe
|
||||
}
|
||||
// All other cases (Yes→No, Yes→Yes, No→No) are allowed naturally
|
||||
}
|
||||
|
||||
const createdContact = await db.contact.upsert({
|
||||
where: {
|
||||
contactBookId_email: {
|
||||
@@ -26,13 +50,13 @@ export async function addOrUpdateContact(
|
||||
firstName: contact.firstName,
|
||||
lastName: contact.lastName,
|
||||
properties: contact.properties ?? {},
|
||||
subscribed: contact.subscribed,
|
||||
subscribed: contact.subscribed ?? true, // Default to subscribed for new contacts
|
||||
},
|
||||
update: {
|
||||
firstName: contact.firstName,
|
||||
lastName: contact.lastName,
|
||||
properties: contact.properties ?? {},
|
||||
subscribed: contact.subscribed,
|
||||
...(subscribedValue !== undefined ? { subscribed: subscribedValue } : {}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -41,7 +65,7 @@ export async function addOrUpdateContact(
|
||||
|
||||
export async function updateContact(
|
||||
contactId: string,
|
||||
contact: Partial<ContactInput>
|
||||
contact: Partial<ContactInput>,
|
||||
) {
|
||||
return db.contact.update({
|
||||
where: {
|
||||
@@ -62,7 +86,7 @@ export async function deleteContact(contactId: string) {
|
||||
export async function bulkAddContacts(
|
||||
contactBookId: string,
|
||||
contacts: Array<ContactInput>,
|
||||
teamId?: number
|
||||
teamId?: number,
|
||||
) {
|
||||
await ContactQueueService.addBulkContactJobs(contactBookId, contacts, teamId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user