diff --git a/server/routes/health.js b/server/routes/health.js index 3080730..75cde00 100644 --- a/server/routes/health.js +++ b/server/routes/health.js @@ -2,32 +2,113 @@ const express = require('express'); const router = express.Router(); const { getDatabase } = require('../db/init'); +// OFA tests that count toward GRCA eligibility +const GRCA_REQUIRED = ['hip_ofa', 'hip_pennhip', 'elbow_ofa', 'heart_ofa', 'heart_echo', 'eye_caer']; +const GRCA_CORE = { + hip: ['hip_ofa', 'hip_pennhip'], + elbow: ['elbow_ofa'], + heart: ['heart_ofa', 'heart_echo'], + eye: ['eye_caer'], +}; + +// Helper: compute clearance summary for a dog +function getClearanceSummary(db, dogId) { + const records = db.prepare(` + SELECT test_type, ofa_result, ofa_number, expires_at, test_date + FROM health_records + WHERE dog_id = ? AND test_type IS NOT NULL + ORDER BY test_date DESC + `).all(dogId); + + const today = new Date(); + const in90 = new Date(); in90.setDate(today.getDate() + 90); + + const summary = {}; + for (const [group, types] of Object.entries(GRCA_CORE)) { + const match = records.find(r => types.includes(r.test_type)); + if (!match) { + summary[group] = { status: 'missing', record: null }; + } else { + let status = 'pass'; + if (match.expires_at) { + const exp = new Date(match.expires_at); + if (exp < today) status = 'expired'; + else if (exp <= in90) status = 'expiring_soon'; + } + summary[group] = { status, record: match }; + } + } + return summary; +} + // GET all health records for a dog router.get('/dog/:dogId', (req, res) => { try { const db = getDatabase(); const records = db.prepare(` - SELECT * FROM health_records - WHERE dog_id = ? + SELECT * FROM health_records + WHERE dog_id = ? ORDER BY test_date DESC `).all(req.params.dogId); - res.json(records); } catch (error) { res.status(500).json({ error: error.message }); } }); +// GET clearance summary (Hip / Elbow / Heart / Eyes) for a dog +router.get('/dog/:dogId/clearance-summary', (req, res) => { + try { + const db = getDatabase(); + const dog = db.prepare('SELECT id, birth_date, chic_number FROM dogs WHERE id = ?').get(req.params.dogId); + if (!dog) return res.status(404).json({ error: 'Dog not found' }); + + const summary = getClearanceSummary(db, dog.id); + + // Age check: must be >= 24 months for hip/elbow + let ageEligible = false; + if (dog.birth_date) { + const months = (new Date() - new Date(dog.birth_date)) / (1000 * 60 * 60 * 24 * 30.44); + ageEligible = months >= 24; + } + + const allPass = Object.values(summary).every(s => ['pass', 'expiring_soon'].includes(s.status)); + const grca_eligible = allPass && ageEligible; + + res.json({ summary, grca_eligible, age_eligible: ageEligible, chic_number: dog.chic_number }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// GET CHIC eligibility check +router.get('/dog/:dogId/chic-eligible', (req, res) => { + try { + const db = getDatabase(); + const dog = db.prepare('SELECT id, chic_number FROM dogs WHERE id = ?').get(req.params.dogId); + if (!dog) return res.status(404).json({ error: 'Dog not found' }); + + const summary = getClearanceSummary(db, dog.id); + const missing = Object.entries(summary) + .filter(([, v]) => v.status === 'missing') + .map(([k]) => k); + + res.json({ + chic_eligible: missing.length === 0, + chic_number: dog.chic_number || null, + missing_tests: missing, + }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + // GET single health record router.get('/:id', (req, res) => { try { const db = getDatabase(); const record = db.prepare('SELECT * FROM health_records WHERE id = ?').get(req.params.id); - - if (!record) { - return res.status(404).json({ error: 'Health record not found' }); - } - + if (!record) return res.status(404).json({ error: 'Health record not found' }); res.json(record); } catch (error) { res.status(500).json({ error: error.message }); @@ -37,20 +118,30 @@ router.get('/:id', (req, res) => { // POST create health record router.post('/', (req, res) => { try { - const { dog_id, record_type, test_name, test_date, result, document_url, notes } = req.body; - + const { + dog_id, record_type, test_type, test_name, test_date, + ofa_result, ofa_number, performed_by, expires_at, + document_url, result, vet_name, next_due, notes + } = req.body; + if (!dog_id || !record_type || !test_date) { - return res.status(400).json({ error: 'Dog ID, record type, and test date are required' }); + return res.status(400).json({ error: 'dog_id, record_type, and test_date are required' }); } - + const db = getDatabase(); const dbResult = db.prepare(` - INSERT INTO health_records (dog_id, record_type, test_name, test_date, result, document_url, notes) - VALUES (?, ?, ?, ?, ?, ?, ?) - `).run(dog_id, record_type, test_name, test_date, result, document_url, notes); - + INSERT INTO health_records + (dog_id, record_type, test_type, test_name, test_date, + ofa_result, ofa_number, performed_by, expires_at, + document_url, result, vet_name, next_due, notes) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `).run( + dog_id, record_type, test_type || null, test_name || null, test_date, + ofa_result || null, ofa_number || null, performed_by || null, expires_at || null, + document_url || null, result || null, vet_name || null, next_due || null, notes || null + ); + const record = db.prepare('SELECT * FROM health_records WHERE id = ?').get(dbResult.lastInsertRowid); - res.status(201).json(record); } catch (error) { res.status(500).json({ error: error.message }); @@ -60,15 +151,27 @@ router.post('/', (req, res) => { // PUT update health record router.put('/:id', (req, res) => { try { - const { record_type, test_name, test_date, result, document_url, notes } = req.body; - + const { + record_type, test_type, test_name, test_date, + ofa_result, ofa_number, performed_by, expires_at, + document_url, result, vet_name, next_due, notes + } = req.body; + const db = getDatabase(); db.prepare(` - UPDATE health_records - SET record_type = ?, test_name = ?, test_date = ?, result = ?, document_url = ?, notes = ? + UPDATE health_records + SET record_type = ?, test_type = ?, test_name = ?, test_date = ?, + ofa_result = ?, ofa_number = ?, performed_by = ?, expires_at = ?, + document_url = ?, result = ?, vet_name = ?, next_due = ?, notes = ?, + updated_at = datetime('now') WHERE id = ? - `).run(record_type, test_name, test_date, result, document_url, notes, req.params.id); - + `).run( + record_type, test_type || null, test_name || null, test_date, + ofa_result || null, ofa_number || null, performed_by || null, expires_at || null, + document_url || null, result || null, vet_name || null, next_due || null, notes || null, + req.params.id + ); + const record = db.prepare('SELECT * FROM health_records WHERE id = ?').get(req.params.id); res.json(record); } catch (error) { @@ -87,4 +190,4 @@ router.delete('/:id', (req, res) => { } }); -module.exports = router; \ No newline at end of file +module.exports = router;