← back to AbramsOS
routes/claims.js
82 lines
const express = require('express');
const db = require('../lib/db');
const audit = require('../lib/audit');
const strategist = require('../lib/claim-strategist');
const router = express.Router();
const DEV_USER_ID = 'user_steve';
// HTML — list view
router.get('/claims', async (_req, res) => {
const r = await db.query(
`SELECT id, claim_type, routing, state, draft_subject, due_at, created_at, asset_table, asset_id
FROM claim_case WHERE user_id = $1 ORDER BY created_at DESC LIMIT 200`,
[DEV_USER_ID]
);
// Household names to suggest against the CA unclaimed-property search.
// Defensive: never let a missing/renamed table break the claims page.
let household = [];
try {
const p = await db.query(
`SELECT full_name FROM person WHERE user_id = $1 AND full_name IS NOT NULL ORDER BY (relation <> 'self'), full_name`,
[DEV_USER_ID]
);
household = p.rows.map(x => x.full_name).filter(Boolean);
} catch (_e) { household = []; }
res.render('claims', { claims: r.rows, household });
});
// HTML — detail view
router.get('/claims/:id', async (req, res) => {
const c = await db.query(`SELECT * FROM claim_case WHERE id = $1 AND user_id = $2`, [req.params.id, DEV_USER_ID]);
if (!c.rows.length) return res.status(404).render('error', { error: 'claim not found' });
const a = await db.query(`SELECT * FROM action_queue WHERE case_id = $1 ORDER BY created_at`, [req.params.id]);
res.render('claim-detail', { claim: c.rows[0], actions: a.rows });
});
router.get('/api/claims', async (_req, res) => {
const r = await db.query(
`SELECT id, claim_type, routing, state, draft_subject, due_at, created_at, asset_table, asset_id
FROM claim_case WHERE user_id = $1 ORDER BY created_at DESC LIMIT 200`,
[DEV_USER_ID]
);
res.json(r.rows);
});
router.get('/api/claims/:id', async (req, res) => {
const r = await db.query(`SELECT * FROM claim_case WHERE id = $1 AND user_id = $2`, [req.params.id, DEV_USER_ID]);
if (!r.rows.length) return res.status(404).json({ error: 'claim not found' });
const actions = await db.query(`SELECT * FROM action_queue WHERE case_id = $1 ORDER BY created_at`, [req.params.id]);
res.json({ ...r.rows[0], actions: actions.rows });
});
router.post('/api/claims/from-reminder/:id', async (req, res) => {
try {
const { caseId, claim } = await strategist.fromReminder(req.params.id, DEV_USER_ID);
res.json({ ok: true, case_id: caseId, claim });
} catch (err) {
res.status(400).json({ error: err.message });
}
});
// Approve an action — but DON'T execute. Steve still has to physically click "send" elsewhere.
// This just flips the gate; sending happens in a future tick when we wire George email.
router.post('/api/claims/:caseId/actions/:actionId/approve', async (req, res) => {
const { caseId, actionId } = req.params;
await db.query(
`UPDATE action_queue SET state = 'approved' WHERE id = $1 AND case_id = $2 AND state = 'pending'`,
[actionId, caseId]
);
await audit.log({
actorType: 'user',
actorId: DEV_USER_ID,
objectType: 'action_queue',
objectId: actionId,
eventType: 'action_approved',
metadata: { case_id: caseId },
});
res.json({ ok: true });
});
module.exports = router;