diff --git a/lib/incidents/dosh.ts b/lib/incidents/dosh.ts new file mode 100644 index 0000000..b9bcba1 --- /dev/null +++ b/lib/incidents/dosh.ts @@ -0,0 +1,49 @@ +export type DoshObligation = { + requires_jkkp6: boolean + requires_jkkp7: boolean + requires_jkkp8: boolean + requires_immediate_notification: boolean + reasons: string[] +} + +export function computeDoshObligation(incident: { + is_fatality: boolean + is_serious_bodily_injury: boolean + is_dangerous_occurrence: boolean + is_occupational_disease: boolean + lost_days: number | null +}): DoshObligation { + const reasons: string[] = [] + let requires_jkkp6 = false + let requires_jkkp7 = false + let requires_jkkp8 = false + let requires_immediate_notification = false + + if (incident.is_fatality) { + reasons.push('Fatality — NADOPOD 2004 s.9(1)(a)') + requires_jkkp6 = true + requires_jkkp7 = true + requires_immediate_notification = true + } + if (incident.is_serious_bodily_injury) { + reasons.push('Serious bodily injury — NADOPOD 2004 s.9(1)(b)') + requires_jkkp6 = true + requires_jkkp7 = true + } + if (incident.is_dangerous_occurrence) { + reasons.push('Dangerous occurrence — NADOPOD 2004 s.9(1)(c)') + requires_jkkp6 = true + requires_jkkp7 = true + } + if ((incident.lost_days ?? 0) >= 4) { + reasons.push('Lost-time injury ≥4 days — NADOPOD 2004 s.9(1)(d)') + requires_jkkp6 = true + requires_jkkp7 = true + } + if (incident.is_occupational_disease) { + reasons.push('Occupational disease — NADOPOD 2004 s.11') + requires_jkkp8 = true + } + + return { requires_jkkp6, requires_jkkp7, requires_jkkp8, requires_immediate_notification, reasons } +} diff --git a/tests/lib/incidents/dosh.test.ts b/tests/lib/incidents/dosh.test.ts new file mode 100644 index 0000000..c2acc85 --- /dev/null +++ b/tests/lib/incidents/dosh.test.ts @@ -0,0 +1,78 @@ +import { describe, it, expect } from 'vitest' +import { computeDoshObligation } from '@/lib/incidents/dosh' + +const base = { + is_fatality: false, + is_serious_bodily_injury: false, + is_dangerous_occurrence: false, + is_occupational_disease: false, + lost_days: null, +} + +describe('computeDoshObligation', () => { + it('returns no obligations for minor incident', () => { + const result = computeDoshObligation(base) + expect(result.requires_jkkp6).toBe(false) + expect(result.requires_jkkp7).toBe(false) + expect(result.requires_jkkp8).toBe(false) + expect(result.requires_immediate_notification).toBe(false) + expect(result.reasons).toHaveLength(0) + }) + + it('fatality triggers jkkp6, jkkp7, immediate notification', () => { + const result = computeDoshObligation({ ...base, is_fatality: true }) + expect(result.requires_jkkp6).toBe(true) + expect(result.requires_jkkp7).toBe(true) + expect(result.requires_immediate_notification).toBe(true) + expect(result.requires_jkkp8).toBe(false) + expect(result.reasons).toContain('Fatality — NADOPOD 2004 s.9(1)(a)') + }) + + it('serious bodily injury triggers jkkp6 + jkkp7, not immediate', () => { + const result = computeDoshObligation({ ...base, is_serious_bodily_injury: true }) + expect(result.requires_jkkp6).toBe(true) + expect(result.requires_jkkp7).toBe(true) + expect(result.requires_immediate_notification).toBe(false) + expect(result.reasons).toContain('Serious bodily injury — NADOPOD 2004 s.9(1)(b)') + }) + + it('dangerous occurrence triggers jkkp6 + jkkp7', () => { + const result = computeDoshObligation({ ...base, is_dangerous_occurrence: true }) + expect(result.requires_jkkp6).toBe(true) + expect(result.requires_jkkp7).toBe(true) + expect(result.requires_immediate_notification).toBe(false) + expect(result.reasons).toContain('Dangerous occurrence — NADOPOD 2004 s.9(1)(c)') + }) + + it('occupational disease triggers jkkp8 only', () => { + const result = computeDoshObligation({ ...base, is_occupational_disease: true }) + expect(result.requires_jkkp8).toBe(true) + expect(result.requires_jkkp6).toBe(false) + expect(result.requires_jkkp7).toBe(false) + expect(result.reasons).toContain('Occupational disease — NADOPOD 2004 s.11') + }) + + it('4+ lost days triggers jkkp6 + jkkp7', () => { + const result = computeDoshObligation({ ...base, lost_days: 4 }) + expect(result.requires_jkkp6).toBe(true) + expect(result.requires_jkkp7).toBe(true) + expect(result.reasons).toContain('Lost-time injury ≥4 days — NADOPOD 2004 s.9(1)(d)') + }) + + it('3 lost days does NOT trigger JKKP reporting', () => { + const result = computeDoshObligation({ ...base, lost_days: 3 }) + expect(result.requires_jkkp6).toBe(false) + expect(result.requires_jkkp7).toBe(false) + }) + + it('multiple flags accumulate reasons', () => { + const result = computeDoshObligation({ + ...base, + is_fatality: true, + is_occupational_disease: true, + }) + expect(result.requires_jkkp6).toBe(true) + expect(result.requires_jkkp8).toBe(true) + expect(result.reasons).toHaveLength(2) + }) +})