mirror of
https://github.com/hanzoai/computer.git
synced 2026-10-26 11:01:00 +00:00
Complete Production Features (1-7): ==================================== 1. STRIPE PAYMENT INTEGRATION ✅ - Full checkout flow with Stripe Elements - Payment intent creation for one-time purchases - Subscription creation for monthly GPU leasing - Success page with order confirmation - Serverless functions: create-payment-intent, create-subscription - PCI-compliant card input with glass-morphism styling - Error handling and loading states - Test mode ready with Stripe test keys 2. EMAIL NOTIFICATION SYSTEM ✅ - SendGrid integration with professional templates - Quote emails with validity period - Order confirmations with invoice details - Subscription activation emails - RFQ confirmations (customer + admin) - Cluster request notifications - HTML + plain text versions - Responsive email design with Hanzo branding - API endpoints: send-quote, send-order, send-subscription, send-rfq 3. PDF INVOICE GENERATION ✅ - @react-pdf/renderer integration - Professional invoice templates with Hanzo branding - Automatic generation on order payment - Download from customer dashboard - Supabase storage integration - Admin invoice management - Regenerate capability - Email invoice attachments ready 4. USAGE ANALYTICS DASHBOARD ✅ - Comprehensive customer analytics at /analytics - Interactive charts: Line, Bar, Pie, Area charts - Metrics: compute hours, costs, GPU utilization - Date range selector (7/30/90 days, all time) - CSV export functionality - Usage tracking with Recharts - Real-time data from Supabase - Sample data generator for demo 5. API RATE LIMITING ✅ - Upstash Redis-based rate limiting - Role-based limits: anonymous (10/min), auth (100/min), admin (1000/min) - Endpoint-specific limits for sensitive operations - 429 Too Many Requests responses - Rate limit headers (X-RateLimit-*) - Frontend retry with exponential backoff - Admin dashboard for monitoring - Clear rate limits endpoint for admins - Database logging and violation tracking 6. STRIPE WEBHOOK HANDLERS ✅ - Webhook endpoint: /api/webhooks/stripe - Event handlers: payment success/failure, subscriptions, invoices, refunds - Signature verification for security - Idempotency handling (prevent duplicates) - Automatic order creation on payment - Subscription lifecycle management - Email triggers on events - Admin retry capability - Comprehensive event logging - Database schema for webhook tracking 7. ADMIN ANALYTICS & CHARTS ✅ - Enhanced Admin Dashboard with Analytics tab - Revenue charts: time series, by GPU type, cumulative - Conversion funnel: RFQ → Quote → Order - Customer growth metrics - Operational metrics: response times, quote performance - Top customers table - Interactive Recharts visualizations - Date range filtering - Auto-refresh every 5 minutes - CSV export for reports - Key metrics cards with % change indicators Technical Implementation: ======================== New Dependencies: - @stripe/stripe-js, @stripe/react-stripe-js, stripe - @sendgrid/mail - @react-pdf/renderer - recharts, date-fns - @upstash/ratelimit, @upstash/redis - micro (webhook body parsing) New Files Created (50+): - API routes: /api/webhooks/, /api/admin/, /api/create-*, /api/send-* - Libraries: stripe.ts, email.ts, invoices.ts, analytics.ts, rateLimit.ts - Components: Invoice, WebhookEventLog, RateLimitDashboard, DashboardInvoices - Pages: Analytics, CheckoutSuccess, admin/RateLimitDashboard - Documentation: EMAIL_NOTIFICATIONS.md, STRIPE_WEBHOOKS.md, RATE_LIMITING.md - Database: Supabase migrations for webhooks, analytics, rate limiting Environment Variables Required: - STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET - VITE_STRIPE_PUBLISHABLE_KEY - SENDGRID_API_KEY, EMAIL_FROM, ADMIN_EMAIL - UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN - ADMIN_API_KEY Build Status: ============= ✓ Production build: 807KB gzipped ✓ 3480 modules transformed ✓ Build time: 5.20s ✓ All TypeScript validated ✓ Zero compilation errors Ready for Launch: ================= ✅ Complete payment processing ✅ Professional email communications ✅ Automated invoicing ✅ Customer analytics ✅ API protection ✅ Webhook automation ✅ Business intelligence dashboard The platform is now enterprise-ready for production deployment!
231 lines
7.7 KiB
SQL
231 lines
7.7 KiB
SQL
-- Webhook events table for idempotency
|
|
CREATE TABLE IF NOT EXISTS webhook_events (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
event_id TEXT UNIQUE NOT NULL,
|
|
event_type TEXT NOT NULL,
|
|
processed BOOLEAN DEFAULT FALSE,
|
|
data JSONB,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
processed_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- Create index for quick lookup
|
|
CREATE INDEX idx_webhook_events_event_id ON webhook_events(event_id);
|
|
CREATE INDEX idx_webhook_events_processed ON webhook_events(processed);
|
|
|
|
-- Orders table for payment tracking
|
|
CREATE TABLE IF NOT EXISTS orders (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
payment_intent_id TEXT UNIQUE,
|
|
checkout_session_id TEXT UNIQUE,
|
|
customer_id TEXT,
|
|
customer_email TEXT,
|
|
amount DECIMAL(10, 2) NOT NULL,
|
|
currency TEXT DEFAULT 'usd',
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
failure_reason TEXT,
|
|
refund_id UUID,
|
|
refunded_amount DECIMAL(10, 2),
|
|
metadata JSONB,
|
|
paid_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Create indexes for orders
|
|
CREATE INDEX idx_orders_payment_intent ON orders(payment_intent_id);
|
|
CREATE INDEX idx_orders_status ON orders(status);
|
|
CREATE INDEX idx_orders_customer_email ON orders(customer_email);
|
|
|
|
-- Subscriptions table
|
|
CREATE TABLE IF NOT EXISTS subscriptions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
subscription_id TEXT UNIQUE NOT NULL,
|
|
customer_id TEXT NOT NULL,
|
|
status TEXT NOT NULL,
|
|
payment_status TEXT DEFAULT 'pending',
|
|
current_period_start TIMESTAMPTZ NOT NULL,
|
|
current_period_end TIMESTAMPTZ NOT NULL,
|
|
cancel_at TIMESTAMPTZ,
|
|
canceled_at TIMESTAMPTZ,
|
|
last_payment_date TIMESTAMPTZ,
|
|
active BOOLEAN DEFAULT TRUE,
|
|
items JSONB NOT NULL,
|
|
metadata JSONB,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Create indexes for subscriptions
|
|
CREATE INDEX idx_subscriptions_subscription_id ON subscriptions(subscription_id);
|
|
CREATE INDEX idx_subscriptions_customer_id ON subscriptions(customer_id);
|
|
CREATE INDEX idx_subscriptions_status ON subscriptions(status);
|
|
CREATE INDEX idx_subscriptions_active ON subscriptions(active);
|
|
|
|
-- Invoices table
|
|
CREATE TABLE IF NOT EXISTS invoices (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
order_id UUID REFERENCES orders(id) ON DELETE SET NULL,
|
|
subscription_id TEXT,
|
|
stripe_invoice_id TEXT UNIQUE,
|
|
payment_intent_id TEXT,
|
|
customer_id TEXT,
|
|
amount DECIMAL(10, 2) NOT NULL,
|
|
currency TEXT DEFAULT 'usd',
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
failure_reason TEXT,
|
|
invoice_pdf TEXT,
|
|
hosted_invoice_url TEXT,
|
|
metadata JSONB,
|
|
paid_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Create indexes for invoices
|
|
CREATE INDEX idx_invoices_order_id ON invoices(order_id);
|
|
CREATE INDEX idx_invoices_subscription_id ON invoices(subscription_id);
|
|
CREATE INDEX idx_invoices_stripe_invoice_id ON invoices(stripe_invoice_id);
|
|
CREATE INDEX idx_invoices_status ON invoices(status);
|
|
|
|
-- Refunds table
|
|
CREATE TABLE IF NOT EXISTS refunds (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
charge_id TEXT NOT NULL,
|
|
payment_intent_id TEXT,
|
|
amount DECIMAL(10, 2) NOT NULL,
|
|
currency TEXT DEFAULT 'usd',
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
reason TEXT,
|
|
metadata JSONB,
|
|
refunded_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Create indexes for refunds
|
|
CREATE INDEX idx_refunds_charge_id ON refunds(charge_id);
|
|
CREATE INDEX idx_refunds_payment_intent_id ON refunds(payment_intent_id);
|
|
|
|
-- Payment failures log
|
|
CREATE TABLE IF NOT EXISTS payment_failures (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
payment_intent_id TEXT,
|
|
amount DECIMAL(10, 2),
|
|
currency TEXT,
|
|
error_message TEXT,
|
|
error_code TEXT,
|
|
customer_email TEXT,
|
|
metadata JSONB,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Create index for payment failures
|
|
CREATE INDEX idx_payment_failures_payment_intent ON payment_failures(payment_intent_id);
|
|
CREATE INDEX idx_payment_failures_customer_email ON payment_failures(customer_email);
|
|
|
|
-- Subscription changes log
|
|
CREATE TABLE IF NOT EXISTS subscription_changes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
subscription_id TEXT NOT NULL,
|
|
change_type TEXT NOT NULL,
|
|
previous_data JSONB,
|
|
new_data JSONB,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Create index for subscription changes
|
|
CREATE INDEX idx_subscription_changes_subscription_id ON subscription_changes(subscription_id);
|
|
|
|
-- GPU access control table (for GPU subscriptions)
|
|
CREATE TABLE IF NOT EXISTS gpu_access (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
subscription_id TEXT,
|
|
customer_id TEXT,
|
|
gpu_type TEXT,
|
|
active BOOLEAN DEFAULT TRUE,
|
|
terminated_at TIMESTAMPTZ,
|
|
metadata JSONB,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Create indexes for GPU access
|
|
CREATE INDEX idx_gpu_access_subscription_id ON gpu_access(subscription_id);
|
|
CREATE INDEX idx_gpu_access_customer_id ON gpu_access(customer_id);
|
|
CREATE INDEX idx_gpu_access_active ON gpu_access(active);
|
|
|
|
-- Webhook retry log table
|
|
CREATE TABLE IF NOT EXISTS webhook_retry_log (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
event_id TEXT NOT NULL,
|
|
event_type TEXT,
|
|
retried_at TIMESTAMPTZ NOT NULL,
|
|
result TEXT NOT NULL,
|
|
message TEXT,
|
|
error_message TEXT,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Create indexes for retry log
|
|
CREATE INDEX idx_webhook_retry_log_event_id ON webhook_retry_log(event_id);
|
|
CREATE INDEX idx_webhook_retry_log_result ON webhook_retry_log(result);
|
|
|
|
-- Add RLS policies
|
|
ALTER TABLE webhook_events ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE subscriptions ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE refunds ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE payment_failures ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE subscription_changes ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE gpu_access ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE webhook_retry_log ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Admin-only access policies (webhook events should only be accessible by service role)
|
|
CREATE POLICY "Service role only" ON webhook_events
|
|
FOR ALL USING (auth.role() = 'service_role');
|
|
|
|
-- Orders can be viewed by the customer who made them
|
|
CREATE POLICY "Users can view their own orders" ON orders
|
|
FOR SELECT USING (auth.email() = customer_email);
|
|
|
|
CREATE POLICY "Service role full access to orders" ON orders
|
|
FOR ALL USING (auth.role() = 'service_role');
|
|
|
|
-- Subscriptions can be viewed by the owner
|
|
CREATE POLICY "Users can view their own subscriptions" ON subscriptions
|
|
FOR SELECT USING (
|
|
customer_id IN (
|
|
SELECT customer_id FROM orders WHERE customer_email = auth.email()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Service role full access to subscriptions" ON subscriptions
|
|
FOR ALL USING (auth.role() = 'service_role');
|
|
|
|
-- Invoices can be viewed by the owner
|
|
CREATE POLICY "Users can view their own invoices" ON invoices
|
|
FOR SELECT USING (
|
|
customer_id IN (
|
|
SELECT customer_id FROM orders WHERE customer_email = auth.email()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Service role full access to invoices" ON invoices
|
|
FOR ALL USING (auth.role() = 'service_role');
|
|
|
|
-- Service role only for other tables
|
|
CREATE POLICY "Service role only for refunds" ON refunds
|
|
FOR ALL USING (auth.role() = 'service_role');
|
|
|
|
CREATE POLICY "Service role only for payment_failures" ON payment_failures
|
|
FOR ALL USING (auth.role() = 'service_role');
|
|
|
|
CREATE POLICY "Service role only for subscription_changes" ON subscription_changes
|
|
FOR ALL USING (auth.role() = 'service_role');
|
|
|
|
CREATE POLICY "Service role only for gpu_access" ON gpu_access
|
|
FOR ALL USING (auth.role() = 'service_role');
|
|
|
|
CREATE POLICY "Service role only for webhook_retry_log" ON webhook_retry_log
|
|
FOR ALL USING (auth.role() = 'service_role'); |