441 lines
18 KiB
SQL
Executable file
441 lines
18 KiB
SQL
Executable file
-- Seed Analytics Data for E2E Testing
|
|
-- Generates realistic data for all analytics routes
|
|
-- NOTE: Uses schema from analytics/database/schema.sql (loaded via 01-analytics-schema.sql)
|
|
|
|
-- =============================================================================
|
|
-- REVENUE METRICS - For Revenue, Transactions, P&L pages
|
|
-- Schema: id, timestamp, user_id, transaction_type, amount_cents, currency, source, metadata
|
|
-- =============================================================================
|
|
|
|
-- Generate subscription revenue (highest volume)
|
|
INSERT INTO revenue_metrics (user_id, transaction_type, amount_cents, currency, source, timestamp)
|
|
SELECT
|
|
gen_random_uuid(),
|
|
'SUBSCRIPTION',
|
|
(ARRAY[999, 1999, 2999, 4999])[floor(random() * 4 + 1)]::BIGINT,
|
|
'USD',
|
|
'stripe',
|
|
NOW() - (random() * INTERVAL '30 days')
|
|
FROM generate_series(1, 800);
|
|
|
|
-- Generate product sales
|
|
INSERT INTO revenue_metrics (user_id, transaction_type, amount_cents, currency, source, timestamp)
|
|
SELECT
|
|
gen_random_uuid(),
|
|
'PRODUCTSALE',
|
|
(floor(random() * 20000 + 1000))::BIGINT,
|
|
'USD',
|
|
'stripe',
|
|
NOW() - (random() * INTERVAL '30 days')
|
|
FROM generate_series(1, 400);
|
|
|
|
-- Generate tips
|
|
INSERT INTO revenue_metrics (user_id, transaction_type, amount_cents, currency, source, timestamp)
|
|
SELECT
|
|
gen_random_uuid(),
|
|
'TIP',
|
|
(ARRAY[500, 1000, 2000, 5000, 10000])[floor(random() * 5 + 1)]::BIGINT,
|
|
'USD',
|
|
'stripe',
|
|
NOW() - (random() * INTERVAL '30 days')
|
|
FROM generate_series(1, 300);
|
|
|
|
-- Generate service bookings
|
|
INSERT INTO revenue_metrics (user_id, transaction_type, amount_cents, currency, source, timestamp)
|
|
SELECT
|
|
gen_random_uuid(),
|
|
'SERVICEBOOKING',
|
|
(floor(random() * 50000 + 10000))::BIGINT,
|
|
'USD',
|
|
'stripe',
|
|
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);
|
|
|
|
-- 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);
|
|
|
|
-- 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);
|
|
|
|
-- 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 (already created by schema)
|
|
-- =============================================================================
|
|
|
|
-- 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 (already created by schema)
|
|
-- =============================================================================
|
|
|
|
-- 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 (already created by schema)
|
|
-- =============================================================================
|
|
|
|
-- 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 with amounts in cents
|
|
-- 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
|