Workplace Compensation Compliance Tracker

Workplace Compensation Compliance Tracker

Analyze payroll data against federal and state labor laws.

Compliance Overview & Settings

Total Payroll
$0.00
Compliance Status
-
Potential Underpayment
$0.00
Step 1 of 3

Disclaimer: This tool provides a general assessment for informational purposes and is not a substitute for professional legal or accounting advice.

Applicable Minimum Wage: $${report.applicableMinWage.toFixed(2)}/hr

${report.employeeCalculations.map(emp => ` `).join('')}
Compliance Details
Employee Effective Rate Calculated Pay Compliance Flags
${emp.name} $${emp.effectiveRate.toFixed(2)}/hr $${emp.totalPay.toFixed(2)} ${emp.flags.length > 0 ? emp.flags.map(f => `${f.message} ($${f.amount.toFixed(2)})`).join('') : 'Compliant'}
Totals $${report.totalPayroll.toFixed(2)} $${report.totalRiskAmount.toFixed(2)}
`; container.innerHTML = html; } // --- Core Logic --- function runComplianceCheck() { const { settings, employees } = appState; const applicableMinWage = Math.max(settings.fedMinWage, settings.stateMinWage); const otThreshold = 40; let totalPayroll = 0; let totalRiskAmount = 0; const employeeCalculations = []; employees.forEach(emp => { let regHours = Math.min(emp.hours, otThreshold); let otHours = Math.max(0, emp.hours - otThreshold); let totalPay = 0; let effectiveRate = 0; const flags = []; if (emp.type === 'hourly') { effectiveRate = emp.rate; const regPay = regHours * emp.rate; const otPay = otHours * emp.rate * 1.5; totalPay = regPay + otPay; if (emp.rate < applicableMinWage) { const underpayment = (applicableMinWage - emp.rate) * emp.hours; flags.push({ message: 'Below minimum wage', amount: underpayment }); totalRiskAmount += underpayment; } } else if (emp.type === 'salary') { // Assuming weekly salary for non-exempt employee const baseRate = emp.rate / otThreshold; effectiveRate = emp.rate / Math.max(emp.hours, otThreshold); if (effectiveRate < applicableMinWage) { const underpayment = (applicableMinWage * emp.hours) - emp.rate; flags.push({ message: 'Effective rate below minimum', amount: underpayment }); totalRiskAmount += underpayment; } // Salaried non-exempt overtime (half-time method) const otPremium = otHours * baseRate * 0.5; totalPay = emp.rate + otPremium; } totalPayroll += totalPay; employeeCalculations.push({ ...emp, totalPay, effectiveRate, flags }); }); appState.report = { totalPayroll, totalRiskAmount, applicableMinWage, employeeCalculations }; } // --- Event Handlers & Navigation --- function showTab(tabNumber) { document.querySelectorAll('.tab-pane').forEach(p => p.classList.add('hidden')); getEl(`tab-${tabNumber}`).classList.remove('hidden'); document.querySelectorAll('.tab-btn').forEach(b => { b.classList.toggle('active', b.dataset.tab === `tab-${tabNumber}`); b.classList.toggle('inactive', b.dataset.tab !== `tab-${tabNumber}`); }); currentTab = tabNumber; updateNavigation(); } function updateNavigation() { prevBtn.disabled = currentTab === 1; nextBtn.textContent = currentTab === totalTabs - 1 ? 'Generate Report' : 'Next'; nextBtn.style.display = currentTab === totalTabs ? 'none' : 'inline-block'; stepIndicator.textContent = `Step ${currentTab} of ${totalTabs}`; } getEl('form-add-employee').addEventListener('submit', (e) => { e.preventDefault(); appState.employees.push({ id: nextEmployeeId++, name: getEl('empName').value, type: getEl('payType').value, rate: parseFloat(getEl('payRate').value), hours: parseFloat(getEl('hoursWorked').value) }); e.target.reset(); renderEmployeeTable(); }); getEl('employee-table-body').addEventListener('click', (e) => { if (e.target.classList.contains('delete-btn')) { const id = parseInt(e.target.dataset.id); appState.employees = appState.employees.filter(emp => emp.id !== id); renderEmployeeTable(); } }); stateSelect.addEventListener('change', (e) => { const state = e.target.value; if (stateMinWages[state]) { getEl('stateMinWage').value = stateMinWages[state]; } }); function generateFullReport() { if (!getEl('form-settings').checkValidity()) { getEl('form-settings').reportValidity(); showTab(1); return; } appState.settings.payPeriod = getEl('payPeriod').value; appState.settings.state = getEl('state').value; appState.settings.fedMinWage = parseFloat(getEl('fedMinWage').value); appState.settings.stateMinWage = parseFloat(getEl('stateMinWage').value); showTab(3); getEl('report-content').classList.add('hidden'); getEl('report-loading').classList.remove('hidden'); setTimeout(() => { runComplianceCheck(); renderDashboard(); renderReport(); getEl('report-loading').classList.add('hidden'); getEl('report-content').classList.remove('hidden'); }, 1000); } nextBtn.addEventListener('click', () => { if (currentTab < totalTabs - 1) { showTab(currentTab + 1); } else if (currentTab === totalTabs - 1) { generateFullReport(); } }); prevBtn.addEventListener('click', () => { if (currentTab > 1) showTab(currentTab - 1); }); getEl('download-pdf-btn').addEventListener('click', () => { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const report = appState.report; const settings = appState.settings; doc.setFontSize(18); doc.text("Workplace Compensation Compliance Report", 105, 20, { align: 'center' }); doc.setFontSize(11); doc.text(`Pay Period Ending: ${settings.payPeriod}`, 14, 30); doc.text(`State: ${settings.state}`, 14, 36); const tableBody = report.employeeCalculations.map(emp => { const flagsText = emp.flags.length > 0 ? emp.flags.map(f => `${f.message} ($${f.amount.toFixed(2)})`).join(', ') : 'Compliant'; return [emp.name, `$${emp.effectiveRate.toFixed(2)}`, `$${emp.totalPay.toFixed(2)}`, flagsText]; }); doc.autoTable({ startY: 45, head: [['Employee', 'Effective Rate', 'Calculated Pay', 'Compliance Flags']], body: tableBody, foot: [['Totals', '', `$${report.totalPayroll.toFixed(2)}`, `Risk: $${report.totalRiskAmount.toFixed(2)}`]], theme: 'grid', headStyles: { fillColor: [29, 78, 216] }, footStyles: { fontStyle: 'bold' } }); doc.save(`Compensation-Report-${settings.payPeriod}.pdf`); }); // --- Initialization --- renderEmployeeTable(); updateNavigation(); });
Scroll to Top