-- Migration: Create all missing tables -- Run this against the database to add missing schema -- Functions CREATE OR REPLACE FUNCTION update_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = CURRENT_TIMESTAMP; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Config table CREATE TABLE IF NOT EXISTS config ( id SERIAL PRIMARY KEY, key VARCHAR(255) UNIQUE NOT NULL, value JSONB NOT NULL, description TEXT, category VARCHAR(100) DEFAULT 'general', is_encrypted BOOLEAN DEFAULT FALSE, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_by INTEGER ); -- Session audit log CREATE TABLE IF NOT EXISTS session_audit_log ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL, session_id VARCHAR(255), event VARCHAR(50) NOT NULL, ip_address VARCHAR(45), user_agent TEXT, metadata JSONB DEFAULT '{}', timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Plesk servers CREATE TABLE IF NOT EXISTS plesk_servers ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, host VARCHAR(255) NOT NULL, port INTEGER DEFAULT 8443, api_key TEXT, username VARCHAR(255), password_hash TEXT, use_https BOOLEAN DEFAULT TRUE, verify_ssl BOOLEAN DEFAULT TRUE, two_factor_enabled BOOLEAN DEFAULT FALSE, two_factor_method VARCHAR(50), connection_status VARCHAR(50) DEFAULT 'unknown', last_connected TIMESTAMP, is_active BOOLEAN DEFAULT TRUE, metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TRIGGER IF NOT EXISTS plesk_servers_updated_at BEFORE UPDATE ON plesk_servers FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- SAP servers CREATE TABLE IF NOT EXISTS sap_servers ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, host VARCHAR(255) NOT NULL, port INTEGER DEFAULT 50000, company_db VARCHAR(255) NOT NULL, username VARCHAR(255), password_hash TEXT, use_ssl BOOLEAN DEFAULT TRUE, timeout_seconds INTEGER DEFAULT 30, connection_status VARCHAR(50) DEFAULT 'unknown', last_connected TIMESTAMP, is_active BOOLEAN DEFAULT TRUE, metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TRIGGER IF NOT EXISTS sap_servers_updated_at BEFORE UPDATE ON sap_servers FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Customers CREATE TABLE IF NOT EXISTS customers ( id SERIAL PRIMARY KEY, sap_customer_id VARCHAR(255), plesk_customer_id VARCHAR(255), name VARCHAR(255) NOT NULL, email VARCHAR(255), status VARCHAR(50) DEFAULT 'active', sync_status VARCHAR(50) DEFAULT 'pending_sync', metadata JSONB DEFAULT '{}', last_sync TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Subscriptions CREATE TABLE IF NOT EXISTS subscriptions ( id SERIAL PRIMARY KEY, customer_id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, description TEXT, start_date DATE, end_date DATE, billing_cycle VARCHAR(50), status VARCHAR(50) DEFAULT 'active', sync_status VARCHAR(50) DEFAULT 'pending_sync', pricing_data JSONB DEFAULT '{}', features JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Sync jobs CREATE TABLE IF NOT EXISTS sync_jobs ( id SERIAL PRIMARY KEY, job_type VARCHAR(50) NOT NULL, sync_direction VARCHAR(50) NOT NULL, status VARCHAR(50) DEFAULT 'pending', started_at TIMESTAMP, completed_at TIMESTAMP, records_processed INTEGER DEFAULT 0, records_failed INTEGER DEFAULT 0, records_skipped INTEGER DEFAULT 0, error_message TEXT, config_snapshot JSONB DEFAULT '{}', progress_percentage NUMERIC(5,2) DEFAULT 0, created_by INTEGER, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TRIGGER IF NOT EXISTS sync_jobs_updated_at BEFORE UPDATE ON sync_jobs FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Sync logs CREATE TABLE IF NOT EXISTS sync_logs ( id SERIAL PRIMARY KEY, sync_job_id INTEGER NOT NULL, entity_type VARCHAR(50) NOT NULL, entity_id VARCHAR(255) NOT NULL, action VARCHAR(50) NOT NULL, status VARCHAR(50) NOT NULL, error_message TEXT, metadata JSONB DEFAULT '{}', timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, resolution_status VARCHAR(50) DEFAULT 'pending', resolution_action VARCHAR(50), resolved_by INTEGER, resolved_at TIMESTAMP, conflict_details JSONB, CONSTRAINT fk_sync_log_job FOREIGN KEY (sync_job_id) REFERENCES sync_jobs(id) ON DELETE CASCADE ); -- Alert thresholds CREATE TABLE IF NOT EXISTS alert_thresholds ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, subscription_id INTEGER, metric_type VARCHAR(50) NOT NULL, threshold_value NUMERIC(15,4) NOT NULL, comparison_operator VARCHAR(10) NOT NULL, action VARCHAR(50) NOT NULL, notification_channels JSONB DEFAULT '["email"]', is_active BOOLEAN DEFAULT TRUE, last_triggered TIMESTAMP, created_by INTEGER, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Alert history CREATE TABLE IF NOT EXISTS alert_history ( id SERIAL PRIMARY KEY, threshold_id INTEGER NOT NULL, subscription_id INTEGER, actual_value NUMERIC(15,4) NOT NULL, triggered_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, action_taken VARCHAR(50), notification_sent BOOLEAN DEFAULT FALSE, notification_error TEXT, CONSTRAINT fk_alert_history_threshold FOREIGN KEY (threshold_id) REFERENCES alert_thresholds(id) ON DELETE CASCADE ); -- Billing records CREATE TABLE IF NOT EXISTS billing_records ( id SERIAL PRIMARY KEY, subscription_id INTEGER NOT NULL, customer_id INTEGER NOT NULL, period_start DATE NOT NULL, period_end DATE NOT NULL, usage_data JSONB NOT NULL DEFAULT '{}', calculated_amount NUMERIC(12,2) NOT NULL, currency VARCHAR(3) DEFAULT 'EUR', sap_invoice_id VARCHAR(255), invoice_status VARCHAR(50) DEFAULT 'draft', notes TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Pricing config CREATE TABLE IF NOT EXISTS pricing_config ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, metric_type VARCHAR(50) NOT NULL, unit VARCHAR(50) NOT NULL, rate_per_unit NUMERIC(10,4) NOT NULL, currency VARCHAR(3) DEFAULT 'EUR', is_active BOOLEAN DEFAULT TRUE, valid_from DATE DEFAULT CURRENT_DATE, valid_to DATE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Default config data INSERT INTO config (key, value, description, category) VALUES ('sync.default_direction', '"sap_to_plesk"', 'Default sync direction', 'sync'), ('sync.conflict_resolution', '"timestamp_based"', 'Default conflict resolution strategy', 'sync'), ('sync.interval_minutes', '60', 'Default sync interval in minutes', 'sync'), ('auth.session_timeout', '1800', 'Session timeout in seconds', 'auth'), ('system.initialized', 'false', 'System initialization flag', 'system') ON CONFLICT (key) DO NOTHING;