mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 14:05:24 +02:00
Add experiments table migration instructions
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
co-authored by
Qwen-Coder
parent
a21c0d532c
commit
2b62bef707
@@ -0,0 +1,96 @@
|
|||||||
|
# Migración de Experimentos - Supabase
|
||||||
|
|
||||||
|
## Pasos para configurar la tabla de experimentos:
|
||||||
|
|
||||||
|
### 1. Ve a tu proyecto de Supabase
|
||||||
|
Abre: https://supabase.com/dashboard/project/qjioywarwdbxmdihyrti
|
||||||
|
|
||||||
|
### 2. Navega a SQL Editor
|
||||||
|
- Click en **"SQL Editor"** en la barra lateral izquierda
|
||||||
|
- Click en **"New query"**
|
||||||
|
|
||||||
|
### 3. Copia y ejecuta el siguiente SQL:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Crear tabla de experimentos
|
||||||
|
CREATE TABLE IF NOT EXISTS experiments (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
type TEXT NOT NULL CHECK (type IN ('pricing', 'advertising', 'content', 'promotion')),
|
||||||
|
status TEXT NOT NULL DEFAULT 'planned' CHECK (status IN ('planned', 'active', 'completed', 'paused')),
|
||||||
|
|
||||||
|
asins TEXT[] NOT NULL DEFAULT '{}',
|
||||||
|
marketplace TEXT NOT NULL,
|
||||||
|
|
||||||
|
start_date DATE NOT NULL,
|
||||||
|
end_date DATE,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
|
||||||
|
hypothesis TEXT,
|
||||||
|
primary_metric TEXT NOT NULL DEFAULT 'units',
|
||||||
|
target_lift_percent NUMERIC,
|
||||||
|
|
||||||
|
baseline_units NUMERIC,
|
||||||
|
baseline_revenue NUMERIC,
|
||||||
|
experiment_units NUMERIC,
|
||||||
|
experiment_revenue NUMERIC,
|
||||||
|
actual_lift_percent NUMERIC,
|
||||||
|
statistical_significance NUMERIC,
|
||||||
|
|
||||||
|
learnings TEXT,
|
||||||
|
owner TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Crear índices para mejorar rendimiento
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_status ON experiments(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_marketplace ON experiments(marketplace);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_type ON experiments(type);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_dates ON experiments(start_date, end_date);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_asins ON experiments USING GIN(asins);
|
||||||
|
|
||||||
|
-- Función para actualizar updated_at
|
||||||
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
NEW.updated_at = NOW();
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Trigger para actualizar updated_at automáticamente
|
||||||
|
DROP TRIGGER IF EXISTS update_experiments_updated_at ON experiments;
|
||||||
|
CREATE TRIGGER update_experiments_updated_at
|
||||||
|
BEFORE UPDATE ON experiments
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION update_updated_at_column();
|
||||||
|
|
||||||
|
-- Deshabilitar RLS para desarrollo (opcional, habilitar en producción)
|
||||||
|
ALTER TABLE experiments DISABLE ROW LEVEL SECURITY;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Click en **"Run"** para ejecutar el SQL
|
||||||
|
|
||||||
|
### 5. Verifica que se creó correctamente
|
||||||
|
- Ve a **"Table Editor"** en la barra lateral
|
||||||
|
- Deberías ver la tabla `experiments` en la lista
|
||||||
|
|
||||||
|
### 6. ¡Listo!
|
||||||
|
La pestaña de Experiments en tu aplicación ya debería funcionar correctamente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Solución de problemas:
|
||||||
|
|
||||||
|
### Error: "relation already exists"
|
||||||
|
La tabla ya existe. No necesitas hacer nada más.
|
||||||
|
|
||||||
|
### Error: "permission denied"
|
||||||
|
Asegúrate de estar usando la **service_role key** en tu `.env.local`:
|
||||||
|
```
|
||||||
|
SUPABASE_SERVICE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error: "type already exists"
|
||||||
|
Los tipos ya están definidos. El resto del SQL debería ejecutarse sin problemas.
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
import type { VercelRequest, VercelResponse } from '@vercel/node';
|
||||||
|
import { createClient } from '@supabase/supabase-js';
|
||||||
|
|
||||||
|
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
||||||
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
|
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
||||||
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
||||||
|
|
||||||
|
if (req.method === 'OPTIONS') return res.status(200).end();
|
||||||
|
if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' });
|
||||||
|
|
||||||
|
const supabaseUrl = process.env.SUPABASE_URL;
|
||||||
|
const supabaseServiceKey = process.env.SUPABASE_SERVICE_KEY;
|
||||||
|
|
||||||
|
if (!supabaseUrl || !supabaseServiceKey) {
|
||||||
|
return res.status(500).json({ error: 'Supabase credentials not configured' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const supabase = createClient(supabaseUrl, supabaseServiceKey);
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
CREATE TABLE IF NOT EXISTS experiments (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
type TEXT NOT NULL CHECK (type IN ('pricing', 'advertising', 'content', 'promotion')),
|
||||||
|
status TEXT NOT NULL DEFAULT 'planned' CHECK (status IN ('planned', 'active', 'completed', 'paused')),
|
||||||
|
|
||||||
|
asins TEXT[] NOT NULL DEFAULT '{}',
|
||||||
|
marketplace TEXT NOT NULL,
|
||||||
|
|
||||||
|
start_date DATE NOT NULL,
|
||||||
|
end_date DATE,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
|
||||||
|
hypothesis TEXT,
|
||||||
|
primary_metric TEXT NOT NULL DEFAULT 'units',
|
||||||
|
target_lift_percent NUMERIC,
|
||||||
|
|
||||||
|
baseline_units NUMERIC,
|
||||||
|
baseline_revenue NUMERIC,
|
||||||
|
experiment_units NUMERIC,
|
||||||
|
experiment_revenue NUMERIC,
|
||||||
|
actual_lift_percent NUMERIC,
|
||||||
|
statistical_significance NUMERIC,
|
||||||
|
|
||||||
|
learnings TEXT,
|
||||||
|
owner TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_status ON experiments(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_marketplace ON experiments(marketplace);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_type ON experiments(type);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_dates ON experiments(start_date, end_date);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_experiments_asins ON experiments USING GIN(asins);
|
||||||
|
|
||||||
|
-- Create updated_at trigger function if not exists
|
||||||
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
NEW.updated_at = NOW();
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Create trigger
|
||||||
|
DROP TRIGGER IF EXISTS update_experiments_updated_at ON experiments;
|
||||||
|
CREATE TRIGGER update_experiments_updated_at
|
||||||
|
BEFORE UPDATE ON experiments
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION update_updated_at_column();
|
||||||
|
`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Execute SQL via Supabase RPC or direct connection
|
||||||
|
// Since we can't run raw SQL via JS client, we'll create the table using the query builder
|
||||||
|
|
||||||
|
// First check if table exists
|
||||||
|
const { error: checkError } = await supabase.from('experiments').select('id').limit(1);
|
||||||
|
|
||||||
|
if (checkError && checkError.message.includes('relation') && checkError.message.includes('does not exist')) {
|
||||||
|
// Table doesn't exist - we need to create it via SQL
|
||||||
|
// Unfortunately the JS client can't run CREATE TABLE directly
|
||||||
|
// We'll return instructions
|
||||||
|
return res.status(200).json({
|
||||||
|
message: 'Table needs to be created via SQL Editor',
|
||||||
|
instructions: 'Please go to Supabase Dashboard → SQL Editor and run the migration SQL',
|
||||||
|
sql: sql
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table exists, create indexes
|
||||||
|
await supabase.rpc('create_experiment_indexes');
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: 'Experiments table is ready'
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
return res.status(500).json({
|
||||||
|
error: error.message,
|
||||||
|
instructions: 'Please go to Supabase Dashboard → SQL Editor and run the migration SQL manually'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user