Added User and Trainer Moved and Cancelled email notifications
continuous-integration/drone/push Build is passing Details

main
Filip Borum Poulsen 3 years ago
parent 7b14a3c378
commit bb974a1df9

@ -4,5 +4,6 @@ interface Trainer {
last_name: string
center_id: number
center_name: string
email?: string
}
export default Trainer;

@ -0,0 +1,34 @@
import { transporter } from ".";
import { smtpAddress } from "../environment";
import { Order } from "../interfaces/order";
import User from "../interfaces/user";
import { formatDate, formatTime } from "../utils/dates";
export async function sendTrainerCancelledOrderEmail(user: User, order: Order) {
await transporter.sendMail({
from: `Fitness World <${smtpAddress}>`,
to: user.email,
subject: "Tid aflyst - Fitness World",
text:
`Hej, ${user.first_name} ${user.last_name}.
Vi er desværre blevet nødt til at aflyse din tid ved ${order.trainer.first_name} ${order.trainer.last_name} i ${order.trainer.center_name} ${formatDate(order.startDate)} ${formatTime(order.startDate)} - ${formatTime(order.endDate)}
Du kan altid gå ind og bestille en ny.
Vi håber at se dig en anden dag.
Venlig hilsen Fitness World.`
})
await transporter.sendMail({
from: `Fitness World <${smtpAddress}>`,
to: order.trainer.email,
subject: "Tid aflyst - Fitness World",
text:
`Hej, ${order.trainer.first_name} ${order.trainer.last_name}.
Du har aflyst en tid med ${user.first_name} ${user.last_name} i ${order.trainer.center_name} ${formatDate(order.startDate)} ${formatTime(order.startDate)} - ${formatTime(order.endDate)}
Venlig hilsen Fitness World.`
})
}

@ -0,0 +1,43 @@
import { Dayjs } from "dayjs";
import { transporter } from ".";
import { smtpAddress } from "../environment";
import { Order, OrderObject } from "../interfaces/order";
import User from "../interfaces/user";
import { formatDate, formatTime } from "../utils/dates";
export async function sendTrainerMovedOrderEmail(user: User, order: Order, oldStartDate: Date | Dayjs, oldEndDate: Date | Dayjs) {
await transporter.sendMail({
from: `Fitness World <${smtpAddress}>`,
to: user.email,
subject: "Ordre flyttet - Fitness World",
text:
`Hej, ${user.first_name} ${user.last_name}.
Vi er desværre blevet nødt til at flytte din tid ved ${order.trainer.first_name} ${order.trainer.last_name} i ${order.trainer.center_name}
Fra: ${formatDate(oldStartDate)} ${formatTime(oldStartDate)} - ${formatTime(oldEndDate)}
Til: ${formatDate(order.startDate)} ${formatTime(order.startDate)} - ${formatTime(order.endDate)}
Vi håber at tiden passer, ellers er du velkommen til selv at foreslå en ny dato.
Venlig hilsen Fitness World.`
})
await transporter.sendMail({
from: `Fitness World <${smtpAddress}>`,
to: order.trainer.email,
subject: "Ordre flyttet - Fitness World",
text:
`Hej, ${order.trainer.first_name} ${order.trainer.last_name}.
Du har flyttet en tid med ${user.first_name} ${user.last_name} i ${order.trainer.center_name}
Fra: ${formatDate(oldStartDate)} ${formatTime(oldStartDate)} - ${formatTime(oldEndDate)}
Til: ${formatDate(order.startDate)} ${formatTime(order.startDate)} - ${formatTime(order.endDate)}
Venlig hilsen Fitness World.`
})
}

