CREATE TABLE pm_encounters (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID NOT NULL REFERENCES pf_organizations(id),
patient_id UUID NOT NULL,
appointment_id UUID REFERENCES pm_appointments(id),
encounter_date DATE NOT NULL,
encounter_type TEXT NOT NULL CHECK (encounter_type IN (
'outpatient', 'residential_daily', 'iop', 'php',
'crisis', 'group', 'telehealth', 'evaluation'
)),
status TEXT NOT NULL DEFAULT 'scheduled' CHECK (status IN (
'scheduled', 'checked_in', 'in_progress', 'documented',
'charge_captured', 'billed', 'cancelled', 'no_show'
)),
rendering_provider_id UUID NOT NULL,
supervising_provider_id UUID,
service_location_id UUID,
place_of_service TEXT NOT NULL DEFAULT '11',
-- Populated by CL-04 via event
clinical_note_id UUID,
note_finalized_at TIMESTAMPTZ,
-- Populated by PM-07 via charge capture
charge_id UUID,
charge_captured_at TIMESTAMPTZ,
-- Populated by PM-08 via claim submission
claim_id UUID,
-- Standard columns
custom_fields JSONB DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
created_by UUID REFERENCES pf_profiles(id),
updated_by UUID REFERENCES pf_profiles(id),
deleted_at TIMESTAMPTZ
);
-- Indexes
CREATE INDEX idx_pm_encounters_org ON pm_encounters(organization_id);
CREATE INDEX idx_pm_encounters_patient ON pm_encounters(organization_id, patient_id);
CREATE INDEX idx_pm_encounters_date ON pm_encounters(organization_id, encounter_date);
CREATE INDEX idx_pm_encounters_status ON pm_encounters(organization_id, status)
WHERE deleted_at IS NULL;
-- RLS
ALTER TABLE pm_encounters ENABLE ROW LEVEL SECURITY;
ALTER TABLE pm_encounters FORCE ROW LEVEL SECURITY;
-- Uses pf_has_org_access SECURITY DEFINER helper (never query RLS-protected tables in policies)
CREATE POLICY pm_encounters_select ON pm_encounters
FOR SELECT USING (pf_has_org_access(organization_id, auth.uid()));
CREATE POLICY pm_encounters_insert ON pm_encounters
FOR INSERT WITH CHECK (pf_has_org_access(organization_id, auth.uid()));
CREATE POLICY pm_encounters_update ON pm_encounters
FOR UPDATE
USING (pf_has_org_access(organization_id, auth.uid()))
WITH CHECK (pf_has_org_access(organization_id, auth.uid()));
CREATE POLICY pm_encounters_delete ON pm_encounters
FOR DELETE USING (pf_is_org_admin(auth.uid(), organization_id));