Files
boc/landvex/reporting-module/schema.sql
T

113 lines
4.7 KiB
PL/PgSQL
Raw Normal View History

-- LandveX Reporting Module — PostgreSQL Schema
-- Tenant-isolerad, audit-loggad, schemalagd rapportering
-- Rapporter (self-service, per tenant)
CREATE TABLE reports (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
type VARCHAR(50) NOT NULL CHECK (type IN ('table','chart','pivot','map','dashboard')),
config JSONB NOT NULL DEFAULT '{}',
data_source_id UUID,
created_by UUID NOT NULL,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_reports_tenant ON reports(tenant_id);
CREATE INDEX idx_reports_type ON reports(type);
-- Körningshistorik (audit + resultat)
CREATE TABLE report_runs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
report_id UUID NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','running','completed','failed','cancelled')),
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
result_url TEXT,
result_format VARCHAR(10) DEFAULT 'json' CHECK (result_format IN ('json','csv','xlsx','pdf')),
row_count INTEGER,
error_message TEXT,
triggered_by UUID,
parameters JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_report_runs_report ON report_runs(report_id, created_at DESC);
CREATE INDEX idx_report_runs_status ON report_runs(status) WHERE status IN ('pending','running');
-- Scheman (cron-baserade)
CREATE TABLE report_schedules (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
report_id UUID NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
cron_expression VARCHAR(100) NOT NULL,
timezone VARCHAR(50) DEFAULT 'Europe/Stockholm',
next_run_at TIMESTAMPTZ,
last_run_at TIMESTAMPTZ,
status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active','paused','disabled')),
created_by UUID NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_schedules_next_run ON report_schedules(next_run_at) WHERE status = 'active';
CREATE INDEX idx_schedules_report ON report_schedules(report_id);
-- Delning (användare + externa e-post)
CREATE TABLE report_shares (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
report_id UUID NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
shared_with_user_id UUID,
shared_with_email VARCHAR(255),
permission VARCHAR(20) NOT NULL DEFAULT 'read' CHECK (permission IN ('read','write','admin')),
share_token VARCHAR(64) UNIQUE,
expires_at TIMESTAMPTZ,
created_by UUID NOT NULL,
created_at TIMESTAMPTZ DEFAULT now(),
CONSTRAINT share_target CHECK (shared_with_user_id IS NOT NULL OR shared_with_email IS NOT NULL)
);
CREATE INDEX idx_shares_user ON report_shares(shared_with_user_id);
CREATE INDEX idx_shares_token ON report_shares(share_token) WHERE share_token IS NOT NULL;
-- Datakällor (befintlig tabell, utökas)
CREATE TABLE data_sources (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
name VARCHAR(255) NOT NULL,
type VARCHAR(50) NOT NULL CHECK (type IN ('postgresql','mysql','api','s3','bigquery','snowflake','mssql')),
connection JSONB NOT NULL,
config JSONB DEFAULT '{}',
status VARCHAR(20) DEFAULT 'active',
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_data_sources_tenant ON data_sources(tenant_id);
-- Audit-logg för alla rapport-händelser
CREATE TABLE report_audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
report_id UUID REFERENCES reports(id) ON DELETE SET NULL,
run_id UUID REFERENCES report_runs(id) ON DELETE SET NULL,
user_id UUID,
action VARCHAR(50) NOT NULL CHECK (action IN ('created','updated','deleted','run','exported','shared','schedule_created','schedule_updated','schedule_deleted')),
details JSONB DEFAULT '{}',
ip_address INET,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_audit_report ON report_audit_log(report_id, created_at DESC);
CREATE INDEX idx_audit_user ON report_audit_log(user_id, created_at DESC);
-- Uppdatera updated_at automatiskt
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_reports_updated_at BEFORE UPDATE ON reports
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();