Skip to content

Commit

Permalink
perf: Reduced DB calls, improved error checks (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
aryanprince committed Nov 28, 2023
1 parent ddf551c commit 3397125
Showing 1 changed file with 126 additions and 105 deletions.
231 changes: 126 additions & 105 deletions src/pages/api/createattendance.ts
Original file line number Diff line number Diff line change
@@ -1,132 +1,153 @@
import type { NextApiRequest, NextApiResponse } from "next";
import type { NextApiRequest, NextApiResponse } from 'next'

import { Status } from "@prisma/client";
import { differenceInMinutes, format, parseISO } from "date-fns";
import { prisma } from "~/server/prisma";
import { Status } from '@prisma/client'
import { differenceInMinutes, format, parseISO } from 'date-fns'
import { prisma } from '~/server/prisma'

type RequestBody = {
studentCardId: string;
lectureId: string;
};
studentCardId: string
lectureId: string
}

export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (req.method === "POST") {
//1 - Receive studentCardId and lectureId from request body
const { lectureId, studentCardId } = req.body as RequestBody;
if (req.method === 'POST') {
// Receive studentCardId and lectureId from request body
const { lectureId, studentCardId } = req.body as RequestBody

if (req.query !== undefined) {
res.status(400).send({
error:
'Query parameters are invalid, please pass values in request body',
})
return
}

if (req.body === undefined) {
res.status(400).send({ error: 'Missing request body' })
return
}

// If request body is missing parameters, throw errorq
if (!lectureId || !studentCardId) {
res.status(400).send({ error: "Missing parameters in request body" });
return;
res.status(400).send({ error: 'Missing parameters in request body' })
return
}

//2 - Check if studentCardId is valid and get its studentId
try {
const returnedData1 = await prisma.student
.findUniqueOrThrow({
where: {
// Check if student is enrolled in module, if not, throw error
const result = await prisma.enrollment.findFirst({
where: {
AND: {
Module: {
is: {
Lectures: {
some: {
lectureId: lectureId,
},
},
},
},

Student: {
studentCardId: studentCardId,
},
},
},
select: {
Student: {
select: {
studentId: true,
},
})
.catch((error) => {
console.log("❌ Error", error);
res.status(404).send({ error: "Student card ID not valid" });
return;
});

// 3 - Check if lectureId is valid and get its moduleId
const returnedData2 = await prisma.lecture
.findUniqueOrThrow({
where: {
lectureId: lectureId,
},
},
Module: {
select: {
startTime: true,
Module: {
Lectures: {
select: {
moduleId: true,
lectureId: true,
startTime: true,
},

where: {
lectureId: lectureId,
},
take: 1,
},
},
})
.catch((error) => {
console.log("❌ Error", error);
res.status(404).send({
error: "Lecture ID not valid",
});
return;
});

// 4 - Check if student is enrolled in module, if not, throw error
const returnedData3 = await prisma.enrollment
.findFirstOrThrow({
where: {
moduleId: returnedData2?.Module.moduleId,
studentId: returnedData1?.studentId,
},
select: {
enrollmentId: true,
},
})
.catch((error) => {
console.log("❌ Error", error);
res.status(404).send({ error: "Student not enrolled" });
return;
});

//5 - Calculate the status of the attendance record based on the time
const lectureStartTime = returnedData2?.startTime;
const formattedDate = format(new Date(), "yyyy-MM-dd'T'HH:mm:ss.SSSX");
const currentTime = parseISO(formattedDate);

if (!lectureStartTime) {
res.status(404).send({ error: "Lecture start time not found" });
return;
}
const timeDiff = differenceInMinutes(currentTime, lectureStartTime);

let calculatedStatus: Status = Status.PRESENT;

if (-15 < timeDiff && timeDiff < 15) {
// timediff = 5
calculatedStatus = Status.PRESENT;
} else if (timeDiff > 15) {
// timediff = 20
calculatedStatus = Status.LATE;
} else if (timeDiff < -15) {
// timediff -500
res
.status(404)
.send({ message: "Please retry closer to lecture start time" });
}

//6 - Creating the attendance record in the database
if (!returnedData1?.studentId) {
res.status(404).send({ error: "Student not found" });
return;
}
const newAttendanceRecord = await prisma.attendanceRecord.create({
data: {
studentId: returnedData1?.studentId,
lectureId: lectureId,
status: calculatedStatus,
},
});

res.status(200).send({
message: "Attendance record created",
status: newAttendanceRecord.status,
});
} catch (error) {
console.error("Error processing request:", error);
res.status(500).send({ error: "Internal Server Error", details: error });
},
})

// Error handling
if (!result) {
res.status(404).send({ error: 'Enrollment not found' })
return
}

if (!result?.Module) {
res.status(404).send({ error: 'Module not found' })
return
}

if (!result?.Module.Lectures[0]?.startTime) {
res.status(404).send({ error: 'Lecture start time not found' })
return
}

if (!result?.Module.Lectures[0]?.lectureId) {
res.status(404).send({ error: 'Lecture not found' })
return
}

if (!result?.Student) {
res.status(404).send({ error: 'Student not found' })
return
}

if (!result?.Student.studentId) {
res.status(404).send({ error: 'Student not found' })
return
}

// Calculate the status of the attendance record based on the time
const lectureStartTime = result.Module.Lectures[0].startTime
const formattedDate: string = format(
new Date(),
"yyyy-MM-dd'T'HH:mm:ss.SSSX",
)
const currentTime = parseISO(formattedDate)

const timeDiff = differenceInMinutes(currentTime, lectureStartTime)

let calculatedStatus: Status = Status.PRESENT

if (-15 < timeDiff && timeDiff < 15) {
calculatedStatus = Status.PRESENT
} else if (timeDiff > 15) {
calculatedStatus = Status.LATE
} else if (timeDiff < -15) {
res.status(404).send({
message: 'Too early! Please retry closer to lecture start time.',
})
}

// Creating the attendance record in the database with the calculated status
const newAttendanceRecord = await prisma.attendanceRecord.create({
data: {
studentId: result.Student.studentId,
lectureId: result.Module.Lectures[0].lectureId,
status: calculatedStatus,
},
})

res.status(200).send({
message: 'Attendance record created',
status: newAttendanceRecord.status,
})
} else {
res.status(405).json({ error: "Method Not Allowell" });
res.status(405).json({
error: 'Method not allowed, this endpoint only allows POST requests',
})
}
}

0 comments on commit 3397125

Please sign in to comment.