Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions server/src/module/attendance/attendance.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const MAX_WORK_HOURS = 24;
5 changes: 5 additions & 0 deletions server/src/module/attendance/attendance.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ export class AttendanceController {
const record = await this.attendanceService.regularize(result.data);
return res.json({ message: "Attendance regularized", record });
} catch (error) {
if (error instanceof Error) {
const msg = error.message;
if (msg.includes("must be after") || msg.includes("must not exceed") || msg.includes("Cannot regularize") || msg.includes("cannot be in the future"))
return res.status(400).json({ message: msg });
}
console.error(error);
return res.status(500).json({ message: "Internal Server Error" });
}
Expand Down
4 changes: 4 additions & 0 deletions server/src/module/attendance/attendance.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { prisma } from "../../database/db.js";
import type { AttendanceStatus, Prisma } from "@prisma/client";
import { MAX_WORK_HOURS } from "./attendance.constants.js";

interface AttendanceQuery {
page: number;
Expand Down Expand Up @@ -133,6 +134,9 @@ export class AttendanceService {
const checkOut = new Date(data.checkOut);
const workHours = (checkOut.getTime() - checkIn.getTime()) / 3600000;

if (workHours <= 0) throw new Error("checkOut must be after checkIn");
if (workHours > MAX_WORK_HOURS) throw new Error("Work hours must not exceed 24");

return prisma.attendanceRecord.upsert({
where: { employeeId_date: { employeeId: data.employeeId, date } },
create: {
Expand Down
11 changes: 11 additions & 0 deletions server/src/module/attendance/attendance.validation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { z } from "zod";
import { MAX_WORK_HOURS } from "./attendance.constants.js";

export const checkInSchema = z.object({
employeeId: z.number().int().positive(),
Expand All @@ -16,6 +17,16 @@ export const regularizeSchema = z.object({
checkIn: z.string().datetime(),
checkOut: z.string().datetime(),
notes: z.string().min(1, "Reason for regularization is required").max(500),
}).superRefine((data, ctx) => {
const workHours = (new Date(data.checkOut).getTime() - new Date(data.checkIn).getTime()) / 3600000;

if (workHours <= 0) {
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "checkOut must be after checkIn", path: ["checkOut"] });
}

if (workHours > MAX_WORK_HOURS) {
ctx.addIssue({ code: z.ZodIssueCode.custom, message: `Work hours must not exceed ${MAX_WORK_HOURS}`, path: ["checkOut"] });
}
});

export const attendanceQuerySchema = z.object({
Expand Down
Loading