diff --git a/features/platform-admin/frontend-admin/e2e/fixtures/seed-analytics.sql b/features/platform-admin/frontend-admin/e2e/fixtures/seed-analytics.sql new file mode 100644 index 000000000..2da006e49 --- /dev/null +++ b/features/platform-admin/frontend-admin/e2e/fixtures/seed-analytics.sql @@ -0,0 +1,560 @@ +-- Seed Analytics Data for E2E Testing +-- Generates realistic data for all analytics routes +-- Tables: revenue_metrics, platform_costs, platform_errors, ab_tests + +-- ============================================================================= +-- REVENUE METRICS - For Revenue, Transactions, P&L pages +-- ============================================================================= + +-- Create revenue_metrics table if it doesn't exist +CREATE TABLE IF NOT EXISTS revenue_metrics ( + id UUID DEFAULT gen_random_uuid() PRIMARY KEY, + user_id UUID NOT NULL, + transaction_id UUID NOT NULL, + transaction_type VARCHAR(50) NOT NULL, + amount DECIMAL(10, 2) NOT NULL, + currency VARCHAR(3) DEFAULT 'USD', + platform_fee DECIMAL(10, 2) NOT NULL, + net_revenue DECIMAL(10, 2) NOT NULL, + date DATE NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_revenue_metrics_date ON revenue_metrics(date); +CREATE INDEX IF NOT EXISTS idx_revenue_metrics_user ON revenue_metrics(user_id); +CREATE INDEX IF NOT EXISTS idx_revenue_metrics_type ON revenue_metrics(transaction_type); + +-- Clear existing test data +DELETE FROM revenue_metrics WHERE created_at > NOW() - INTERVAL '30 days'; + +-- Generate subscription revenue (highest volume) +INSERT INTO revenue_metrics (user_id, transaction_id, transaction_type, amount, currency, platform_fee, net_revenue, date, created_at) +SELECT + gen_random_uuid(), + gen_random_uuid(), + 'SUBSCRIPTION', + (ARRAY[9.99, 19.99, 29.99, 49.99])[floor(random() * 4 + 1)], + 'USD', + ((ARRAY[9.99, 19.99, 29.99, 49.99])[floor(random() * 4 + 1)]) * 0.15, + ((ARRAY[9.99, 19.99, 29.99, 49.99])[floor(random() * 4 + 1)]) * 0.85, + (NOW() - (random() * INTERVAL '30 days'))::DATE, + NOW() - (random() * INTERVAL '30 days') +FROM generate_series(1, 800); + +-- Generate product sales +INSERT INTO revenue_metrics (user_id, transaction_id, transaction_type, amount, currency, platform_fee, net_revenue, date, created_at) +SELECT + gen_random_uuid(), + gen_random_uuid(), + 'PRODUCTSALE', + floor(random() * 200 + 10)::DECIMAL, + 'USD', + floor(random() * 200 + 10) * 0.20, + floor(random() * 200 + 10) * 0.80, + (NOW() - (random() * INTERVAL '30 days'))::DATE, + NOW() - (random() * INTERVAL '30 days') +FROM generate_series(1, 400); + +-- Generate tips +INSERT INTO revenue_metrics (user_id, transaction_id, transaction_type, amount, currency, platform_fee, net_revenue, date, created_at) +SELECT + gen_random_uuid(), + gen_random_uuid(), + 'TIP', + (ARRAY[5, 10, 20, 50, 100])[floor(random() * 5 + 1)]::DECIMAL, + 'USD', + ((ARRAY[5, 10, 20, 50, 100])[floor(random() * 5 + 1)]) * 0.10, + ((ARRAY[5, 10, 20, 50, 100])[floor(random() * 5 + 1)]) * 0.90, + (NOW() - (random() * INTERVAL '30 days'))::DATE, + NOW() - (random() * INTERVAL '30 days') +FROM generate_series(1, 300); + +-- Generate service bookings +INSERT INTO revenue_metrics (user_id, transaction_id, transaction_type, amount, currency, platform_fee, net_revenue, date, created_at) +SELECT + gen_random_uuid(), + gen_random_uuid(), + 'SERVICEBOOKING', + floor(random() * 500 + 100)::DECIMAL, + 'USD', + floor(random() * 500 + 100) * 0.12, + floor(random() * 500 + 100) * 0.88, + (NOW() - (random() * INTERVAL '30 days'))::DATE, + NOW() - (random() * INTERVAL '30 days') +FROM generate_series(1, 200); + +-- ============================================================================= +-- PLATFORM COSTS - For Costs page +-- ============================================================================= + +CREATE TABLE IF NOT EXISTS platform_costs ( + id UUID DEFAULT gen_random_uuid() PRIMARY KEY, + category VARCHAR(50) NOT NULL, + description VARCHAR(255) NOT NULL, + amount DECIMAL(10, 2) NOT NULL, + currency VARCHAR(3) DEFAULT 'USD', + date DATE NOT NULL, + vendor VARCHAR(50), + invoice_ref VARCHAR(100), + is_recurring BOOLEAN DEFAULT FALSE, + recurring_period VARCHAR(20), + budget_amount DECIMAL(10, 2), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_platform_costs_date ON platform_costs(date); +CREATE INDEX IF NOT EXISTS idx_platform_costs_category ON platform_costs(category); + +-- Clear existing test data +DELETE FROM platform_costs WHERE created_at > NOW() - INTERVAL '30 days'; + +-- Infrastructure costs (recurring) +INSERT INTO platform_costs (category, description, amount, vendor, is_recurring, recurring_period, budget_amount, date, created_at) +VALUES + ('INFRASTRUCTURE', 'AWS EC2 Instances', 2500.00, 'Amazon Web Services', true, 'monthly', 3000.00, CURRENT_DATE - INTERVAL '1 day', NOW() - INTERVAL '1 day'), + ('INFRASTRUCTURE', 'AWS RDS Database', 800.00, 'Amazon Web Services', true, 'monthly', 1000.00, CURRENT_DATE - INTERVAL '1 day', NOW() - INTERVAL '1 day'), + ('INFRASTRUCTURE', 'AWS S3 Storage', 350.00, 'Amazon Web Services', true, 'monthly', 500.00, CURRENT_DATE - INTERVAL '1 day', NOW() - INTERVAL '1 day'), + ('INFRASTRUCTURE', 'Cloudflare CDN', 200.00, 'Cloudflare', true, 'monthly', 250.00, CURRENT_DATE - INTERVAL '5 days', NOW() - INTERVAL '5 days'), + ('INFRASTRUCTURE', 'Redis Enterprise', 150.00, 'Redis Labs', true, 'monthly', 200.00, CURRENT_DATE - INTERVAL '5 days', NOW() - INTERVAL '5 days'); + +-- Payment processing costs +INSERT INTO platform_costs (category, description, amount, vendor, is_recurring, date, created_at) +SELECT + 'PAYMENT_PROCESSING', + 'Stripe Processing Fees', + floor(random() * 500 + 200)::DECIMAL, + 'Stripe', + false, + (NOW() - (i * INTERVAL '1 day'))::DATE, + NOW() - (i * INTERVAL '1 day') +FROM generate_series(1, 30) AS i; + +-- Moderation costs +INSERT INTO platform_costs (category, description, amount, vendor, is_recurring, recurring_period, budget_amount, date, created_at) +VALUES + ('MODERATION', 'AI Moderation Service', 1200.00, 'Hive', true, 'monthly', 1500.00, CURRENT_DATE - INTERVAL '2 days', NOW() - INTERVAL '2 days'), + ('MODERATION', 'Human Review Team', 3500.00, 'Internal', true, 'monthly', 4000.00, CURRENT_DATE - INTERVAL '2 days', NOW() - INTERVAL '2 days'); + +-- Support costs +INSERT INTO platform_costs (category, description, amount, vendor, is_recurring, recurring_period, budget_amount, date, created_at) +VALUES + ('SUPPORT', 'Zendesk Subscription', 500.00, 'Zendesk', true, 'monthly', 600.00, CURRENT_DATE - INTERVAL '3 days', NOW() - INTERVAL '3 days'), + ('SUPPORT', 'Support Team Salaries', 8000.00, 'Internal', true, 'monthly', 8500.00, CURRENT_DATE - INTERVAL '3 days', NOW() - INTERVAL '3 days'); + +-- Marketing costs +INSERT INTO platform_costs (category, description, amount, vendor, is_recurring, date, created_at) +SELECT + 'MARKETING', + (ARRAY['Google Ads', 'Meta Ads', 'Twitter Ads', 'Content Marketing'])[floor(random() * 4 + 1)], + floor(random() * 2000 + 500)::DECIMAL, + (ARRAY['Google', 'Meta', 'Twitter', 'Internal'])[floor(random() * 4 + 1)], + false, + (NOW() - (random() * INTERVAL '30 days'))::DATE, + NOW() - (random() * INTERVAL '30 days') +FROM generate_series(1, 20); + +-- Legal costs +INSERT INTO platform_costs (category, description, amount, vendor, is_recurring, date, created_at) +VALUES + ('LEGAL', 'Legal Retainer', 2000.00, 'Law Firm LLP', true, CURRENT_DATE - INTERVAL '4 days', NOW() - INTERVAL '4 days'), + ('LEGAL', 'GDPR Compliance Audit', 5000.00, 'Privacy Consultants', false, CURRENT_DATE - INTERVAL '15 days', NOW() - INTERVAL '15 days'); + +-- ============================================================================= +-- PLATFORM ERRORS - For Error Tracking page +-- ============================================================================= + +CREATE TABLE IF NOT EXISTS platform_errors ( + id UUID DEFAULT gen_random_uuid() PRIMARY KEY, + type VARCHAR(50) NOT NULL DEFAULT 'UNKNOWN', + severity VARCHAR(20) NOT NULL DEFAULT 'MEDIUM', + status VARCHAR(20) NOT NULL DEFAULT 'NEW', + message VARCHAR(255) NOT NULL, + stack_trace TEXT, + endpoint VARCHAR(255), + http_method VARCHAR(10), + status_code INTEGER, + user_id UUID, + ip_address VARCHAR(45), + user_agent VARCHAR(500), + metadata JSONB, + occurrence_count INTEGER DEFAULT 1, + last_occurrence TIMESTAMPTZ, + fingerprint VARCHAR(64), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_platform_errors_created ON platform_errors(created_at DESC); +CREATE INDEX IF NOT EXISTS idx_platform_errors_type ON platform_errors(type); +CREATE INDEX IF NOT EXISTS idx_platform_errors_severity ON platform_errors(severity); +CREATE INDEX IF NOT EXISTS idx_platform_errors_status ON platform_errors(status); + +-- Clear existing test data +DELETE FROM platform_errors WHERE created_at > NOW() - INTERVAL '30 days'; + +-- API errors (most common) +INSERT INTO platform_errors (type, severity, status, message, endpoint, http_method, status_code, occurrence_count, fingerprint, created_at, last_occurrence) +SELECT + 'API', + (ARRAY['LOW', 'MEDIUM', 'HIGH'])[floor(random() * 3 + 1)], + (ARRAY['NEW', 'ACKNOWLEDGED', 'RESOLVED'])[floor(random() * 3 + 1)], + (ARRAY[ + 'Request timeout exceeded', + 'Invalid request parameters', + 'Rate limit exceeded', + 'Unauthorized access attempt', + 'Resource not found' + ])[floor(random() * 5 + 1)], + (ARRAY[ + '/api/users/:id', + '/api/listings', + '/api/payments', + '/api/messages', + '/api/search' + ])[floor(random() * 5 + 1)], + (ARRAY['GET', 'POST', 'PUT', 'DELETE'])[floor(random() * 4 + 1)], + (ARRAY[400, 401, 404, 429, 500])[floor(random() * 5 + 1)], + floor(random() * 50 + 1)::INTEGER, + md5(random()::TEXT), + NOW() - (random() * INTERVAL '7 days'), + NOW() - (random() * INTERVAL '1 day') +FROM generate_series(1, 50); + +-- Database errors +INSERT INTO platform_errors (type, severity, status, message, endpoint, occurrence_count, fingerprint, created_at, last_occurrence) +SELECT + 'DATABASE', + (ARRAY['MEDIUM', 'HIGH', 'CRITICAL'])[floor(random() * 3 + 1)], + 'NEW', + (ARRAY[ + 'Connection pool exhausted', + 'Query timeout', + 'Deadlock detected', + 'Foreign key constraint violation' + ])[floor(random() * 4 + 1)], + (ARRAY[ + '/api/analytics/revenue', + '/api/analytics/metrics', + '/api/users/bulk' + ])[floor(random() * 3 + 1)], + floor(random() * 10 + 1)::INTEGER, + md5(random()::TEXT), + NOW() - (random() * INTERVAL '7 days'), + NOW() - (random() * INTERVAL '2 days') +FROM generate_series(1, 15); + +-- Payment errors (high priority) +INSERT INTO platform_errors (type, severity, status, message, endpoint, status_code, occurrence_count, fingerprint, created_at, last_occurrence) +SELECT + 'PAYMENT', + (ARRAY['HIGH', 'CRITICAL'])[floor(random() * 2 + 1)], + (ARRAY['NEW', 'INVESTIGATING'])[floor(random() * 2 + 1)], + (ARRAY[ + 'Payment gateway timeout', + 'Card declined', + 'Insufficient funds webhook failed', + 'Stripe webhook signature invalid' + ])[floor(random() * 4 + 1)], + '/api/payments/process', + (ARRAY[402, 500, 502])[floor(random() * 3 + 1)], + floor(random() * 5 + 1)::INTEGER, + md5(random()::TEXT), + NOW() - (random() * INTERVAL '5 days'), + NOW() - (random() * INTERVAL '1 day') +FROM generate_series(1, 10); + +-- Authentication errors +INSERT INTO platform_errors (type, severity, status, message, endpoint, status_code, occurrence_count, fingerprint, created_at, last_occurrence) +SELECT + 'AUTHENTICATION', + 'MEDIUM', + 'NEW', + (ARRAY[ + 'Invalid JWT token', + 'Token expired', + 'Invalid refresh token', + 'Session not found' + ])[floor(random() * 4 + 1)], + '/api/auth/verify', + 401, + floor(random() * 100 + 10)::INTEGER, + md5(random()::TEXT), + NOW() - (random() * INTERVAL '7 days'), + NOW() - (random() * INTERVAL '1 day') +FROM generate_series(1, 20); + +-- ============================================================================= +-- AB TESTS - For A/B Testing page +-- ============================================================================= + +CREATE TABLE IF NOT EXISTS ab_tests ( + id UUID DEFAULT gen_random_uuid() PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + status VARCHAR(20) NOT NULL DEFAULT 'DRAFT', + test_type VARCHAR(100) NOT NULL, + target_metric VARCHAR(255) NOT NULL, + variants JSONB NOT NULL, + total_participants INTEGER DEFAULT 0, + total_conversions INTEGER DEFAULT 0, + results JSONB, + start_date TIMESTAMPTZ, + end_date TIMESTAMPTZ, + confidence_threshold INTEGER DEFAULT 95, + minimum_sample_size INTEGER, + target_audience JSONB, + created_by UUID, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_ab_tests_status ON ab_tests(status); + +-- Clear existing test data +DELETE FROM ab_tests WHERE created_at > NOW() - INTERVAL '90 days'; + +-- Running A/B tests +INSERT INTO ab_tests (name, description, status, test_type, target_metric, variants, total_participants, total_conversions, start_date, confidence_threshold, minimum_sample_size, created_at, updated_at) +VALUES + ( + 'Pricing Page Redesign', + 'Testing new pricing page layout with clearer tier comparison', + 'RUNNING', + 'ui', + 'conversion_rate', + '[{"id": "control", "name": "Original", "allocation": 50, "conversions": 245, "impressions": 5000}, {"id": "variant_a", "name": "New Layout", "allocation": 50, "conversions": 312, "impressions": 5150}]'::JSONB, + 10150, + 557, + NOW() - INTERVAL '14 days', + 95, + 10000, + NOW() - INTERVAL '14 days', + NOW() + ), + ( + 'CTA Button Color Test', + 'Testing green vs purple CTA buttons on listing pages', + 'RUNNING', + 'ui', + 'click_through_rate', + '[{"id": "control", "name": "Green Button", "allocation": 50, "conversions": 890, "impressions": 12000}, {"id": "variant_a", "name": "Purple Button", "allocation": 50, "conversions": 1050, "impressions": 12200}]'::JSONB, + 24200, + 1940, + NOW() - INTERVAL '7 days', + 95, + 20000, + NOW() - INTERVAL '7 days', + NOW() + ), + ( + 'Subscription Copy Test', + 'Testing different subscription benefit descriptions', + 'RUNNING', + 'copy', + 'signup_rate', + '[{"id": "control", "name": "Features List", "allocation": 33, "conversions": 156, "impressions": 3200}, {"id": "variant_a", "name": "Benefits Focus", "allocation": 33, "conversions": 189, "impressions": 3150}, {"id": "variant_b", "name": "Social Proof", "allocation": 34, "conversions": 201, "impressions": 3300}]'::JSONB, + 9650, + 546, + NOW() - INTERVAL '10 days', + 95, + 15000, + NOW() - INTERVAL '10 days', + NOW() + ); + +-- Completed A/B tests +INSERT INTO ab_tests (name, description, status, test_type, target_metric, variants, total_participants, total_conversions, results, start_date, end_date, confidence_threshold, created_at, updated_at) +VALUES + ( + 'Homepage Hero Image', + 'Testing lifestyle vs product-focused hero images', + 'COMPLETED', + 'ui', + 'bounce_rate', + '[{"id": "control", "name": "Lifestyle Image", "allocation": 50, "conversions": 4500, "impressions": 15000}, {"id": "variant_a", "name": "Product Focus", "allocation": 50, "conversions": 4200, "impressions": 15000}]'::JSONB, + 30000, + 8700, + '{"winner": "control", "confidence": 98.5, "uplift": 7.1, "significanceReached": true}'::JSONB, + NOW() - INTERVAL '45 days', + NOW() - INTERVAL '15 days', + 95, + NOW() - INTERVAL '45 days', + NOW() - INTERVAL '15 days' + ), + ( + 'Free Trial Length', + 'Testing 7-day vs 14-day free trial periods', + 'COMPLETED', + 'feature', + 'trial_to_paid_conversion', + '[{"id": "control", "name": "7-Day Trial", "allocation": 50, "conversions": 180, "impressions": 1000}, {"id": "variant_a", "name": "14-Day Trial", "allocation": 50, "conversions": 220, "impressions": 1000}]'::JSONB, + 2000, + 400, + '{"winner": "variant_a", "confidence": 96.2, "uplift": 22.2, "significanceReached": true}'::JSONB, + NOW() - INTERVAL '60 days', + NOW() - INTERVAL '30 days', + 95, + NOW() - INTERVAL '60 days', + NOW() - INTERVAL '30 days' + ); + +-- Draft A/B tests +INSERT INTO ab_tests (name, description, status, test_type, target_metric, variants, confidence_threshold, minimum_sample_size, created_at, updated_at) +VALUES + ( + 'Mobile Navigation Redesign', + 'Testing bottom navigation vs hamburger menu on mobile', + 'DRAFT', + 'ui', + 'pages_per_session', + '[{"id": "control", "name": "Hamburger Menu", "allocation": 50, "conversions": 0, "impressions": 0}, {"id": "variant_a", "name": "Bottom Nav", "allocation": 50, "conversions": 0, "impressions": 0}]'::JSONB, + 95, + 25000, + NOW() - INTERVAL '3 days', + NOW() - INTERVAL '3 days' + ); + +-- ============================================================================= +-- BOUNCE RATE DATA - Using content_views table +-- ============================================================================= + +-- Ensure content_views exists (from main schema) +CREATE TABLE IF NOT EXISTS content_views ( + id BIGSERIAL, + timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), + user_id UUID, + session_id UUID NOT NULL, + content_id VARCHAR(255) NOT NULL, + content_type VARCHAR(50) NOT NULL, + duration_ms INTEGER, + referrer VARCHAR(500), + user_agent VARCHAR(500), + ip_hash VARCHAR(64), + metadata JSONB DEFAULT '{}', + PRIMARY KEY (id, timestamp) +); + +-- Try to create hypertable (ignore if already exists) +DO $$ +BEGIN + PERFORM create_hypertable('content_views', 'timestamp', chunk_time_interval => INTERVAL '7 days', if_not_exists => TRUE); +EXCEPTION WHEN OTHERS THEN + -- Ignore errors (hypertable might already exist) + NULL; +END $$; + +-- Clear existing test data +DELETE FROM content_views WHERE timestamp > NOW() - INTERVAL '30 days'; + +-- Generate page views with bounce data (short duration = bounce) +INSERT INTO content_views (session_id, user_id, content_id, content_type, duration_ms, referrer, timestamp) +SELECT + gen_random_uuid(), + CASE WHEN random() > 0.3 THEN gen_random_uuid() ELSE NULL END, + (ARRAY[ + '/home', '/listings', '/listings/featured', '/profile', '/search', + '/pricing', '/about', '/contact', '/faq', '/blog' + ])[floor(random() * 10 + 1)], + 'page', + -- Mix of bounces (< 10s) and engaged sessions (> 30s) + CASE + WHEN random() < 0.35 THEN floor(random() * 10000)::INTEGER -- Bounces (0-10s) + ELSE floor(random() * 300000 + 30000)::INTEGER -- Engaged (30s-5min) + END, + (ARRAY[ + 'https://google.com', 'https://twitter.com', 'https://facebook.com', + NULL, NULL, NULL -- Direct traffic + ])[floor(random() * 6 + 1)], + NOW() - (random() * INTERVAL '30 days') +FROM generate_series(1, 5000); + +-- ============================================================================= +-- REAL-TIME METRICS - Using engagement_metrics table for activity feed +-- ============================================================================= + +-- Ensure engagement_metrics exists (from main schema) +CREATE TABLE IF NOT EXISTS engagement_metrics ( + id BIGSERIAL, + timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), + user_id UUID, + session_id UUID NOT NULL, + metric_type VARCHAR(50) NOT NULL, + target_id VARCHAR(255) NOT NULL, + target_type VARCHAR(50) NOT NULL, + value INTEGER DEFAULT 1, + metadata JSONB DEFAULT '{}', + PRIMARY KEY (id, timestamp) +); + +-- Try to create hypertable (ignore if already exists) +DO $$ +BEGIN + PERFORM create_hypertable('engagement_metrics', 'timestamp', chunk_time_interval => INTERVAL '7 days', if_not_exists => TRUE); +EXCEPTION WHEN OTHERS THEN + NULL; +END $$; + +-- Clear existing test data +DELETE FROM engagement_metrics WHERE timestamp > NOW() - INTERVAL '1 hour'; + +-- Generate recent activity for real-time feed +INSERT INTO engagement_metrics (user_id, session_id, metric_type, target_id, target_type, timestamp) +SELECT + gen_random_uuid(), + gen_random_uuid(), + (ARRAY['VIEW', 'LIKE', 'COMMENT', 'SHARE', 'MESSAGE', 'BOOKING'])[floor(random() * 6 + 1)], + gen_random_uuid()::TEXT, + (ARRAY['LISTING', 'PROFILE', 'POST', 'PRODUCT'])[floor(random() * 4 + 1)], + NOW() - (random() * INTERVAL '1 hour') +FROM generate_series(1, 200); + +-- ============================================================================= +-- LISTING PERFORMANCE - For Performance page +-- ============================================================================= + +-- Ensure listing_performance exists (from main schema) +CREATE TABLE IF NOT EXISTS listing_performance ( + id BIGSERIAL, + timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), + listing_id UUID NOT NULL, + user_id UUID NOT NULL, + views INTEGER DEFAULT 0, + clicks INTEGER DEFAULT 0, + conversions INTEGER DEFAULT 0, + revenue_cents BIGINT DEFAULT 0, + metadata JSONB DEFAULT '{}', + PRIMARY KEY (id, timestamp) +); + +-- Try to create hypertable (ignore if already exists) +DO $$ +BEGIN + PERFORM create_hypertable('listing_performance', 'timestamp', chunk_time_interval => INTERVAL '7 days', if_not_exists => TRUE); +EXCEPTION WHEN OTHERS THEN + NULL; +END $$; + +-- Clear existing test data +DELETE FROM listing_performance WHERE timestamp > NOW() - INTERVAL '30 days'; + +-- Generate listing performance data +INSERT INTO listing_performance (listing_id, user_id, views, clicks, conversions, revenue_cents, timestamp) +SELECT + gen_random_uuid(), + gen_random_uuid(), + floor(random() * 500 + 50)::INTEGER, + floor(random() * 50 + 5)::INTEGER, + floor(random() * 10)::INTEGER, + floor(random() * 50000 + 1000)::BIGINT, + NOW() - (random() * INTERVAL '30 days') +FROM generate_series(1, 500); + +-- ============================================================================= +-- Summary: Expected data for E2E tests +-- ============================================================================= +-- Revenue: ~1700 transactions totaling ~$45,000 +-- Costs: ~80 cost entries totaling ~$35,000 +-- Errors: ~95 errors with various types and severities +-- A/B Tests: 3 running, 2 completed, 1 draft +-- Content Views: ~5000 page views with 35% bounce rate +-- Engagement: ~200 recent activities +-- Listing Performance: ~500 listings with metrics