/**
* Builds the full HTML string for a CPAS violation PDF document.
* Matches the styling of the original HTML violation form.
*/
const TIERS = [
{ min: 0, max: 4, label: 'Tier 0-1 — Elite Standing', color: '#28a745' },
{ min: 5, max: 9, label: 'Tier 1 — Realignment', color: '#856404' },
{ min: 10, max: 14, label: 'Tier 2 — Administrative Lockdown', color: '#d9534f' },
{ min: 15, max: 19, label: 'Tier 3 — Verification', color: '#d9534f' },
{ min: 20, max: 24, label: 'Tier 4 — Risk Mitigation', color: '#c0392b' },
{ min: 25, max: 29, label: 'Tier 5 — Final Decision', color: '#c0392b' },
{ min: 30, max: 999,label: 'Tier 6 — Separation', color: '#721c24' },
];
function getTier(points) {
return TIERS.find(t => points >= t.min && points <= t.max) || TIERS[0];
}
function formatDate(d) {
if (!d) return '—';
const dt = new Date(d + 'T12:00:00');
return dt.toLocaleDateString('en-US', {
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',
timeZone: 'America/Chicago'
});
}
function formatDateTime(d, t) {
const date = formatDate(d);
return t ? `${date} at ${t}` : date;
}
function row(label, value) {
return `
| ${label} |
${value || '—'} |
`;
}
function buildHtml(v, score) {
const activePts = score.active_points || 0;
const tier = getTier(activePts);
const newTotal = activePts + v.points;
const newTier = getTier(newTotal);
const tierChange = tier.label !== newTier.label;
const generatedAt = new Date().toLocaleString('en-US', {
timeZone: 'America/Chicago',
dateStyle: 'full', timeStyle: 'short'
});
return `
⚠ CONFIDENTIAL — For authorized HR and management use only
Employee Information
${row('Employee Name', `${v.employee_name}`)}
${row('Department', v.department)}
${row('Supervisor', v.supervisor)}
${row('Witness / Documenting Officer', v.witness_name)}
Violation Details
${row('Violation Type', `${v.violation_name}`)}
${row('Category', v.category)}
${row('Policy Reference', v.violation_type.replace(/_/g,' ').replace(/\w/g,c=>c.toUpperCase()))}
${row('Incident Date / Time', formatDateTime(v.incident_date, v.incident_time))}
${v.location ? row('Location / Context', v.location) : ''}
${v.details ? row('Incident Details', `${v.details}`) : ''}
${row('Submitted By', v.submitted_by || 'System')}
CPAS Point Assessment
${v.points}
Points Assessed — This Violation
${activePts}
Active Points (Prior)
${tier.label}
+
${v.points}
Points — This Violation
=
${newTotal}
New Active Total
${newTier.label}
${tierChange ? `
⚠ Tier Escalation: This violation advances the employee from
${tier.label} to ${newTier.label}.
Review associated tier consequences per the Employee Handbook.
` : ''}
CPAS Tier Reference
| Points |
Tier |
${TIERS.map(t => `
| ${t.min === 30 ? '30+' : t.min + '–' + t.max} |
${t.label} |
`).join('')}
Employee Notice: CPAS points remain active for a rolling 90-day period from the date of each incident.
Accumulation of points may result in tier escalation and associated consequences as outlined in the Employee Handbook,
Chapter 4, Section 5. This document should be reviewed with the employee and signed by all parties.
Acknowledgement & Signatures
By signing below, the employee acknowledges receipt of this violation record.
Acknowledgement does not imply agreement. The employee may submit a written
response within 5 business days.
Supervisor / Documenting Officer Signature
`;
}
module.exports = buildHtml;