-- supabase/migrations/20260709000003_incidents.sql CREATE TYPE incident_type AS ENUM ( 'injury', 'near_miss', 'hazard', 'asset_damage', 'environmental', 'security', 'fire' ); CREATE TYPE incident_status AS ENUM ( 'reported', 'triaged', 'investigating', 'capa_pending', 'verification', 'closed' ); CREATE TYPE medical_status AS ENUM ( 'none', 'first_aid', 'medical_treatment', 'lti' ); CREATE TABLE incidents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), reference_no TEXT UNIQUE, incident_type incident_type NOT NULL, site_id UUID NOT NULL REFERENCES sites(id), zone_id UUID REFERENCES zones(id), reported_by UUID NOT NULL REFERENCES users(id), reported_at TIMESTAMPTZ NOT NULL DEFAULT now(), description TEXT NOT NULL, severity SMALLINT CHECK (severity BETWEEN 1 AND 5), status incident_status NOT NULL DEFAULT 'reported', injury_involved BOOLEAN NOT NULL DEFAULT false, asset_involved BOOLEAN NOT NULL DEFAULT false, medical_status medical_status, lost_days INT CHECK (lost_days >= 0), closed_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- Auto-generate reference_no: SITECODE-YYYYMM-#### (e.g. SCW1-202607-0001) CREATE OR REPLACE FUNCTION public.generate_incident_reference() RETURNS TRIGGER LANGUAGE plpgsql AS $$ DECLARE v_site_code TEXT; v_month TEXT; v_seq INT; BEGIN SELECT UPPER(REGEXP_REPLACE(SUBSTRING(name, 1, 6), '[^A-Za-z0-9]', '', 'g')) INTO v_site_code FROM sites WHERE id = NEW.site_id; v_month := TO_CHAR(NEW.reported_at, 'YYYYMM'); SELECT COUNT(*) + 1 INTO v_seq FROM incidents WHERE site_id = NEW.site_id AND TO_CHAR(reported_at, 'YYYYMM') = v_month; NEW.reference_no := v_site_code || '-' || v_month || '-' || LPAD(v_seq::TEXT, 4, '0'); RETURN NEW; END; $$; CREATE TRIGGER set_incident_reference BEFORE INSERT ON incidents FOR EACH ROW WHEN (NEW.reference_no IS NULL) EXECUTE FUNCTION public.generate_incident_reference(); CREATE INDEX incidents_site_id_idx ON incidents(site_id); CREATE INDEX incidents_reported_by_idx ON incidents(reported_by); CREATE INDEX incidents_status_idx ON incidents(status);