Merge pull request 'Upload files to "/"' (#19) from p4-hotfixes into master
Reviewed-on: #19
This commit was merged in pull request #19.
This commit is contained in:
66
server.js
66
server.js
@@ -70,7 +70,7 @@ app.get('/api/violations/employee/:id', (req, res) => {
|
|||||||
res.json(rows);
|
res.json(rows);
|
||||||
});
|
});
|
||||||
|
|
||||||
// NEW helper: compute prior_active_points at time of insert (excluding this violation)
|
// Helper: compute prior_active_points at time of insert
|
||||||
function getPriorActivePoints(employeeId, incidentDate) {
|
function getPriorActivePoints(employeeId, incidentDate) {
|
||||||
const row = db.prepare(
|
const row = db.prepare(
|
||||||
`SELECT COALESCE(SUM(points),0) AS pts
|
`SELECT COALESCE(SUM(points),0) AS pts
|
||||||
@@ -116,9 +116,63 @@ app.post('/api/violations', (req, res) => {
|
|||||||
res.status(201).json({ id: result.lastInsertRowid });
|
res.status(201).json({ id: result.lastInsertRowid });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Negate / restore / delete endpoints unchanged ...
|
// ── Negate a violation ──────────────────────────────────────────────────────
|
||||||
|
app.patch('/api/violations/:id/negate', (req, res) => {
|
||||||
|
const { resolution_type, details, resolved_by } = req.body;
|
||||||
|
const id = req.params.id;
|
||||||
|
|
||||||
// PDF endpoint — use stored prior_active_points snapshot
|
const violation = db.prepare('SELECT * FROM violations WHERE id = ?').get(id);
|
||||||
|
if (!violation) return res.status(404).json({ error: 'Violation not found' });
|
||||||
|
|
||||||
|
// Mark negated
|
||||||
|
db.prepare('UPDATE violations SET negated = 1 WHERE id = ?').run(id);
|
||||||
|
|
||||||
|
// Upsert resolution record
|
||||||
|
const existing = db.prepare('SELECT id FROM violation_resolutions WHERE violation_id = ?').get(id);
|
||||||
|
if (existing) {
|
||||||
|
db.prepare(`
|
||||||
|
UPDATE violation_resolutions
|
||||||
|
SET resolution_type = ?, details = ?, resolved_by = ?, created_at = datetime('now')
|
||||||
|
WHERE violation_id = ?
|
||||||
|
`).run(resolution_type || 'Resolved', details || null, resolved_by || null, id);
|
||||||
|
} else {
|
||||||
|
db.prepare(`
|
||||||
|
INSERT INTO violation_resolutions (violation_id, resolution_type, details, resolved_by)
|
||||||
|
VALUES (?, ?, ?, ?)
|
||||||
|
`).run(id, resolution_type || 'Resolved', details || null, resolved_by || null);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({ success: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── Restore a negated violation ─────────────────────────────────────────────
|
||||||
|
app.patch('/api/violations/:id/restore', (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
|
||||||
|
const violation = db.prepare('SELECT * FROM violations WHERE id = ?').get(id);
|
||||||
|
if (!violation) return res.status(404).json({ error: 'Violation not found' });
|
||||||
|
|
||||||
|
db.prepare('UPDATE violations SET negated = 0 WHERE id = ?').run(id);
|
||||||
|
db.prepare('DELETE FROM violation_resolutions WHERE violation_id = ?').run(id);
|
||||||
|
|
||||||
|
res.json({ success: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── Hard delete a violation ─────────────────────────────────────────────────
|
||||||
|
app.delete('/api/violations/:id', (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
|
||||||
|
const violation = db.prepare('SELECT * FROM violations WHERE id = ?').get(id);
|
||||||
|
if (!violation) return res.status(404).json({ error: 'Violation not found' });
|
||||||
|
|
||||||
|
// Delete resolution first (FK safety)
|
||||||
|
db.prepare('DELETE FROM violation_resolutions WHERE violation_id = ?').run(id);
|
||||||
|
db.prepare('DELETE FROM violations WHERE id = ?').run(id);
|
||||||
|
|
||||||
|
res.json({ success: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── PDF endpoint ─────────────────────────────────────────────────────────────
|
||||||
app.get('/api/violations/:id/pdf', async (req, res) => {
|
app.get('/api/violations/:id/pdf', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const violation = db.prepare(`
|
const violation = db.prepare(`
|
||||||
@@ -130,14 +184,12 @@ app.get('/api/violations/:id/pdf', async (req, res) => {
|
|||||||
|
|
||||||
if (!violation) return res.status(404).json({ error: 'Violation not found' });
|
if (!violation) return res.status(404).json({ error: 'Violation not found' });
|
||||||
|
|
||||||
// For PDF, compute score row but pass stored prior_active_points so math is stable
|
|
||||||
const active = db.prepare('SELECT * FROM active_cpas_scores WHERE employee_id = ?')
|
const active = db.prepare('SELECT * FROM active_cpas_scores WHERE employee_id = ?')
|
||||||
.get(violation.employee_id) || { active_points: 0, violation_count: 0 };
|
.get(violation.employee_id) || { active_points: 0, violation_count: 0 };
|
||||||
|
|
||||||
const scoreForPdf = {
|
const scoreForPdf = {
|
||||||
employee_id: violation.employee_id,
|
employee_id: violation.employee_id,
|
||||||
// snapshot at time of violation (if present); fall back to current
|
active_points: violation.prior_active_points != null ? violation.prior_active_points : active.active_points,
|
||||||
active_points: violation.prior_active_points != null ? violation.prior_active_points : active.active_points,
|
|
||||||
violation_count: active.violation_count,
|
violation_count: active.violation_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user