@ -16,6 +16,18 @@ Du har afbestilt din tid ved ${order.trainer.first_name} ${order.trainer.last_na
Vi håber at se dig en anden dag.
Venlig hilsen Fitness World.`
})
await transporter.sendMail({
from: `Fitness World <${smtpAddress}>`,
to: order.trainer.email,
subject: "Ordre afbestilt - Fitness World",
text:
`Hej, ${order.trainer.first_name} ${order.trainer.last_name}.
${user.first_name} ${user.last_name} har aflyst sin tid i ${order.trainer.center_name}
Venlig hilsen Fitness World.`
})
}

@ -1,10 +1,11 @@
import { Dayjs } from "dayjs";
import { transporter } from ".";
import { smtpAddress } from "../environment";
import { Order, OrderObject } from "../interfaces/order";
import User from "../interfaces/user";
import { formatDate, formatTime } from "../utils/dates";
export async function sendUserMovedOrderEmail(user: User, order: Order) {
export async function sendUserMovedOrderEmail(user: User, order: Order, oldStartDate: Date | Dayjs, oldEndDate: Date | Dayjs) {
await transporter.sendMail({
from: `Fitness World <${smtpAddress}>`,
to: user.email,
@ -12,9 +13,30 @@ export async function sendUserMovedOrderEmail(user: User, order: Order) {
text:
`Hej, ${user.first_name} ${user.last_name}.
Din tid ved ${order.trainer.first_name} ${order.trainer.last_name} i ${order.trainer.center_name} er blevet flyttet.
Du har flyttet din tid ved ${order.trainer.first_name} ${order.trainer.last_name} i ${order.trainer.center_name}
Vi glæder os til at se dig ${formatDate(order.startDate)} ${formatTime(order.startDate)} - ${formatTime(order.endDate)}
Fra: ${formatDate(oldStartDate)} ${formatTime(oldStartDate)} - ${formatTime(oldEndDate)}
Til: ${formatDate(order.startDate)} ${formatTime(order.startDate)} - ${formatTime(order.endDate)}
Vi glæder os til at se dig.
Venlig hilsen Fitness World.`
})
await transporter.sendMail({
from: `Fitness World <${smtpAddress}>`,
to: order.trainer.email,
subject: "Ordre flyttet - Fitness World",
text:
`Hej, ${order.trainer.first_name} ${order.trainer.last_name}.
${user.first_name} ${user.last_name} har flyttet sin tid i ${order.trainer.center_name}
Fra: ${formatDate(oldStartDate)} ${formatTime(oldStartDate)} - ${formatTime(oldEndDate)}
Til: ${formatDate(order.startDate)} ${formatTime(order.startDate)} - ${formatTime(order.endDate)}
Venlig hilsen Fitness World.`
})

@ -35,7 +35,8 @@ router.post("/order/:id/cancel", UserAuth, async (req: AuthedRequest, res: Respo
'first_name',trainer_user.first_name,
'last_name',trainer_user.last_name,
'center_id',trainers.center_id,
'center_name',centers.name
'center_name',centers.name,
'email',trainer_user.email
) as trainer,
json_build_object(
'id', order_user.id,

@ -66,7 +66,8 @@ router.put("/order/:id", UserAuth, async (req: AuthedRequest, res: Response) =>
'first_name',trainer_user.first_name,
'last_name',trainer_user.last_name,
'center_id',trainers.center_id,
'center_name',centers.name
'center_name',centers.name,
'email',trainer_user.email
) as trainer,
json_build_object(
'id', order_user.id,
@ -189,10 +190,13 @@ router.put("/order/:id", UserAuth, async (req: AuthedRequest, res: Response) =>
timeslot_id
]);
const oldStartDate = order.startDate;
const oldEndDate = order.endDate;
order.startDate = startDate;
order.endDate = endDate;
sendUserMovedOrderEmail(user, order);
sendUserMovedOrderEmail(user, order, oldStartDate, oldEndDate);
return res.sendStatus(204);
} catch (error: DatabaseError | Error | any) {

@ -6,8 +6,11 @@ import { client } from "../../db";
import { DatabaseError } from "pg";
import { AuthedRequest } from "../../interfaces/auth";
import Trainer from "../../interfaces/trainer";
import { OrderObject, OrderObjectStatus, OrderStatus, PaymentIntentStatus } from "../../interfaces/order";
import { Order, OrderObject, OrderObjectStatus, OrderStatus, PaymentIntentStatus } from "../../interfaces/order";
import { TrainerAuth } from "../../middlewares/auth";
import User from "../../interfaces/user";
import { sendTrainerMovedOrderEmail } from "../../mail/trainerMovedOrder";
import { sendTrainerCancelledOrderEmail } from "../../mail/trainerCancelledOrder";
const router: Router = express.Router();
@ -121,18 +124,38 @@ const orderSchema = Joi.object({
router.put("/trainer/order/:id", TrainerAuth, async (req: AuthedRequest, res: Response) => {
try {
const lookupResult = await client.query(`
SELECT
order_status,
start_time,
end_time,
trainer_id,
timeslot_id
FROM orders
LEFT JOIN payment_intents ON payment_intents.id = orders.payment_intent
LEFT JOIN reserved_timeslots ON reserved_timeslots.id = orders.timeslot_id
LEFT JOIN trainers ON trainers.id = reserved_timeslots.trainer_id
WHERE orders.id = $1
AND trainers.user_id = $2
SELECT
orders.id,
order_status,
price,
created_at,
payment_intents.status as payment_intent_status,
start_time as "startDate",
end_time as "endDate",
timeslot_id,
json_build_object(
'id',trainers.id,
'first_name',trainer_user.first_name,
'last_name',trainer_user.last_name,
'center_id',trainers.center_id,
'center_name',centers.name,
'email',trainer_user.email
) as trainer,
json_build_object(
'id', order_user.id,
'first_name', order_user.first_name,
'last_name', order_user.last_name,
'email', order_user.email
) as user
FROM orders
LEFT JOIN reserved_timeslots ON reserved_timeslots.id = orders.timeslot_id
LEFT JOIN payment_intents ON payment_intents.id = orders.payment_intent
LEFT JOIN trainers ON trainers.id = reserved_timeslots.trainer_id
LEFT JOIN centers on trainers.center_id = centers.id
LEFT JOIN users AS trainer_user on trainer_user.id = trainers.user_id
LEFT JOIN users AS order_user on order_user.id = orders.user_id
WHERE orders.id = $1
AND trainer_user.id = $2
AND order_status = 'Confirmed';
`, [
req.params.id,
@ -143,10 +166,14 @@ router.put("/trainer/order/:id", TrainerAuth, async (req: AuthedRequest, res: Re
return res.sendStatus(404);
}
const order: ChangeOrderLookup = lookupResult.rows[0];
const user: User = lookupResult.rows[0].user;
lookupResult.rows[0].user = undefined;
const timeslot_id: number = lookupResult.rows[0].timeslot_id;
lookupResult.rows[0].timeslot_id = undefined;
const order: Order = lookupResult.rows[0];
const originalStartDate: dayjs.Dayjs = dayjs(order.start_time).utcOffset(0);
const originalEndDate: dayjs.Dayjs = dayjs(order.end_time).utcOffset(0);
const originalStartDate: dayjs.Dayjs = dayjs(order.startDate).utcOffset(0);
const originalEndDate: dayjs.Dayjs = dayjs(order.endDate).utcOffset(0);
/** The duration of the original timeslot in miliseconds */
const originalDuration: number = originalEndDate.diff(originalStartDate);
@ -182,10 +209,10 @@ router.put("/trainer/order/:id", TrainerAuth, async (req: AuthedRequest, res: Re
AND reserved_timeslots.id != $4
) as time_already_reserved;
`, [
order.trainer_id,
order.trainer.id,
startDate.toISOString(),
endDate.toISOString(),
order.timeslot_id
timeslot_id
]);
const time_already_reserved: boolean = timeslotValidQuery.rows[0].time_already_reserved;
@ -218,9 +245,17 @@ router.put("/trainer/order/:id", TrainerAuth, async (req: AuthedRequest, res: Re
`, [
startDate.toISOString(),
endDate.toISOString(),
order.timeslot_id
timeslot_id
]);
const oldStartDate = order.startDate
const oldEndDate = order.endDate;
order.startDate = startDate;
order.endDate = endDate;
sendTrainerMovedOrderEmail(user, order, oldStartDate, oldEndDate);
return res.sendStatus(204);
} catch (error: DatabaseError | Error | any) {
console.error(error);
@ -231,16 +266,37 @@ router.put("/trainer/order/:id", TrainerAuth, async (req: AuthedRequest, res: Re
router.post("/trainer/order/:id/cancel", TrainerAuth, async (req: AuthedRequest, res: Response) => {
try {
const lookupResult = await client.query(`
SELECT
order_status,
payment_intents.status as payment_intent_status,
start_time
FROM orders
LEFT JOIN payment_intents ON payment_intents.id = orders.payment_intent
LEFT JOIN reserved_timeslots ON reserved_timeslots.id = orders.timeslot_id
LEFT JOIN trainers ON trainers.id = reserved_timeslots.trainer_id
WHERE orders.id = $1
AND trainers.user_id = $2
SELECT
orders.id,
order_status,
price,
created_at,
payment_intents.status as payment_intent_status,
start_time as "startDate",
end_time as "endDate",
json_build_object(
'id',trainers.id,
'first_name',trainer_user.first_name,
'last_name',trainer_user.last_name,
'center_id',trainers.center_id,
'center_name',centers.name,
'email',trainer_user.email
) as trainer,
json_build_object(
'id', order_user.id,
'first_name', order_user.first_name,
'last_name', order_user.last_name,
'email', order_user.email
) as user
FROM orders
LEFT JOIN reserved_timeslots ON reserved_timeslots.id = orders.timeslot_id
LEFT JOIN payment_intents ON payment_intents.id = orders.payment_intent
LEFT JOIN trainers ON trainers.id = reserved_timeslots.trainer_id
LEFT JOIN centers on trainers.center_id = centers.id
LEFT JOIN users AS trainer_user on trainer_user.id = trainers.user_id
LEFT JOIN users AS order_user on order_user.id = orders.user_id
WHERE orders.id = $1
AND trainer_user.id = $2
AND order_status = 'Confirmed';
`, [
req.params.id,
@ -251,9 +307,11 @@ router.post("/trainer/order/:id/cancel", TrainerAuth, async (req: AuthedRequest,
return res.sendStatus(404);
}
const order: CancelOrderLookup = lookupResult.rows[0];
const user: User = lookupResult.rows[0].user;
lookupResult.rows[0].user = undefined;
const order: Order = lookupResult.rows[0];
const dateValidation = Joi.date().min(Date.now()).validate(order.start_time)
const dateValidation = Joi.date().min(Date.now()).validate(order.startDate)
if (dateValidation.error !== undefined) {
return res.status(400).send({ message: "Timeslot has already occurred" });
}
@ -267,6 +325,8 @@ router.post("/trainer/order/:id/cancel", TrainerAuth, async (req: AuthedRequest,
req.params.id
]);
sendTrainerCancelledOrderEmail(user, order);
return res.sendStatus(204);
} catch (error: DatabaseError | Error | any) {
console.error(error);

Loading…
Cancel
Save