-- Doku-only (siehe README.md in diesem Verzeichnis) — die tatsächliche -- Ausführung passiert idempotent über internal/storage/taxonomy.go -- initTaxonomySchema(), aufgerufen aus (*Store).initSchema(). -- -- Strukturierte Entitäten (Tags/Dokumenttypen/Korrespondenten) statt der -- bisherigen documents.doc_type/correspondent-Freitextfelder (die bleiben -- unangetastet, Bestandsschutz), plus Barcode-Erkennung fuer automatische -- Zuordnung beim Ingest (siehe internal/matching, internal/barcode). CREATE TABLE IF NOT EXISTS tags ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, name TEXT NOT NULL, color TEXT, match_algorithm TEXT NOT NULL DEFAULT 'none' CHECK (match_algorithm IN ('none','any','all','exact','regex','fuzzy')), match_pattern TEXT, case_sensitive BOOLEAN NOT NULL DEFAULT false, barcode_value TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE(tenant_id, name) ); CREATE TABLE IF NOT EXISTS document_types ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, name TEXT NOT NULL, color TEXT, match_algorithm TEXT NOT NULL DEFAULT 'none' CHECK (match_algorithm IN ('none','any','all','exact','regex','fuzzy')), match_pattern TEXT, case_sensitive BOOLEAN NOT NULL DEFAULT false, barcode_value TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE(tenant_id, name) ); CREATE TABLE IF NOT EXISTS correspondents ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, name TEXT NOT NULL, color TEXT, match_algorithm TEXT NOT NULL DEFAULT 'none' CHECK (match_algorithm IN ('none','any','all','exact','regex','fuzzy')), match_pattern TEXT, case_sensitive BOOLEAN NOT NULL DEFAULT false, barcode_value TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE(tenant_id, name) ); CREATE TABLE IF NOT EXISTS document_tags ( document_id BIGINT NOT NULL REFERENCES documents(id) ON DELETE CASCADE, tag_id BIGINT NOT NULL REFERENCES tags(id) ON DELETE CASCADE, PRIMARY KEY (document_id, tag_id) ); CREATE INDEX IF NOT EXISTS idx_tags_tenant ON tags(tenant_id); CREATE INDEX IF NOT EXISTS idx_document_types_tenant ON document_types(tenant_id); CREATE INDEX IF NOT EXISTS idx_correspondents_tenant ON correspondents(tenant_id); CREATE INDEX IF NOT EXISTS idx_document_tags_tag ON document_tags(tag_id); CREATE UNIQUE INDEX IF NOT EXISTS idx_tags_tenant_barcode ON tags(tenant_id, barcode_value) WHERE barcode_value IS NOT NULL; CREATE UNIQUE INDEX IF NOT EXISTS idx_document_types_tenant_barcode ON document_types(tenant_id, barcode_value) WHERE barcode_value IS NOT NULL; CREATE UNIQUE INDEX IF NOT EXISTS idx_correspondents_tenant_barcode ON correspondents(tenant_id, barcode_value) WHERE barcode_value IS NOT NULL; -- documents: neue Spalten, alte doc_type/correspondent-Textspalten bleiben -- unveraendert (Bestandsschutz fuer vorhandene GoBD-Metadaten). ALTER TABLE documents ADD COLUMN IF NOT EXISTS doc_type_id BIGINT REFERENCES document_types(id); ALTER TABLE documents ADD COLUMN IF NOT EXISTS correspondent_id BIGINT REFERENCES correspondents(id); ALTER TABLE documents ADD COLUMN IF NOT EXISTS barcode_values JSONB;