feat: screening & intake database schema (Epic 1)

Implements complete database schema for screening and intake workflow:

Database additions:
- 7 new tables: screenings, screening_activities, screening_documents,
  intakes, anamneses, examinations, risk_assessments
- Extended patients table with status (episode_status) and is_john_doe
- Extended encounters table with intake_id for linking
- Extended care_plans with intake reference columns

Architecture:
- Separate tables for reusable content (anamneses, examinations, risk_assessments)
- JSONB fields for context-bound data (kindcheck_data, treatment_advice)
- RLS policies, indexes, and updated_at triggers on all new tables
- Helper view: active_intakes_overview

Generated TypeScript types from schema for type-safe database access.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
colinislit
2025-11-22 13:45:37 +01:00
parent 3cb60e6a0b
commit 4caab6a8ca
4 changed files with 2148 additions and 4 deletions

View File

@@ -0,0 +1,137 @@
# 🚀 Mission Control — Bouwplan Screening & Intake
💡 **Tip:** Dit document is opgesteld op basis van `fo-screening-intake-v1_0.md`.
---
**Projectnaam:** AI Speedrun - Mini EPD v1.2
**Versie:** v1.0
**Datum:** 22-11-2025
**Auteur:** Antigravity (i.s.m. Colin)
---
## 1. Doel en context
🎯 **Doel:** Het realiseren van de volledige screening- en intakeflow voor GGZ-professionals, van aanmelding tot behandeladvies.
📘 **Toelichting:** Dit bouwplan vertaalt het Functioneel Ontwerp (FO) naar concrete ontwikkelstappen. De focus ligt op het bouwen van de fundering (zonder AI in eerste instantie) zodat cliënten kunnen worden geregistreerd, gescreend en geïntaked volgens de specificaties.
---
## 2. Uitgangspunten
### 2.1 Technische Stack
- **Frontend:** Next.js (App Router) + Tailwind CSS + Lucide Icons
- **Backend:** Supabase (PostgreSQL + Auth)
- **State Management:** React Query / Server Actions
- **UI Library:** shadcn/ui (of vergelijkbaar)
### 2.2 Projectkaders
- **Scope:** Zoals beschreven in FO v1.0 (MVP).
- **Data:** Gebruik van Supabase voor persistentie.
- **AI:** Nog niet in scope voor deze fase (komt in latere iteratie).
### 2.3 Programmeer Uitgangspunten
- **DRY & SOC:** Strikte scheiding tussen UI en data-fetching (Server Actions / Services).
- **Types:** Volledig getypeerd met TypeScript (Database types genereren uit Supabase).
- **Componenten:** Herbruikbare componenten voor veelvoorkomende patronen (bijv. `SectionCard`, `StatusBadge`).
---
## 3. Epics & Stories Overzicht
| Epic ID | Titel | Doel | Status | Stories |
|---------|-------|------|--------|---------|
| E1 | Database & Types | Datamodel implementeren in Supabase | ✅ Done | 3 |
| E2 | Cliëntenbeheer | Lijstweergave en aanmaken cliënten | ⏳ To Do | 3 |
| E3 | Screening Module | Screening tab en functionaliteit | ⏳ To Do | 4 |
| E4 | Intake Core | Intake overzicht en navigatie | ⏳ To Do | 3 |
| E5 | Intake Details | Specifieke tabbladen (Contact, Risico, etc.) | ⏳ To Do | 5 |
| E6 | Diagnose & Advies | Diagnose stelling en behandeladvies | ⏳ To Do | 3 |
---
## 4. Epics & Stories (Uitwerking)
### Epic 1 — Database & Types
**Doel:** Een solide datamodel in Supabase dat voldoet aan de eisen uit het FO.
| Story ID | Beschrijving | Acceptatiecriteria |
|----------|--------------|---------------------|
| E1.S1 | Tabellen aanmaken | ✅ Migration `20251122_screening_intake_schema.sql` aangemaakt met:<br>- Patient status kolom (`episode_status` enum)<br>- Screening module (3 tabellen: `screenings`, `screening_activities`, `screening_documents`)<br>- Intake module (4 tabellen: `intakes`, `anamneses`, `examinations`, `risk_assessments`)<br>- `encounters` tabel uitgebreid met `intake_id` kolom<br>- `care_plans` uitgebreid met intake referenties |
| E1.S2 | Migration toepassen | Migration succesvol toegepast op Supabase database met:<br>- Foreign keys en constraints<br>- RLS policies voor alle nieuwe tabellen<br>- Indexes voor performance<br>- Triggers voor `updated_at` timestamps |
| E1.S3 | TypeScript Types genereren | Types gegenereerd met `supabase gen types` en geëxporteerd naar `lib/supabase/database.types.ts` |
### Epic 2 — Cliëntenbeheer (Level 1)
**Doel:** Behandelaars kunnen cliënten vinden en nieuwe cliënten aanmaken.
| Story ID | Beschrijving | Acceptatiecriteria |
|----------|--------------|---------------------|
| E2.S1 | Cliëntenlijst | Tabel met zoekfunctie, filters en status badges. |
| E2.S2 | Nieuwe Cliënt Flow | Formulier voor aanmaken cliënt (incl. John Doe logica). |
| E2.S3 | Cliënt Header & Nav | Context-aware header en sidebar navigatie (Level 2). |
### Epic 3 — Screening Module (Level 2)
**Doel:** Faciliteren van het screeningsproces.
| Story ID | Beschrijving | Acceptatiecriteria |
|----------|--------------|---------------------|
| E3.S1 | Activiteitenlog | Tijdlijn component met toevoeg-functionaliteit. |
| E3.S2 | Documenten & Hulpvraag | Upload functionaliteit en tekstveld voor hulpvraag. |
| E3.S3 | Screeningsbesluit | Formulier voor besluit (geschikt/niet geschikt) + status update logica. |
| E3.S4 | Basisgegevens Tab | Read-only weergave met edit-modus voor NAW gegevens. |
### Epic 4 — Intake Core (Level 2)
**Doel:** Beheer van intakes (meerdere per cliënt mogelijk).
| Story ID | Beschrijving | Acceptatiecriteria |
|----------|--------------|---------------------|
| E4.S1 | Intake Overzicht | Kaartweergave van alle intakes per cliënt. |
| E4.S2 | Nieuwe Intake | Modal/page voor starten nieuwe intake. |
| E4.S3 | Intake Layout | Sub-navigatie (tabs) binnen een specifieke intake. |
### Epic 5 — Intake Details (Tabs)
**Doel:** Inhoudelijke registratie van de intake.
| Story ID | Beschrijving | Acceptatiecriteria |
|----------|--------------|---------------------|
| E5.S1 | Tab Algemeen | Overzicht van intake details, status en notities. |
| E5.S2 | Tab Contactmomenten | CRUD voor contactmomenten (datum, type, verslag). |
| E5.S3 | Tab Kindcheck | Formulier voor kindcheck registratie. |
| E5.S4 | Tab Risicotaxatie | Formulier voor risico-inschatting. |
| E5.S5 | Tabs Anamnese, Onderzoek, ROM | Generieke of specifieke formulieren voor deze onderdelen. |
### Epic 6 — Diagnose & Advies
**Doel:** Afronding van de intake met diagnose en advies.
| Story ID | Beschrijving | Acceptatiecriteria |
|----------|--------------|---------------------|
| E6.S1 | Diagnose Tab | Toevoegen DSM-5 diagnoses (code, ernst, toelichting). |
| E6.S2 | Behandeladvies Tab | Rich text editor voor advies + doorzet-logica. |
| E6.S3 | Intake Afronding | Status transitie naar 'Afgerond' en update cliënt status. |
---
## 5. Kwaliteit & Testplan
### Test Types
- **Unit Tests:** Voor complexe validatielogica (bijv. BSN check).
- **Manual Testing:** Doorlopen van de volledige flow van 'Nieuwe Cliënt' tot 'Intake Afgerond'.
### Manual Test Checklist
- [ ] Nieuwe cliënt aanmaken (John Doe & Regulier).
- [ ] Screening doorlopen en besluit nemen.
- [ ] Intake starten en contactmoment toevoegen.
- [ ] Diagnose toevoegen en behandeladvies opstellen.
- [ ] Intake afronden en controleren of status update.
---
## 6. Risico's & Mitigatie
| Risico | Mitigatie |
|--------|-----------|
| Complexiteit datamodel | Starten met strikte types en ERD validatie. |
| Navigatie diepte (Level 3?) | Duidelijke breadcrumbs en 'terug' knoppen implementeren. |
| Performance bij veel data | Paginering op lijsten en lazy loading van tabs. |
---

