From 3220ee70c4a3e37f735eadb009be46f8a9923802 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 11 May 2026 12:04:34 -0500 Subject: [PATCH] financial data entry --- AGENTS.md | 2 +- client/src/components/AmendViolationModal.jsx | 2 ++ client/src/components/ViolationForm.jsx | 2 +- db/database.js | 2 ++ db/schema.sql | 1 + pdf/template.js | 5 +++++ server.js | 13 ++++++++----- 7 files changed, 20 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b7fd96a..45b7ba8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -82,7 +82,7 @@ The following fields on `violations` are locked after submission. They are the b - `prior_active_points` (snapshot at insert time) - `prior_tier_label` -Amendable fields (non-scoring): `location`, `details`, `witness_name`, `acknowledged_by`, `acknowledged_date` +Amendable fields (non-scoring): `incident_time`, `location`, `details`, `submitted_by`, `witness_name`, `acknowledged_by`, `acknowledged_date`, `amount` ### Soft-Delete Pattern diff --git a/client/src/components/AmendViolationModal.jsx b/client/src/components/AmendViolationModal.jsx index c9dbd91..c412093 100644 --- a/client/src/components/AmendViolationModal.jsx +++ b/client/src/components/AmendViolationModal.jsx @@ -7,6 +7,7 @@ const FIELD_LABELS = { details: 'Incident Notes', submitted_by: 'Submitted By', witness_name: 'Witness / Documenting Officer', + amount: 'Amount in Question', }; const s = { @@ -84,6 +85,7 @@ export default function AmendViolationModal({ violation, onClose, onSaved }) { details: violation.details || '', submitted_by: violation.submitted_by || '', witness_name: violation.witness_name || '', + amount: violation.amount || '', }); const [changedBy, setChangedBy] = useState(''); const [saving, setSaving] = useState(false); diff --git a/client/src/components/ViolationForm.jsx b/client/src/components/ViolationForm.jsx index c9a45dd..c7edf45 100755 --- a/client/src/components/ViolationForm.jsx +++ b/client/src/components/ViolationForm.jsx @@ -36,7 +36,6 @@ const s = { const EMPTY_FORM = { employeeId: '', employeeName: '', department: '', supervisor: '', witnessName: '', violationType: '', incidentDate: '', incidentTime: '', - // TODO [MAJOR #6]: `amount` and `minutesLate` are rendered but never sent to the API amount: '', minutesLate: '', location: '', additionalDetails: '', points: 1, acknowledgedBy: '', acknowledgedDate: '', }; @@ -159,6 +158,7 @@ export default function ViolationForm() { witness_name: form.witnessName || null, acknowledged_by: form.acknowledgedBy || null, acknowledged_date: form.acknowledgedDate || null, + amount: form.amount || null, }); const newId = violRes.data.id; diff --git a/db/database.js b/db/database.js index 520ac7a..8013835 100755 --- a/db/database.js +++ b/db/database.js @@ -21,6 +21,8 @@ if (!cols.includes('prior_active_points')) db.exec("ALTER TABLE violations ADD C if (!cols.includes('prior_tier_label')) db.exec("ALTER TABLE violations ADD COLUMN prior_tier_label TEXT"); if (!cols.includes('acknowledged_by')) db.exec("ALTER TABLE violations ADD COLUMN acknowledged_by TEXT"); if (!cols.includes('acknowledged_date')) db.exec("ALTER TABLE violations ADD COLUMN acknowledged_date TEXT"); +// Financial amount in question (record-keeping / repayment for chargeback, receipt negligence, etc.) +if (!cols.includes('amount')) db.exec("ALTER TABLE violations ADD COLUMN amount TEXT"); // Employee notes column (free-text, does not affect scoring) const empCols = db.prepare('PRAGMA table_info(employees)').all().map(c => c.name); diff --git a/db/schema.sql b/db/schema.sql index 8129bb3..5ee5c9a 100755 --- a/db/schema.sql +++ b/db/schema.sql @@ -25,6 +25,7 @@ CREATE TABLE IF NOT EXISTS violations ( prior_tier_label TEXT, -- optional human-readable tier acknowledged_by TEXT, -- employee name who acknowledged receipt acknowledged_date TEXT, -- date of acknowledgment (YYYY-MM-DD) + amount TEXT, -- dollar amount in question for financial violations (record-keeping / repayment) created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); diff --git a/pdf/template.js b/pdf/template.js index 3a10deb..6f958fb 100755 --- a/pdf/template.js +++ b/pdf/template.js @@ -243,6 +243,11 @@ function buildHtml(v, score) {
Submitted By
${v.submitted_by || 'System'}
+ ${v.amount ? ` +
+
Amount in Question
+
${v.amount}
+
` : ''} ${v.location ? `
Location / Context
diff --git a/server.js b/server.js index c1fe4e7..65b89f5 100755 --- a/server.js +++ b/server.js @@ -266,7 +266,8 @@ app.post('/api/violations', (req, res) => { employee_id, violation_type, violation_name, category, points, incident_date, incident_time, location, details, submitted_by, witness_name, - acknowledged_by, acknowledged_date + acknowledged_by, acknowledged_date, + amount } = req.body; if (!employee_id || !violation_type || !points || !incident_date) { @@ -282,15 +283,17 @@ app.post('/api/violations', (req, res) => { points, incident_date, incident_time, location, details, submitted_by, witness_name, prior_active_points, - acknowledged_by, acknowledged_date - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + acknowledged_by, acknowledged_date, + amount + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `).run( employee_id, violation_type, violation_name || violation_type, category || 'General', ptsInt, incident_date, incident_time || null, location || null, details || null, submitted_by || null, witness_name || null, priorPts, - acknowledged_by || null, acknowledged_date || null + acknowledged_by || null, acknowledged_date || null, + amount || null ); audit('violation_created', 'violation', result.lastInsertRowid, submitted_by, { @@ -302,7 +305,7 @@ app.post('/api/violations', (req, res) => { // ── Violation Amendment (edit) ─────────────────────────────────────────────── // PATCH /api/violations/:id/amend — edit mutable fields; logs a diff per changed field -const AMENDABLE_FIELDS = ['incident_time', 'location', 'details', 'submitted_by', 'witness_name', 'acknowledged_by', 'acknowledged_date']; +const AMENDABLE_FIELDS = ['incident_time', 'location', 'details', 'submitted_by', 'witness_name', 'acknowledged_by', 'acknowledged_date', 'amount']; // Pre-build one prepared UPDATE statement per amendable field combination is not // practical (2^n combos), so instead we validate columns against the static