mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-06 05:40:02 -06:00
fix: Weekly summary endpoint failing (#1440)
Co-authored-by: Johannes <johannes@formbricks.com>
This commit is contained in:
committed by
GitHub
parent
61c7d78612
commit
1582ac13da
@@ -6,122 +6,78 @@ import { NextResponse } from "next/server";
|
||||
import { sendNoLiveSurveyNotificationEmail, sendWeeklySummaryNotificationEmail } from "./email";
|
||||
import { EnvironmentData, NotificationResponse, ProductData, Survey, SurveyResponse } from "./types";
|
||||
|
||||
const BATCH_SIZE = 10;
|
||||
|
||||
export async function POST(): Promise<NextResponse> {
|
||||
// check authentication with x-api-key header and CRON_SECRET env variable
|
||||
// Check authentication
|
||||
if (headers().get("x-api-key") !== CRON_SECRET) {
|
||||
return responses.notAuthenticatedResponse();
|
||||
}
|
||||
|
||||
// list of email sending promises to wait for
|
||||
const emailSendingPromises: Promise<void>[] = [];
|
||||
|
||||
const products = await getProducts();
|
||||
// Fetch all team IDs
|
||||
const teamIds = await getTeamIds();
|
||||
|
||||
// iterate through the products and send weekly summary email to each team member
|
||||
for await (const product of products) {
|
||||
// check if there are team members that have weekly summary notification enabled
|
||||
const teamMembers = product.team.memberships;
|
||||
const teamMembersWithNotificationEnabled = teamMembers.filter((member) => {
|
||||
return (
|
||||
member.user.notificationSettings?.weeklySummary &&
|
||||
member.user.notificationSettings.weeklySummary[product.id]
|
||||
);
|
||||
});
|
||||
// if there are no team members with weekly summary notification enabled, skip to the next product (do not send email)
|
||||
if (teamMembersWithNotificationEnabled.length == 0) {
|
||||
continue;
|
||||
}
|
||||
// calculate insights for the product
|
||||
const notificationResponse = getNotificationResponse(product.environments[0], product.name);
|
||||
// Paginate through teams
|
||||
for (let i = 0; i < teamIds.length; i += BATCH_SIZE) {
|
||||
const batchedTeamIds = teamIds.slice(i, i + BATCH_SIZE);
|
||||
// Fetch products for batched teams asynchronously
|
||||
const batchedProductsPromises = batchedTeamIds.map((teamId) => getProductsByTeamId(teamId));
|
||||
|
||||
// if there were no responses in the last 7 days, send a different email
|
||||
if (notificationResponse.insights.numLiveSurvey == 0) {
|
||||
for (const teamMember of teamMembersWithNotificationEnabled) {
|
||||
emailSendingPromises.push(
|
||||
sendNoLiveSurveyNotificationEmail(teamMember.user.email, notificationResponse)
|
||||
const batchedProducts = await Promise.all(batchedProductsPromises);
|
||||
for (const products of batchedProducts) {
|
||||
for (const product of products) {
|
||||
const teamMembers = product.team.memberships;
|
||||
const teamMembersWithNotificationEnabled = teamMembers.filter(
|
||||
(member) =>
|
||||
member.user.notificationSettings?.weeklySummary &&
|
||||
member.user.notificationSettings.weeklySummary[product.id]
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// send weekly summary email
|
||||
for (const teamMember of teamMembersWithNotificationEnabled) {
|
||||
emailSendingPromises.push(
|
||||
sendWeeklySummaryNotificationEmail(teamMember.user.email, notificationResponse)
|
||||
);
|
||||
if (teamMembersWithNotificationEnabled.length === 0) continue;
|
||||
|
||||
const notificationResponse = getNotificationResponse(product.environments[0], product.name);
|
||||
|
||||
if (notificationResponse.insights.numLiveSurvey === 0) {
|
||||
for (const teamMember of teamMembersWithNotificationEnabled) {
|
||||
emailSendingPromises.push(
|
||||
sendNoLiveSurveyNotificationEmail(teamMember.user.email, notificationResponse)
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const teamMember of teamMembersWithNotificationEnabled) {
|
||||
emailSendingPromises.push(
|
||||
sendWeeklySummaryNotificationEmail(teamMember.user.email, notificationResponse)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// wait for all emails to be sent
|
||||
|
||||
await Promise.all(emailSendingPromises);
|
||||
return responses.successResponse({}, true);
|
||||
}
|
||||
|
||||
const getNotificationResponse = (environment: EnvironmentData, productName: string): NotificationResponse => {
|
||||
const insights = {
|
||||
totalCompletedResponses: 0,
|
||||
totalDisplays: 0,
|
||||
totalResponses: 0,
|
||||
completionRate: 0,
|
||||
numLiveSurvey: 0,
|
||||
};
|
||||
|
||||
const surveys: Survey[] = [];
|
||||
|
||||
// iterate through the surveys and calculate the overall insights
|
||||
for (const survey of environment.surveys) {
|
||||
const surveyData: Survey = {
|
||||
id: survey.id,
|
||||
name: survey.name,
|
||||
status: survey.status,
|
||||
responseCount: survey.responses.length,
|
||||
responses: [],
|
||||
};
|
||||
// iterate through the responses and calculate the survey insights
|
||||
for (const response of survey.responses) {
|
||||
// only take the first 3 responses
|
||||
if (surveyData.responses.length >= 1) {
|
||||
break;
|
||||
}
|
||||
const surveyResponse: SurveyResponse = {};
|
||||
for (const question of survey.questions) {
|
||||
const headline = question.headline;
|
||||
const answer = response.data[question.id]?.toString() || null;
|
||||
if (answer === null || answer === "" || answer?.length === 0) {
|
||||
continue;
|
||||
}
|
||||
surveyResponse[headline] = answer;
|
||||
}
|
||||
surveyData.responses.push(surveyResponse);
|
||||
}
|
||||
surveys.push(surveyData);
|
||||
// calculate the overall insights
|
||||
if (survey.status == "inProgress") {
|
||||
insights.numLiveSurvey += 1;
|
||||
}
|
||||
insights.totalCompletedResponses += survey.responses.filter((r) => r.finished).length;
|
||||
insights.totalDisplays += survey.displays.length;
|
||||
insights.totalResponses += survey.responses.length;
|
||||
insights.completionRate = Math.round((insights.totalCompletedResponses / insights.totalResponses) * 100);
|
||||
}
|
||||
// build the notification response needed for the emails
|
||||
const lastWeekDate = new Date();
|
||||
lastWeekDate.setDate(lastWeekDate.getDate() - 7);
|
||||
return {
|
||||
environmentId: environment.id,
|
||||
currentDate: new Date(),
|
||||
lastWeekDate,
|
||||
productName: productName,
|
||||
surveys,
|
||||
insights,
|
||||
};
|
||||
const getTeamIds = async (): Promise<string[]> => {
|
||||
const teams = await prisma.team.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
return teams.map((team) => team.id);
|
||||
};
|
||||
|
||||
const getProducts = async (): Promise<ProductData[]> => {
|
||||
// gets all products together with team members, surveys, responses, and displays for the last 7 days
|
||||
const getProductsByTeamId = async (teamId: string): Promise<ProductData[]> => {
|
||||
const sevenDaysAgo = new Date();
|
||||
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
|
||||
|
||||
return await prisma.product.findMany({
|
||||
where: {
|
||||
teamId: teamId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
@@ -204,3 +160,63 @@ const getProducts = async (): Promise<ProductData[]> => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const getNotificationResponse = (environment: EnvironmentData, productName: string): NotificationResponse => {
|
||||
const insights = {
|
||||
totalCompletedResponses: 0,
|
||||
totalDisplays: 0,
|
||||
totalResponses: 0,
|
||||
completionRate: 0,
|
||||
numLiveSurvey: 0,
|
||||
};
|
||||
|
||||
const surveys: Survey[] = [];
|
||||
|
||||
// iterate through the surveys and calculate the overall insights
|
||||
for (const survey of environment.surveys) {
|
||||
const surveyData: Survey = {
|
||||
id: survey.id,
|
||||
name: survey.name,
|
||||
status: survey.status,
|
||||
responseCount: survey.responses.length,
|
||||
responses: [],
|
||||
};
|
||||
// iterate through the responses and calculate the survey insights
|
||||
for (const response of survey.responses) {
|
||||
// only take the first 3 responses
|
||||
if (surveyData.responses.length >= 1) {
|
||||
break;
|
||||
}
|
||||
const surveyResponse: SurveyResponse = {};
|
||||
for (const question of survey.questions) {
|
||||
const headline = question.headline;
|
||||
const answer = response.data[question.id]?.toString() || null;
|
||||
if (answer === null || answer === "" || answer?.length === 0) {
|
||||
continue;
|
||||
}
|
||||
surveyResponse[headline] = answer;
|
||||
}
|
||||
surveyData.responses.push(surveyResponse);
|
||||
}
|
||||
surveys.push(surveyData);
|
||||
// calculate the overall insights
|
||||
if (survey.status == "inProgress") {
|
||||
insights.numLiveSurvey += 1;
|
||||
}
|
||||
insights.totalCompletedResponses += survey.responses.filter((r) => r.finished).length;
|
||||
insights.totalDisplays += survey.displays.length;
|
||||
insights.totalResponses += survey.responses.length;
|
||||
insights.completionRate = Math.round((insights.totalCompletedResponses / insights.totalResponses) * 100);
|
||||
}
|
||||
// build the notification response needed for the emails
|
||||
const lastWeekDate = new Date();
|
||||
lastWeekDate.setDate(lastWeekDate.getDate() - 7);
|
||||
return {
|
||||
environmentId: environment.id,
|
||||
currentDate: new Date(),
|
||||
lastWeekDate,
|
||||
productName: productName,
|
||||
surveys,
|
||||
insights,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user