View File

@@ -1,4 +0,0 @@
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://claude.ai/chat/904d781b-2ce6-4f3b-9863-0c70dbdce984
HostUrl=https://claude.ai/api/organizations/8a590403-7491-4913-ae4f-e0085c8dfb82/conversations/904d781b-2ce6-4f3b-9863-0c70dbdce984/wiggle/download-file?path=%2Fmnt%2Fuser-data%2Foutputs%2Ffo-screening-intake-v1_0.md

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,422 @@
-- ============================================================================
-- SCREENING & INTAKE SCHEMA - Mini EPD v1.2
-- ============================================================================
-- Created: 2025-11-22
-- Purpose: Complete database schema for screening and intake workflow
-- Based on: FO v1.0 Chapter 10 (Data Requirements)
--
-- Architecture decisions:
-- - Separate tables for reusable content (anamneses, examinations, risk_assessments)
-- - JSONB for context-bound data (kindcheck, treatment_advice)
-- - Reuse existing FHIR tables where possible (observations, conditions, encounters)
-- ============================================================================
-- ============================================================================
-- STEP 1: Add patient status for EpisodeOfCare workflow
-- ============================================================================
-- Create enum for patient/episode status (FHIR EpisodeOfCare.status)
CREATE TYPE episode_status AS ENUM (
'planned', -- Aangemeld / In screening
'active', -- Intake t/m behandeling (in zorg)
'finished', -- Behandeling afgerond
'cancelled' -- Niet geschikt / afgemeld
);
-- Add status column to patients table
ALTER TABLE patients
ADD COLUMN IF NOT EXISTS status episode_status DEFAULT 'planned',
ADD COLUMN IF NOT EXISTS is_john_doe BOOLEAN DEFAULT false;
-- Add index for status filtering
CREATE INDEX IF NOT EXISTS idx_patients_status ON patients(status);
COMMENT ON COLUMN patients.status IS 'Episode of care status: planned (screening) → active (in zorg) → finished/cancelled';
COMMENT ON COLUMN patients.is_john_doe IS 'Crisis admission without complete personal data (BSN optional)';
-- ============================================================================
-- STEP 2: Screening module tables
-- ============================================================================
-- 2.1 Main screening table (FO 10.2)
CREATE TABLE IF NOT EXISTS screenings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
patient_id UUID NOT NULL REFERENCES patients(id) ON DELETE CASCADE,
-- Hulpvraag (FO 4.3 Sectie 3)
request_for_help TEXT,
-- Screeningsbesluit (FO 4.3 Sectie 4)
decision TEXT CHECK (decision IN ('geschikt', 'niet_geschikt')),
decision_department TEXT, -- Volwassenen, Jeugd, Forensisch, Verslaving, Ouderen, FACT
decision_notes TEXT,
decision_date TIMESTAMPTZ,
decision_by UUID REFERENCES practitioners(id),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_screenings_patient ON screenings(patient_id);
CREATE INDEX idx_screenings_decision ON screenings(decision);
COMMENT ON TABLE screenings IS 'Screening process per patient: request for help, activities, documents, and decision';
-- Enable RLS
ALTER TABLE screenings ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable read for authenticated users" ON screenings
FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "Enable insert for authenticated users" ON screenings
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "Enable update for authenticated users" ON screenings
FOR UPDATE USING (auth.role() = 'authenticated');
-- 2.2 Screening activities / timeline (FO 10.3)
CREATE TABLE IF NOT EXISTS screening_activities (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
screening_id UUID NOT NULL REFERENCES screenings(id) ON DELETE CASCADE,
activity_text TEXT NOT NULL,
created_by UUID REFERENCES practitioners(id),
created_by_name TEXT, -- Denormalized for display
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_screening_activities_screening ON screening_activities(screening_id);
CREATE INDEX idx_screening_activities_created_at ON screening_activities(created_at DESC);
COMMENT ON TABLE screening_activities IS 'Activity log / timeline during screening process (FO 4.3 Sectie 1)';
-- Enable RLS
ALTER TABLE screening_activities ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable read for authenticated users" ON screening_activities
FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "Enable insert for authenticated users" ON screening_activities
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
-- 2.3 Screening documents (FO 10.4)
CREATE TABLE IF NOT EXISTS screening_documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
screening_id UUID NOT NULL REFERENCES screenings(id) ON DELETE CASCADE,
file_name TEXT NOT NULL,
file_type TEXT, -- PDF, DOC, DOCX, JPG, PNG
file_size INTEGER, -- bytes
file_path TEXT, -- Storage path or URL
document_type TEXT CHECK (document_type IN ('verwijsbrief', 'verhuisbericht', 'indicatie', 'overig')),
uploaded_by UUID REFERENCES practitioners(id),
uploaded_by_name TEXT, -- Denormalized
uploaded_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_screening_documents_screening ON screening_documents(screening_id);
COMMENT ON TABLE screening_documents IS 'Uploaded documents during screening (referral letters, etc.)';
-- Enable RLS
ALTER TABLE screening_documents ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable read for authenticated users" ON screening_documents
FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "Enable insert for authenticated users" ON screening_documents
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "Enable delete for authenticated users" ON screening_documents
FOR DELETE USING (auth.role() = 'authenticated');
-- ============================================================================
-- STEP 3: Intake module tables
-- ============================================================================
-- 3.1 Main intake table (FO 10.5)
CREATE TABLE IF NOT EXISTS intakes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
patient_id UUID NOT NULL REFERENCES patients(id) ON DELETE CASCADE,
-- Intake metadata
title TEXT NOT NULL, -- "Aanvang zorg", "Overplaatsing Forensisch"
department TEXT NOT NULL, -- Volwassenen, Jeugd, Forensisch, etc.
psychologist_id UUID REFERENCES practitioners(id),
-- Status and dates
status TEXT NOT NULL DEFAULT 'bezig' CHECK (status IN ('bezig', 'afgerond')),
start_date DATE NOT NULL DEFAULT CURRENT_DATE,
end_date DATE,
-- General notes (FO 4.4.3)
notes TEXT,
-- Context-bound data (JSONB for flexibility)
kindcheck_data JSONB DEFAULT '{}',
treatment_advice JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_intakes_patient ON intakes(patient_id);
CREATE INDEX idx_intakes_status ON intakes(status);
CREATE INDEX idx_intakes_psychologist ON intakes(psychologist_id);
COMMENT ON TABLE intakes IS 'Intake sessions per patient (multiple possible per patient, e.g., department transfer)';
COMMENT ON COLUMN intakes.kindcheck_data IS 'Child safety check data (JSONB): children_present, ages, concerns, actions';
COMMENT ON COLUMN intakes.treatment_advice IS 'Treatment advice (JSONB): advice_text, target_department, care_program';
-- Enable RLS
ALTER TABLE intakes ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable read for authenticated users" ON intakes
FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "Enable insert for authenticated users" ON intakes
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "Enable update for authenticated users" ON intakes
FOR UPDATE USING (auth.role() = 'authenticated');
-- 3.2 Extend encounters table for intake contacts (FO 10.6)
-- Reuse existing FHIR encounters table, add intake_id reference
ALTER TABLE encounters
ADD COLUMN IF NOT EXISTS intake_id UUID REFERENCES intakes(id) ON DELETE SET NULL;
CREATE INDEX IF NOT EXISTS idx_encounters_intake ON encounters(intake_id);
COMMENT ON COLUMN encounters.intake_id IS 'Link encounter to specific intake (null for other encounter types)';
-- 3.3 Anamneses table (FO 10.9) - Separate for reusability
CREATE TABLE IF NOT EXISTS anamneses (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
intake_id UUID NOT NULL REFERENCES intakes(id) ON DELETE CASCADE,
anamnese_date DATE NOT NULL DEFAULT CURRENT_DATE,
anamnese_type TEXT NOT NULL CHECK (anamnese_type IN (
'psychiatrisch',
'sociaal',
'medisch',
'familie',
'ontwikkeling',
'overig'
)),
content TEXT NOT NULL, -- Rich text / markdown
notes TEXT,
created_by UUID REFERENCES practitioners(id),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_anamneses_intake ON anamneses(intake_id);
CREATE INDEX idx_anamneses_type ON anamneses(anamnese_type);
COMMENT ON TABLE anamneses IS 'Anamnesis records (psychiatric, social, medical, family, developmental) - reusable in care plans';
-- Enable RLS
ALTER TABLE anamneses ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable read for authenticated users" ON anamneses
FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "Enable insert for authenticated users" ON anamneses
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "Enable update for authenticated users" ON anamneses
FOR UPDATE USING (auth.role() = 'authenticated');
-- 3.4 Examinations table (FO 10.10) - Separate for reusability
CREATE TABLE IF NOT EXISTS examinations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
intake_id UUID NOT NULL REFERENCES intakes(id) ON DELETE CASCADE,
examination_date DATE NOT NULL DEFAULT CURRENT_DATE,
examination_type TEXT NOT NULL CHECK (examination_type IN (
'bloedonderzoek',
'neuropsychologisch',
'psychodiagnostiek',
'iq_test',
'persoonlijkheid',
'medisch', -- EEG, ECG, etc.
'overig'
)),
performed_by TEXT,
reason TEXT,
findings TEXT NOT NULL,
document_url TEXT, -- Link to uploaded report
notes TEXT,
created_by UUID REFERENCES practitioners(id),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_examinations_intake ON examinations(intake_id);
CREATE INDEX idx_examinations_type ON examinations(examination_type);
COMMENT ON TABLE examinations IS 'Medical and psychological examinations - reusable in care plans';
-- Enable RLS
ALTER TABLE examinations ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable read for authenticated users" ON examinations
FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "Enable insert for authenticated users" ON examinations
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "Enable update for authenticated users" ON examinations
FOR UPDATE USING (auth.role() = 'authenticated');
-- 3.5 Risk assessments table (FO 10.8) - Separate for history tracking
CREATE TABLE IF NOT EXISTS risk_assessments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
intake_id UUID NOT NULL REFERENCES intakes(id) ON DELETE CASCADE,
assessment_date DATE NOT NULL DEFAULT CURRENT_DATE,
risk_type TEXT NOT NULL CHECK (risk_type IN (
'suicidaliteit',
'agressie',
'zelfverwaarlozing',
'middelenmisbruik',
'verward_gedrag',
'overig'
)),
risk_level TEXT NOT NULL CHECK (risk_level IN ('laag', 'gemiddeld', 'hoog', 'zeer_hoog')),
rationale TEXT NOT NULL,
measures TEXT, -- Maatregelen
evaluation_date DATE,
notes TEXT,
created_by UUID REFERENCES practitioners(id),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_risk_assessments_intake ON risk_assessments(intake_id);
CREATE INDEX idx_risk_assessments_type ON risk_assessments(risk_type);
CREATE INDEX idx_risk_assessments_level ON risk_assessments(risk_level);
COMMENT ON TABLE risk_assessments IS 'Risk assessments (suicide, aggression, etc.) with history tracking';
-- Enable RLS
ALTER TABLE risk_assessments ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable read for authenticated users" ON risk_assessments
FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "Enable insert for authenticated users" ON risk_assessments
FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "Enable update for authenticated users" ON risk_assessments
FOR UPDATE USING (auth.role() = 'authenticated');
-- ============================================================================
-- STEP 4: Extend care_plans for intake references
-- ============================================================================
-- Add columns to reference intake components in care plans
ALTER TABLE care_plans
ADD COLUMN IF NOT EXISTS based_on_intake_id UUID REFERENCES intakes(id),
ADD COLUMN IF NOT EXISTS based_on_anamneses UUID[],
ADD COLUMN IF NOT EXISTS based_on_examinations UUID[],
ADD COLUMN IF NOT EXISTS based_on_risk_assessments UUID[];
COMMENT ON COLUMN care_plans.based_on_intake_id IS 'Primary intake this care plan is based on';
COMMENT ON COLUMN care_plans.based_on_anamneses IS 'Array of anamnese IDs referenced in this care plan';
COMMENT ON COLUMN care_plans.based_on_examinations IS 'Array of examination IDs referenced in this care plan';
COMMENT ON COLUMN care_plans.based_on_risk_assessments IS 'Array of risk assessment IDs referenced in this care plan';
-- ============================================================================
-- STEP 5: Triggers for updated_at timestamps
-- ============================================================================
-- Function to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Apply triggers
CREATE TRIGGER update_screenings_updated_at BEFORE UPDATE ON screenings
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_intakes_updated_at BEFORE UPDATE ON intakes
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_anamneses_updated_at BEFORE UPDATE ON anamneses
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_examinations_updated_at BEFORE UPDATE ON examinations
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_risk_assessments_updated_at BEFORE UPDATE ON risk_assessments
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================================
-- STEP 6: Helper views for common queries
-- ============================================================================
-- View: Active intakes with patient info
CREATE OR REPLACE VIEW active_intakes_overview AS
SELECT
i.id,
i.title,
i.status,
i.start_date,
i.end_date,
i.department,
p.name_family,
p.name_given,
p.birth_date,
pr.name_family as psychologist_name,
COUNT(DISTINCT e.id) as contact_count,
COUNT(DISTINCT c.id) as diagnosis_count
FROM intakes i
JOIN patients p ON i.patient_id = p.id
LEFT JOIN practitioners pr ON i.psychologist_id = pr.id
LEFT JOIN encounters e ON e.intake_id = i.id
LEFT JOIN conditions c ON c.patient_id = p.id AND c.encounter_id IN (
SELECT id FROM encounters WHERE intake_id = i.id
)
WHERE i.status = 'bezig'
GROUP BY i.id, p.name_family, p.name_given, p.birth_date, pr.name_family;
COMMENT ON VIEW active_intakes_overview IS 'Overview of active intakes with patient info and counts';
-- ============================================================================
-- SUMMARY
-- ============================================================================
-- This migration creates:
-- ✓ Patient status column (episode_status enum)
-- ✓ Screenings module (3 tables: screenings, activities, documents)
-- ✓ Intakes module (4 new tables + extend encounters)
-- - intakes (with JSONB for kindcheck, treatment_advice)
-- - anamneses (separate for reusability)
-- - examinations (separate for reusability)
-- - risk_assessments (separate for history)
-- ✓ Care plan extensions (reference intake components)
-- ✓ RLS policies for all tables
-- ✓ Indexes for performance
-- ✓ Helper views
--
-- Reuses existing FHIR tables:
-- ✓ observations (for ROM measurements)
-- ✓ conditions (for diagnoses/DSM-5)
-- ✓ encounters (extended with intake_id for contacts)
-- ✓ practitioners (for users/psychologists)
--
-- Total new tables: 7
-- Extended tables: 3 (patients, encounters, care_plans)
-- ============================================================================