(Feat-Fix): Fixed attendance system

This commit is contained in:
2025-12-21 10:06:05 +00:00
parent 04e25527e8
commit 2d3412f79a
2 changed files with 34 additions and 18 deletions

View File

@@ -157,27 +157,43 @@ router.post(
return; return;
} }
// Check if there's an active check-in (not yet checked out) for today // Check if there's any existing attendance record for today
const activeCheckIn = await db.query<Attendance[]>( const existingRecord = await db.query<Attendance[]>(
"SELECT * FROM attendance WHERE employee_id = ? AND work_date = ? AND status = 'CheckedIn'", "SELECT * FROM attendance WHERE employee_id = ? AND work_date = ?",
[employeeId, workDate], [employeeId, workDate],
); );
if (activeCheckIn.length > 0) {
ctx.response.status = 400;
ctx.response.body = { error: "User has an active check-in. Please check out first before checking in again." };
return;
}
const checkInTime = new Date().toISOString().slice(0, 19).replace( const checkInTime = new Date().toISOString().slice(0, 19).replace(
"T", "T",
" ", " ",
); );
const result = await db.execute( let recordId: number;
"INSERT INTO attendance (employee_id, supervisor_id, check_in_time, work_date, status) VALUES (?, ?, ?, ?, ?)",
[employeeId, currentUser.id, checkInTime, workDate, "CheckedIn"], if (existingRecord.length > 0) {
); const record = existingRecord[0];
// If already checked in, don't allow another check-in
if (record.status === "CheckedIn") {
ctx.response.status = 400;
ctx.response.body = { error: "User has an active check-in. Please check out first before checking in again." };
return;
}
// If checked out or other status, update the existing record to check in again
await db.execute(
"UPDATE attendance SET check_in_time = ?, check_out_time = NULL, status = ?, supervisor_id = ? WHERE id = ?",
[checkInTime, "CheckedIn", currentUser.id, record.id],
);
recordId = record.id;
} else {
// No existing record, create new one
const result = await db.execute(
"INSERT INTO attendance (employee_id, supervisor_id, check_in_time, work_date, status) VALUES (?, ?, ?, ?, ?)",
[employeeId, currentUser.id, checkInTime, workDate, "CheckedIn"],
);
recordId = result.insertId as number;
}
const newRecord = await db.query<Attendance[]>( const newRecord = await db.query<Attendance[]>(
`SELECT a.*, `SELECT a.*,
@@ -191,10 +207,10 @@ router.post(
LEFT JOIN departments d ON e.department_id = d.id LEFT JOIN departments d ON e.department_id = d.id
LEFT JOIN users c ON e.contractor_id = c.id LEFT JOIN users c ON e.contractor_id = c.id
WHERE a.id = ?`, WHERE a.id = ?`,
[result.insertId], [recordId],
); );
ctx.response.status = 201; ctx.response.status = existingRecord.length > 0 ? 200 : 201;
ctx.response.body = newRecord[0]; ctx.response.body = newRecord[0];
} catch (error) { } catch (error) {
console.error("Check in error:", error); console.error("Check in error:", error);

View File

@@ -45,7 +45,7 @@ export const AllRatesPage: React.FC = () => {
setLoading(true); setLoading(true);
setError(""); setError("");
try { try {
const params: any = {}; const params: { departmentId?: number; startDate?: string; endDate?: string } = {};
if (filters.departmentId) { if (filters.departmentId) {
params.departmentId = parseInt(filters.departmentId); params.departmentId = parseInt(filters.departmentId);
} }
@@ -55,8 +55,8 @@ export const AllRatesPage: React.FC = () => {
const data = await api.getAllRates(params); const data = await api.getAllRates(params);
setAllRates(data.allRates); setAllRates(data.allRates);
setSummary(data.summary); setSummary(data.summary);
} catch (err: any) { } catch (err: unknown) {
setError(err.message || "Failed to fetch rates"); setError(err instanceof Error ? err.message : "Failed to fetch rates");
} finally { } finally {
setLoading(false); setLoading(false);
} }