feat(db): phase 4 group 3 — incident routes to Drizzle
Convert all 11 incident API routes from Supabase PostgREST to Drizzle ORM with withUser/asAdmin/writeAuditLog patterns and RLS enforcement. Only uploadEvidenceFile retains supabase client (Phase 5 storage work). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { createClient } from '@/lib/supabase/server'
|
||||
import { aliasedTable } from 'drizzle-orm'
|
||||
import { getSession } from '@/lib/auth/get-session'
|
||||
import { withUser } from '@/lib/db/with-user'
|
||||
import { incidents, sites, users } from '@/lib/db/schema'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { buildJkkp6Pdf, buildJkkp7Pdf, type JkkpIncident } from '@/lib/pdf/jkkp'
|
||||
import { computeDoshObligation } from '@/lib/incidents/dosh'
|
||||
|
||||
@@ -20,44 +23,55 @@ export async function GET(
|
||||
if (!['hse', 'admin'].includes(session.role))
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
|
||||
|
||||
const supabase = await createClient()
|
||||
const reporterAlias = aliasedTable(users, 'reporter')
|
||||
|
||||
const { data: incident } = await supabase
|
||||
.from('incidents')
|
||||
.select(`
|
||||
reference_no, incident_type, description, reported_at, severity, lost_days,
|
||||
is_fatality, is_serious_bodily_injury, is_dangerous_occurrence, is_occupational_disease,
|
||||
sites (name),
|
||||
reporter:users!reported_by (name)
|
||||
`)
|
||||
.eq('id', id)
|
||||
.single()
|
||||
const [incident] = await withUser(session.sub, async tx =>
|
||||
tx.select({
|
||||
referenceNo: incidents.referenceNo,
|
||||
incidentType: incidents.incidentType,
|
||||
description: incidents.description,
|
||||
reportedAt: incidents.reportedAt,
|
||||
severity: incidents.severity,
|
||||
lostDays: incidents.lostDays,
|
||||
isFatality: incidents.isFatality,
|
||||
isSeriousBodilyInjury: incidents.isSeriousBodilyInjury,
|
||||
isDangerousOccurrence: incidents.isDangerousOccurrence,
|
||||
isOccupationalDisease: incidents.isOccupationalDisease,
|
||||
siteName: sites.name,
|
||||
reporterName: reporterAlias.name,
|
||||
})
|
||||
.from(incidents)
|
||||
.leftJoin(sites, eq(incidents.siteId, sites.id))
|
||||
.leftJoin(reporterAlias, eq(incidents.reportedBy, reporterAlias.id))
|
||||
.where(eq(incidents.id, id))
|
||||
.limit(1)
|
||||
)
|
||||
|
||||
if (!incident) return NextResponse.json({ error: 'Not found' }, { status: 404 })
|
||||
|
||||
const dosh = computeDoshObligation({
|
||||
is_fatality: (incident as { is_fatality: boolean }).is_fatality,
|
||||
is_serious_bodily_injury: (incident as { is_serious_bodily_injury: boolean }).is_serious_bodily_injury,
|
||||
is_dangerous_occurrence: (incident as { is_dangerous_occurrence: boolean }).is_dangerous_occurrence,
|
||||
is_occupational_disease: (incident as { is_occupational_disease: boolean }).is_occupational_disease,
|
||||
lost_days: (incident as { lost_days: number | null }).lost_days,
|
||||
is_fatality: incident.isFatality,
|
||||
is_serious_bodily_injury: incident.isSeriousBodilyInjury,
|
||||
is_dangerous_occurrence: incident.isDangerousOccurrence,
|
||||
is_occupational_disease: incident.isOccupationalDisease,
|
||||
lost_days: incident.lostDays,
|
||||
})
|
||||
|
||||
const required = form === 'jkkp6' ? dosh.requires_jkkp6 : dosh.requires_jkkp7
|
||||
if (!required) return NextResponse.json({ error: 'This form is not required for this incident' }, { status: 400 })
|
||||
|
||||
const jkkpIncident: JkkpIncident = {
|
||||
reference_no: (incident as { reference_no: string | null }).reference_no,
|
||||
incident_type: (incident as { incident_type: string }).incident_type,
|
||||
description: (incident as { description: string }).description,
|
||||
reported_at: (incident as { reported_at: string }).reported_at,
|
||||
severity: (incident as { severity: number | null }).severity,
|
||||
is_fatality: (incident as { is_fatality: boolean }).is_fatality,
|
||||
is_serious_bodily_injury: (incident as { is_serious_bodily_injury: boolean }).is_serious_bodily_injury,
|
||||
is_dangerous_occurrence: (incident as { is_dangerous_occurrence: boolean }).is_dangerous_occurrence,
|
||||
lost_days: (incident as { lost_days: number | null }).lost_days,
|
||||
site_name: (incident.sites as unknown as { name: string } | null)?.name ?? 'Unknown',
|
||||
reporter_name: (incident.reporter as unknown as { name: string } | null)?.name ?? 'Unknown',
|
||||
reference_no: incident.referenceNo,
|
||||
incident_type: incident.incidentType,
|
||||
description: incident.description,
|
||||
reported_at: incident.reportedAt instanceof Date ? incident.reportedAt.toISOString() : (incident.reportedAt as string),
|
||||
severity: incident.severity,
|
||||
is_fatality: incident.isFatality,
|
||||
is_serious_bodily_injury: incident.isSeriousBodilyInjury,
|
||||
is_dangerous_occurrence: incident.isDangerousOccurrence,
|
||||
lost_days: incident.lostDays,
|
||||
site_name: incident.siteName ?? 'Unknown',
|
||||
reporter_name: incident.reporterName ?? 'Unknown',
|
||||
}
|
||||
|
||||
const pdfBytes = form === 'jkkp6'
|
||||
|
||||
Reference in New Issue
Block a user