Files
mwitnessing/pages/api/email.ts
2024-04-18 13:34:17 +03:00

344 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// API endpoint to process email user actions - urls we send in emails to users
import { getToken } from "next-auth/jwt";
import type { NextApiRequest, NextApiResponse } from 'next';
import { createRouter, expressWrapper } from "next-connect";
const common = require('../../src/helpers/common');
const data = require('../../src/helpers/data');
const emailHelper = require('../../src/helpers/email');
const { v4: uuidv4 } = require('uuid');
const CON = require("../../src/helpers/const");
import { EventLogType } from "@prisma/client";
import fs from 'fs';
import path from 'path';
const handlebars = require("handlebars");
const router = createRouter<NextApiRequest, NextApiResponse>();
//action to accept coverme request from email
/**
*
* @param req import { NextApiRequest, NextApiResponse } from 'next'
* @param res import { NextApiRequest, NextApiResponse } from 'next'
*/
export default async function handler(req, res) {
const prisma = common.getPrismaClient();
const action = req.query.action;
const emailaction = req.query.emailaction;
// Retrieve and validate the JWT token
//response is a special action that does not require a token
if (action == "email_response") {
switch (emailaction) {
case "coverMeAccept":
//validate shiftId and assignmentId
let shiftId = req.query.shiftId;
let userId = req.query.userId;
let publisher = await prisma.publisher.findUnique({
where: {
id: userId
}
});
// Update the user status to accepted
console.log("User: " + publisher.firstName + " " + publisher.lastName + " accepted the CoverMe request");
let assignmentPID = req.query.assignmentPID;
if (!shiftId) {
return res.status(400).json({ message: "Shift ID is not provided" });
}
if (!assignmentPID) {
return res.status(400).json({ message: "Assignment PID is not provided" });
}
//check if the assignment request is still open
const assignment = await prisma.assignment.findFirst({
where: {
publicGuid: assignmentPID,
shiftId: parseInt(shiftId),
isConfirmed: false
},
include: {
shift: {
include: {
cartEvent: {
include: {
location: true
}
},
assignments: {
include: {
publisher: true
// {
// include: {
// email: true,
// firstName: true,
// lastName: true
// }
// }
}
}
}
},
publisher: true
}
});
if (!assignment) {
const messagePageUrl = `/message?message=${encodeURIComponent('Благодаря за желанието, но някой е отговорил на тази заявка за заместване и тя вече е неактивна')}&type=info&caption=${encodeURIComponent('Някой вече те изпревари. Заявката е вече обработена')}`;
res.redirect(messagePageUrl);
return;
}
let to = assignment.shift.assignments.map(a => a.publisher.email);
to.push(publisher.email);
// update the assignment. clear the guid, isConfirmed to true
await prisma.assignment.update({
where: {
id: assignment.id
},
data: {
publisherId: userId,
publicGuid: null, // if this exists, we consider the request open
isConfirmed: true
}
});
const newAssignment = await prisma.assignment.findFirst({
where: {
shiftId: parseInt(shiftId),
isConfirmed: true
},
include: {
shift: {
include: {
cartEvent: {
include: {
location: true
}
},
assignments: {
include: {
publisher: true
}
}
}
}
}
});
await prisma.eventLog.create({
data: {
date: new Date(),
publisher: { connect: { id: publisher.id } },
shift: { connect: { id: assignment.shiftId } },
type: EventLogType.AssignmentReplacementAccepted,
content: "Заявка за заместване приета от " + publisher.firstName + " " + publisher.lastName
}
});
const shiftStr = `${CON.weekdaysBG[assignment.shift.startTime.getDay()]} ${CON.GetDateFormat(assignment.shift.startTime)} at ${assignment.shift.cartEvent.location.name} from ${CON.GetTimeFormat(assignment.shift.startTime)} to ${CON.GetTimeFormat(assignment.shift.endTime)}`;
const newPubs = newAssignment.shift.assignments.map(a => ({
name: `${a.publisher.firstName} ${a.publisher.lastName}`,
phone: a.publisher.phone
}));
let model = {
user: publisher,
shiftStr: shiftStr,
shiftId: assignment.shiftId,
prefix: publisher.isMale ? "Брат" : "Сестра",
oldPubName: assignment.publisher.firstName + " " + assignment.publisher.lastName,
firstName: publisher.firstName,
lastName: publisher.lastName,
newPubs: newPubs,
placeName: assignment.shift.cartEvent.location.name,
dateStr: common.getDateFormated(assignment.shift.startTime),
time: common.formatTimeHHmm(assignment.shift.startTime),
sentDate: common.getDateFormated(new Date())
};
emailHelper.SendEmailHandlebars(to, "coverMeAccepted", model);
const messagePageUrl = `/message?message=${encodeURIComponent('Вашата заявка за замстване е обработена успешно')}&type=info&caption=${encodeURIComponent('Благодаря!')}`;
res.redirect(messagePageUrl);
break;
//POST
case "send_report": //we can send report form in the emails to the user. process the POSTED data here
// Send report form to the user
//get from POST data: locationId, date, placementCount, videoCount, returnVisitInfoCount, conversationCount
let locationId = req.body.locationId;
let date = req.body.date;
let placementCount = req.body.placementCount;
let videoCount = req.body.videoCount;
let returnVisitInfoCount = req.body.returnVisitInfoCount;
let conversationCount = req.body.conversationCount;
console.log("User: " + user.email + " sent a report: " +
locationId + " " + date + " " +
placementCount + " " + videoCount + " " +
returnVisitInfoCount + " " + conversationCount);
//save the report in the database
await prisma.report.create({
data: {
userId: parseInt(userId),
locationId: parseInt(locationId),
date: date,
placementCount: parseInt(placementCount),
videoCount: parseInt(videoCount),
returnVisitInfoCount: parseInt(returnVisitInfoCount),
conversationCount: parseInt(conversationCount)
}
});
break;
}
// //send email response to the user
// const emailResponse = await common.sendEmail(user.email, "Email Action Processed",
// "Your email action was processed successfully");
}
else {
const token = await getToken({ req: req });
if (!token) {
// If no token or invalid token, return unauthorized status
return res.status(401).json({ message: "Unauthorized to call this API endpoint" });
}
const publisher = await prisma.publisher.findUnique({
where: {
email: token.email
}
});
switch (action) {
case "sendCoverMeRequestByEmail":
// Send CoverMe request to the users
//get from POST data: shiftId, assignmentId, date
//let shiftId = req.body.shiftId;
let assignmentId = req.body.assignmentId;
let toSubscribed = req.body.toSubscribed;
let toAvailable = req.body.toAvailable;
let assignment = await prisma.assignment.findUnique({
where: {
id: parseInt(assignmentId)
},
include: {
shift: {
include: {
cartEvent: {
include: {
location: true
}
}
}
}
}
});
console.log("User: " + publisher.email + " sent a 'CoverMe' request for his assignment " + assignmentId + " - " + assignment.shift.cartEvent.location.name + " " + assignment.shift.startTime.toISOString());
// update the assignment. generate new publicGuid, isConfirmed to false
let newPublicGuid = uuidv4();
await prisma.assignment.update({
where: {
id: parseInt(assignmentId)
},
data: {
publicGuid: newPublicGuid, // if this exists, we consider the request open
isConfirmed: false
}
});
let subscribedPublishers = [], availablePublishers = [];
if (toSubscribed) {
//get all subscribed publisers
subscribedPublishers = await prisma.publisher.findMany({
where: {
isSubscribedToCoverMe: true
}
});
}
if (toAvailable) {
availablePublishers = await data.filterPublishersNew("id,firstName,lastName,email", new Date(assignment.shift.startTime), true, false);
}
//concat and remove duplicate emails
let pubsToSend = subscribedPublishers.concat(availablePublishers).
filter((item, index, self) =>
index === self.findIndex((t) => (
t.email === item.email //and exclude the user himself
)) //&& item.email !== publisher.email
);
console.log("Sending CoverMe request to " + pubsToSend.length + " publishers");
await prisma.eventLog.create({
data: {
date: new Date(),
publisher: { connect: { id: publisher.id } },
shift: { connect: { id: assignment.shiftId } },
type: EventLogType.AssignmentReplacementRequested,
content: "Заявка за заместване от " + publisher.firstName + " " + publisher.lastName
+ "до: " + pubsToSend.map(p => p.firstName + " " + p.lastName + "<" + p.email + ">").join(", "),
}
});
//send email to all subscribed publishers
for (let i = 0; i < pubsToSend.length; i++) {
//send email to subscribed publisher
let acceptUrl = process.env.NEXTAUTH_URL + "/api/email?action=email_response&emailaction=coverMeAccept&userId=" + pubsToSend[i].id + "&shiftId=" + assignment.shiftId + "&assignmentPID=" + newPublicGuid;
let model = {
user: publisher,
shiftId: assignment.shiftId,
acceptUrl: acceptUrl,
prefix: publisher.isMale ? "Брат" : "Сестра",
firstName: pubsToSend[i].firstName,
lastName: pubsToSend[i].lastName,
email: pubsToSend[i].email,
placeName: assignment.shift.cartEvent.location.name,
dateStr: common.getDateFormated(assignment.shift.startTime),
time: common.formatTimeHHmm(assignment.shift.startTime),
sentDate: common.getDateFormated(new Date())
};
let results = emailHelper.SendEmailHandlebars(
{
name: pubsToSend[i].firstName + " " + pubsToSend[i].lastName,
email: pubsToSend[i].email
}, "coverMe", model);
// if (results) {
// console.log("Error sending email: " + error);
// return res.status(500).json({ message: "Error sending email:" + error });
//}
if (results) {
console.log("Email sent to: " + pubsToSend[i].email);
}
}
res.status(200).json({ message: "CoverMe request sent" });
break;
default:
return res.status(400).json({ message: "Invalid action" });
}
return res.status(200).json({ message: "User action processed" });
}
}
router.use(expressWrapper(handler));