chore: format
This commit is contained in:
@@ -1,59 +1,59 @@
|
||||
import { z } from "zod"
|
||||
import { authProcedure } from "../trpc"
|
||||
import { prisma } from "../utils/prisma"
|
||||
import { TRPCError } from "@trpc/server"
|
||||
import { MessageStatus } from "../../prisma/client"
|
||||
import { z } from "zod";
|
||||
import { authProcedure } from "../trpc";
|
||||
import { prisma } from "../utils/prisma";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { MessageStatus } from "../../prisma/client";
|
||||
|
||||
export const resendMessage = authProcedure
|
||||
.input(
|
||||
z.object({
|
||||
messageId: z.string(),
|
||||
organizationId: z.string(),
|
||||
})
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const userOrganization = await prisma.userOrganization.findFirst({
|
||||
where: {
|
||||
userId: ctx.user.id,
|
||||
organizationId: input.organizationId,
|
||||
},
|
||||
})
|
||||
.input(
|
||||
z.object({
|
||||
messageId: z.string(),
|
||||
organizationId: z.string(),
|
||||
}),
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const userOrganization = await prisma.userOrganization.findFirst({
|
||||
where: {
|
||||
userId: ctx.user.id,
|
||||
organizationId: input.organizationId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!userOrganization) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You do not have access to this organization.",
|
||||
})
|
||||
}
|
||||
if (!userOrganization) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You do not have access to this organization.",
|
||||
});
|
||||
}
|
||||
|
||||
const message = await prisma.message.findFirst({
|
||||
where: {
|
||||
id: input.messageId,
|
||||
Campaign: {
|
||||
organizationId: input.organizationId,
|
||||
},
|
||||
},
|
||||
})
|
||||
const message = await prisma.message.findFirst({
|
||||
where: {
|
||||
id: input.messageId,
|
||||
Campaign: {
|
||||
organizationId: input.organizationId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!message) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Message not found or you don't have access.",
|
||||
})
|
||||
}
|
||||
if (!message) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Message not found or you don't have access.",
|
||||
});
|
||||
}
|
||||
|
||||
const updatedMessage = await prisma.message.update({
|
||||
where: {
|
||||
id: input.messageId,
|
||||
},
|
||||
data: {
|
||||
status: MessageStatus.QUEUED,
|
||||
tries: 0,
|
||||
lastTriedAt: null,
|
||||
error: null,
|
||||
messageId: null,
|
||||
},
|
||||
})
|
||||
const updatedMessage = await prisma.message.update({
|
||||
where: {
|
||||
id: input.messageId,
|
||||
},
|
||||
data: {
|
||||
status: MessageStatus.QUEUED,
|
||||
tries: 0,
|
||||
lastTriedAt: null,
|
||||
error: null,
|
||||
messageId: null,
|
||||
},
|
||||
});
|
||||
|
||||
return updatedMessage
|
||||
})
|
||||
return updatedMessage;
|
||||
});
|
||||
|
||||
@@ -1,159 +1,159 @@
|
||||
import { z } from "zod"
|
||||
import { authProcedure } from "../trpc"
|
||||
import { prisma } from "../utils/prisma"
|
||||
import { TRPCError } from "@trpc/server"
|
||||
import { paginationSchema } from "../utils/schemas"
|
||||
import { Prisma } from "../../prisma/client"
|
||||
import { z } from "zod";
|
||||
import { authProcedure } from "../trpc";
|
||||
import { prisma } from "../utils/prisma";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { paginationSchema } from "../utils/schemas";
|
||||
import { Prisma } from "../../prisma/client";
|
||||
|
||||
const messageStatusEnum = z.enum([
|
||||
"QUEUED",
|
||||
"PENDING",
|
||||
"SENT",
|
||||
"OPENED",
|
||||
"CLICKED",
|
||||
"FAILED",
|
||||
"RETRYING",
|
||||
])
|
||||
"QUEUED",
|
||||
"PENDING",
|
||||
"SENT",
|
||||
"OPENED",
|
||||
"CLICKED",
|
||||
"FAILED",
|
||||
"RETRYING",
|
||||
]);
|
||||
|
||||
export const listMessages = authProcedure
|
||||
.input(
|
||||
z
|
||||
.object({
|
||||
organizationId: z.string(),
|
||||
campaignId: z.string().optional(),
|
||||
subscriberId: z.string().optional(),
|
||||
status: messageStatusEnum.optional(),
|
||||
})
|
||||
.merge(paginationSchema)
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const userOrganization = await prisma.userOrganization.findFirst({
|
||||
where: {
|
||||
userId: ctx.user.id,
|
||||
organizationId: input.organizationId,
|
||||
},
|
||||
})
|
||||
.input(
|
||||
z
|
||||
.object({
|
||||
organizationId: z.string(),
|
||||
campaignId: z.string().optional(),
|
||||
subscriberId: z.string().optional(),
|
||||
status: messageStatusEnum.optional(),
|
||||
})
|
||||
.merge(paginationSchema),
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const userOrganization = await prisma.userOrganization.findFirst({
|
||||
where: {
|
||||
userId: ctx.user.id,
|
||||
organizationId: input.organizationId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!userOrganization) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "Organization not found",
|
||||
})
|
||||
}
|
||||
if (!userOrganization) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "Organization not found",
|
||||
});
|
||||
}
|
||||
|
||||
const where: Prisma.MessageWhereInput = {
|
||||
Campaign: {
|
||||
organizationId: input.organizationId,
|
||||
},
|
||||
...(input.campaignId ? { campaignId: input.campaignId } : {}),
|
||||
...(input.subscriberId ? { subscriberId: input.subscriberId } : {}),
|
||||
...(input.status ? { status: input.status } : {}),
|
||||
...(input.search
|
||||
? {
|
||||
OR: [
|
||||
{
|
||||
Subscriber: {
|
||||
name: {
|
||||
contains: input.search,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Subscriber: {
|
||||
email: {
|
||||
contains: input.search,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Campaign: {
|
||||
title: {
|
||||
contains: input.search,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
: {}),
|
||||
}
|
||||
const where: Prisma.MessageWhereInput = {
|
||||
Campaign: {
|
||||
organizationId: input.organizationId,
|
||||
},
|
||||
...(input.campaignId ? { campaignId: input.campaignId } : {}),
|
||||
...(input.subscriberId ? { subscriberId: input.subscriberId } : {}),
|
||||
...(input.status ? { status: input.status } : {}),
|
||||
...(input.search
|
||||
? {
|
||||
OR: [
|
||||
{
|
||||
Subscriber: {
|
||||
name: {
|
||||
contains: input.search,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Subscriber: {
|
||||
email: {
|
||||
contains: input.search,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Campaign: {
|
||||
title: {
|
||||
contains: input.search,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
const [total, messages] = await Promise.all([
|
||||
prisma.message.count({ where }),
|
||||
prisma.message.findMany({
|
||||
where,
|
||||
orderBy: [{ updatedAt: "desc" }, { id: "desc" }],
|
||||
skip: (input.page - 1) * input.perPage,
|
||||
take: input.perPage,
|
||||
include: {
|
||||
Campaign: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
},
|
||||
},
|
||||
Subscriber: {
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
])
|
||||
const [total, messages] = await Promise.all([
|
||||
prisma.message.count({ where }),
|
||||
prisma.message.findMany({
|
||||
where,
|
||||
orderBy: [{ updatedAt: "desc" }, { id: "desc" }],
|
||||
skip: (input.page - 1) * input.perPage,
|
||||
take: input.perPage,
|
||||
include: {
|
||||
Campaign: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
},
|
||||
},
|
||||
Subscriber: {
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
const totalPages = Math.ceil(total / input.perPage)
|
||||
const totalPages = Math.ceil(total / input.perPage);
|
||||
|
||||
return {
|
||||
messages,
|
||||
pagination: {
|
||||
total,
|
||||
totalPages,
|
||||
page: input.page,
|
||||
perPage: input.perPage,
|
||||
hasMore: input.page < totalPages,
|
||||
},
|
||||
}
|
||||
})
|
||||
return {
|
||||
messages,
|
||||
pagination: {
|
||||
total,
|
||||
totalPages,
|
||||
page: input.page,
|
||||
perPage: input.perPage,
|
||||
hasMore: input.page < totalPages,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const getMessage = authProcedure
|
||||
.input(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
})
|
||||
)
|
||||
.query(async ({ input }) => {
|
||||
const message = await prisma.message.findUnique({
|
||||
where: {
|
||||
id: input.id,
|
||||
},
|
||||
include: {
|
||||
Campaign: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
content: true,
|
||||
},
|
||||
},
|
||||
Subscriber: {
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
.input(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
}),
|
||||
)
|
||||
.query(async ({ input }) => {
|
||||
const message = await prisma.message.findUnique({
|
||||
where: {
|
||||
id: input.id,
|
||||
},
|
||||
include: {
|
||||
Campaign: {
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
content: true,
|
||||
},
|
||||
},
|
||||
Subscriber: {
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!message) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Message not found",
|
||||
})
|
||||
}
|
||||
if (!message) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Message not found",
|
||||
});
|
||||
}
|
||||
|
||||
return message
|
||||
})
|
||||
return message;
|
||||
});
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { router } from "../trpc"
|
||||
import { listMessages, getMessage } from "./query"
|
||||
import { resendMessage } from "./mutation"
|
||||
import { router } from "../trpc";
|
||||
import { listMessages, getMessage } from "./query";
|
||||
import { resendMessage } from "./mutation";
|
||||
|
||||
export const messageRouter = router({
|
||||
list: listMessages,
|
||||
get: getMessage,
|
||||
resend: resendMessage,
|
||||
})
|
||||
list: listMessages,
|
||||
get: getMessage,
|
||||
resend: resendMessage,
|
||||
});
|
||||
|
||||
@@ -1,84 +1,84 @@
|
||||
import { prisma } from "../utils/prisma"
|
||||
import { MessageStatus } from "../../prisma/client"
|
||||
import { prisma } from "../utils/prisma";
|
||||
import { MessageStatus } from "../../prisma/client";
|
||||
|
||||
interface MessageQueryOptions {
|
||||
campaignId?: string
|
||||
organizationId: string
|
||||
status: MessageStatus | MessageStatus[]
|
||||
campaignId?: string;
|
||||
organizationId: string;
|
||||
status: MessageStatus | MessageStatus[];
|
||||
}
|
||||
|
||||
export async function findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status,
|
||||
campaignId,
|
||||
organizationId,
|
||||
status,
|
||||
}: MessageQueryOptions) {
|
||||
return prisma.message.findMany({
|
||||
where: {
|
||||
...(campaignId && { campaignId }),
|
||||
Campaign: {
|
||||
organizationId,
|
||||
},
|
||||
status: Array.isArray(status) ? { in: status } : status,
|
||||
},
|
||||
})
|
||||
return prisma.message.findMany({
|
||||
where: {
|
||||
...(campaignId && { campaignId }),
|
||||
Campaign: {
|
||||
organizationId,
|
||||
},
|
||||
status: Array.isArray(status) ? { in: status } : status,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
interface CampaignMessagesQueryOptions {
|
||||
campaignId: string
|
||||
organizationId: string
|
||||
campaignId: string;
|
||||
organizationId: string;
|
||||
}
|
||||
|
||||
export async function getDeliveredMessages({
|
||||
campaignId,
|
||||
organizationId,
|
||||
campaignId,
|
||||
organizationId,
|
||||
}: CampaignMessagesQueryOptions) {
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: ["SENT", "CLICKED", "OPENED"],
|
||||
})
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: ["SENT", "CLICKED", "OPENED"],
|
||||
});
|
||||
}
|
||||
|
||||
export async function getFailedMessages({
|
||||
campaignId,
|
||||
organizationId,
|
||||
campaignId,
|
||||
organizationId,
|
||||
}: CampaignMessagesQueryOptions) {
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: "FAILED",
|
||||
})
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: "FAILED",
|
||||
});
|
||||
}
|
||||
|
||||
export async function getOpenedMessages({
|
||||
campaignId,
|
||||
organizationId,
|
||||
campaignId,
|
||||
organizationId,
|
||||
}: CampaignMessagesQueryOptions) {
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: ["OPENED", "CLICKED"], // Clicked implies opened
|
||||
})
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: ["OPENED", "CLICKED"], // Clicked implies opened
|
||||
});
|
||||
}
|
||||
|
||||
export async function getClickedMessages({
|
||||
campaignId,
|
||||
organizationId,
|
||||
campaignId,
|
||||
organizationId,
|
||||
}: CampaignMessagesQueryOptions) {
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: "CLICKED",
|
||||
})
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: "CLICKED",
|
||||
});
|
||||
}
|
||||
|
||||
export async function getQueuedMessages({
|
||||
campaignId,
|
||||
organizationId,
|
||||
campaignId,
|
||||
organizationId,
|
||||
}: CampaignMessagesQueryOptions) {
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: "QUEUED",
|
||||
})
|
||||
return findMessagesByStatus({
|
||||
campaignId,
|
||||
organizationId,
|
||||
status: "QUEUED",
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user