feat: DOSH obligation pure function with NADOPOD 2004 rules
This commit is contained in:
@@ -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 }
|
||||
}
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user