Time unification
This commit is contained in:
@@ -1,11 +1,20 @@
|
||||
import express from 'express';
|
||||
import { DateTime } from 'luxon';
|
||||
import { getDbConnection, getPoolStatus } from '../db/connection.js';
|
||||
import { parseMySql, toMySqlBound } from '../../../shared/business-time/index.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const TIMEZONE = 'America/New_York';
|
||||
|
||||
// timeclock.TimeStamp stores Central wall-clock literals; the driver returns
|
||||
// them as strings (dateStrings: true). Parse in business time, compare/display
|
||||
// in ET (pay-period boundaries are an ET display convention).
|
||||
const punchDateTime = (punch) => {
|
||||
const dt = parseMySql(punch.TimeStamp);
|
||||
return dt ? dt.setZone(TIMEZONE) : null;
|
||||
};
|
||||
|
||||
// Punch types from the database
|
||||
const PUNCH_TYPES = {
|
||||
OUT: 0,
|
||||
@@ -108,17 +117,17 @@ function calculateHoursByWeek(punches, payPeriod) {
|
||||
|
||||
byEmployee.forEach((employeeData) => {
|
||||
// Sort punches by timestamp
|
||||
employeeData.punches.sort((a, b) => new Date(a.TimeStamp) - new Date(b.TimeStamp));
|
||||
employeeData.punches.sort((a, b) => (punchDateTime(a)?.toMillis() ?? 0) - (punchDateTime(b)?.toMillis() ?? 0));
|
||||
|
||||
// Calculate hours for each week
|
||||
const week1Punches = employeeData.punches.filter(p => {
|
||||
const dt = DateTime.fromJSDate(new Date(p.TimeStamp), { zone: TIMEZONE });
|
||||
return dt >= payPeriod.week1.start && dt <= payPeriod.week1.end;
|
||||
const dt = punchDateTime(p);
|
||||
return dt && dt >= payPeriod.week1.start && dt <= payPeriod.week1.end;
|
||||
});
|
||||
|
||||
const week2Punches = employeeData.punches.filter(p => {
|
||||
const dt = DateTime.fromJSDate(new Date(p.TimeStamp), { zone: TIMEZONE });
|
||||
return dt >= payPeriod.week2.start && dt <= payPeriod.week2.end;
|
||||
const dt = punchDateTime(p);
|
||||
return dt && dt >= payPeriod.week2.start && dt <= payPeriod.week2.end;
|
||||
});
|
||||
|
||||
const week1Hours = calculateHoursFromPunches(week1Punches);
|
||||
@@ -205,7 +214,7 @@ function calculateHoursFromPunches(punches) {
|
||||
let breakStart = null;
|
||||
|
||||
punches.forEach(punch => {
|
||||
const punchTime = new Date(punch.TimeStamp);
|
||||
const punchTime = punchDateTime(punch)?.toJSDate() ?? new Date(NaN);
|
||||
|
||||
switch (punch.PunchType) {
|
||||
case PUNCH_TYPES.IN:
|
||||
@@ -283,9 +292,11 @@ router.get('/', async (req, res) => {
|
||||
console.log(`[PAYROLL-METRICS] DB connection obtained in ${Date.now() - startTime}ms`);
|
||||
try {
|
||||
|
||||
// Build query for the pay period
|
||||
const periodStart = payPeriod.start.toJSDate();
|
||||
const periodEnd = payPeriod.end.toJSDate();
|
||||
// Build query for the pay period. Bounds are serialized to Central
|
||||
// wall-clock strings (the column's literal zone), half-open
|
||||
// [start, start + 14 days).
|
||||
const periodStart = toMySqlBound(payPeriod.start);
|
||||
const periodEnd = toMySqlBound(payPeriod.start.plus({ days: 14 }));
|
||||
|
||||
const timeclockQuery = `
|
||||
SELECT
|
||||
@@ -296,7 +307,7 @@ router.get('/', async (req, res) => {
|
||||
e.lastname
|
||||
FROM timeclock tc
|
||||
LEFT JOIN employees e ON tc.EmployeeID = e.employeeid
|
||||
WHERE tc.TimeStamp >= ? AND tc.TimeStamp <= ?
|
||||
WHERE tc.TimeStamp >= ? AND tc.TimeStamp < ?
|
||||
AND e.hidden = 0
|
||||
AND e.disabled = 0
|
||||
ORDER BY tc.EmployeeID, tc.TimeStamp
|
||||
@@ -322,8 +333,8 @@ router.get('/', async (req, res) => {
|
||||
// Get previous pay period data for comparison
|
||||
const prevPayPeriod = navigatePayPeriod(payPeriod.start, -1);
|
||||
const [prevTimeclockRows] = await connection.execute(timeclockQuery, [
|
||||
prevPayPeriod.start.toJSDate(),
|
||||
prevPayPeriod.end.toJSDate(),
|
||||
toMySqlBound(prevPayPeriod.start),
|
||||
toMySqlBound(prevPayPeriod.start.plus({ days: 14 })),
|
||||
]);
|
||||
|
||||
const prevHoursData = calculateHoursByWeek(prevTimeclockRows, prevPayPeriod);
|
||||
|
||||
Reference in New Issue
Block a user