Add payroll and operations dashboard components

This commit is contained in:
2026-02-06 10:45:34 -05:00
parent fd14af0f9e
commit b5469440bf
9 changed files with 860 additions and 406 deletions

View File

@@ -234,10 +234,13 @@ function calculateHoursFromPunches(punches) {
/**
* Calculate FTE for a pay period (based on 80 hours = 1 FTE for 2-week period)
* @param {number} totalHours - Total hours worked
* @param {number} elapsedFraction - Fraction of the period elapsed (0-1). Defaults to 1 for complete periods.
*/
function calculateFTE(totalHours) {
function calculateFTE(totalHours, elapsedFraction = 1) {
const fullTimePeriodHours = STANDARD_WEEKLY_HOURS * 2; // 80 hours for 2 weeks
return totalHours / fullTimePeriodHours;
const proratedHours = fullTimePeriodHours * elapsedFraction;
return proratedHours > 0 ? totalHours / proratedHours : 0;
}
// Main payroll metrics endpoint
@@ -303,8 +306,15 @@ router.get('/', async (req, res) => {
// Calculate hours with week breakdown
const hoursData = calculateHoursByWeek(timeclockRows, payPeriod);
// Calculate FTE
const fte = calculateFTE(hoursData.totals.hours);
// Calculate FTE — prorate for in-progress periods so the value reflects
// the pace employees are on rather than raw hours / 80
let elapsedFraction = 1;
if (isCurrentPayPeriod(payPeriod)) {
const now = DateTime.now().setZone(TIMEZONE);
const elapsedDays = Math.max(1, Math.ceil(now.diff(payPeriod.start, 'days').days));
elapsedFraction = Math.min(1, elapsedDays / 14);
}
const fte = calculateFTE(hoursData.totals.hours, elapsedFraction);
const activeEmployees = hoursData.totals.activeEmployees;
const avgHoursPerEmployee = activeEmployees > 0 ? hoursData.totals.hours / activeEmployees : 0;