mirror of
https://github.com/marcogll/AnchorOS.git
synced 2026-03-15 11:24:26 +00:00
refactor: migrate from old db/ to supabase CLI structure
- Migrated database schema from db/migrations to supabase/migrations - Added Supabase CLI configuration (config.toml, .gitignore) - Added kiosk role and amenities tables for touch kiosks - Added notification system for artist alerts - Added seed data with test locations and staff - Removed old migration scripts and documentation - Updated tasks_mg.md with current setup Features: - 2 locations: ANCHOR:23 - Via KLAVA and TEST - Kiosk role for touch screen check-in/booking - Amenities: coffee, cocktails, mocktails for clients - Notifications when client arrives - 1 staff + 4 artists + 1 kiosk per location - Services: hair, nails, makeup, lashes
This commit is contained in:
@@ -1,342 +0,0 @@
|
||||
# 🚀 Scripts Simples - SalonOS
|
||||
|
||||
Este directorio contiene scripts simplificados para facilitar el setup de SalonOS.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Scripts Disponibles
|
||||
|
||||
### 1. check-connection.sh
|
||||
**Qué hace:** Verifica la conexión a Supabase y si el puerto 5432 está abierto.
|
||||
|
||||
**Cómo ejecutar:**
|
||||
```bash
|
||||
./scripts/check-connection.sh
|
||||
```
|
||||
|
||||
**Output esperado:**
|
||||
```
|
||||
✅ psql instalado
|
||||
✅ Host alcanzable
|
||||
✅ Puerto 5432 está abierto
|
||||
✅ Conexión a base de datos exitosa
|
||||
✅ Tablas encontradas: 8/8
|
||||
✅ Funciones encontradas: 14
|
||||
```
|
||||
|
||||
**Si falla:**
|
||||
- Si el puerto está bloqueado, usa Supabase Dashboard
|
||||
- Si falla la conexión, verifica las credenciales
|
||||
|
||||
---
|
||||
|
||||
### 2. simple-verify.sh
|
||||
**Qué hace:** Verifica que todas las migraciones están correctas.
|
||||
|
||||
**Cómo ejecutar:**
|
||||
```bash
|
||||
./scripts/simple-verify.sh
|
||||
```
|
||||
|
||||
**Output esperado:**
|
||||
```
|
||||
📊 Verificando tablas...
|
||||
✅ Tablas: 8/8
|
||||
|
||||
📊 Verificando funciones...
|
||||
✅ Funciones: 14/14
|
||||
|
||||
📊 Verificando triggers...
|
||||
✅ Triggers: 17+/17+
|
||||
|
||||
📊 Verificando políticas RLS...
|
||||
✅ Políticas RLS: 24+/20+
|
||||
|
||||
📊 Probando generación de Short ID...
|
||||
✅ Short ID: A3F7X2 (6 caracteres)
|
||||
|
||||
📊 Probando generación de código de invitación...
|
||||
✅ Código de invitación: X9J4K2M5N8 (10 caracteres)
|
||||
|
||||
==========================================
|
||||
RESUMEN
|
||||
==========================================
|
||||
🎉 TODAS LAS MIGRACIONES ESTÁN CORRECTAS
|
||||
==========================================
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. simple-seed.sh
|
||||
**Qué hace:** Crea todos los datos de prueba en la base de datos.
|
||||
|
||||
**Cómo ejecutar:**
|
||||
```bash
|
||||
./scripts/simple-seed.sh
|
||||
```
|
||||
|
||||
**Output esperado:**
|
||||
```
|
||||
📍 Creando locations...
|
||||
✅ Locations: 3/3
|
||||
|
||||
🪑 Creando resources...
|
||||
✅ Resources: 6/6
|
||||
|
||||
👥 Creando staff...
|
||||
✅ Staff: 8/8
|
||||
|
||||
💇 Creando services...
|
||||
✅ Services: 6/6
|
||||
|
||||
👩 Creando customers...
|
||||
✅ Customers: 4/4
|
||||
|
||||
💌 Creando invitations...
|
||||
✅ Invitaciones: 15/15
|
||||
|
||||
📅 Creando bookings...
|
||||
✅ Bookings: 5/5
|
||||
|
||||
==========================================
|
||||
RESUMEN
|
||||
==========================================
|
||||
🎉 SEED DE DATOS COMPLETADO EXITOSAMENTE
|
||||
==========================================
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. create-auth-users.js
|
||||
**Qué hace:** Crea usuarios de staff y customers en Supabase Auth automáticamente.
|
||||
|
||||
**Requiere:** `npm install @supabase/supabase-js`
|
||||
|
||||
**Cómo ejecutar:**
|
||||
```bash
|
||||
node scripts/create-auth-users.js
|
||||
```
|
||||
|
||||
**Output esperado:**
|
||||
```
|
||||
👥 Creando usuarios de staff (8 usuarios)...
|
||||
|
||||
✅ Admin Principal creado (ID: ...)
|
||||
✅ Manager Centro creado (ID: ...)
|
||||
✅ Manager Polanco creado (ID: ...)
|
||||
✅ Staff Coordinadora creado (ID: ...)
|
||||
✅ Artist María García creado (ID: ...)
|
||||
✅ Artist Ana Rodríguez creado (ID: ...)
|
||||
✅ Artist Carla López creado (ID: ...)
|
||||
✅ Artist Laura Martínez creado (ID: ...)
|
||||
✅ Usuarios de staff creados: 8/8
|
||||
|
||||
🔄 Actualizando tabla staff con user_ids...
|
||||
|
||||
✅ Admin Principal actualizado con user_id
|
||||
✅ Manager Centro actualizado con user_id
|
||||
...
|
||||
✅ Staff actualizados: 8/8
|
||||
|
||||
👩 Creando usuarios de customers (4 usuarios)...
|
||||
|
||||
✅ Sofía Ramírez creado (ID: ...)
|
||||
✅ Valentina Hernández creado (ID: ...)
|
||||
✅ Camila López creado (ID: ...)
|
||||
✅ Isabella García creado (ID: ...)
|
||||
✅ Usuarios de customers creados: 4/4
|
||||
|
||||
🔄 Actualizando tabla customers con user_ids...
|
||||
|
||||
✅ Sofía Ramírez actualizado con user_id
|
||||
...
|
||||
✅ Customers actualizados: 4/4
|
||||
|
||||
==========================================
|
||||
RESUMEN FINAL
|
||||
==========================================
|
||||
Staff creados: 8/8
|
||||
Staff actualizados: 8/8
|
||||
Customers creados: 4/4
|
||||
Customers actualizados: 4/4
|
||||
==========================================
|
||||
|
||||
🎉 TODOS LOS USUARIOS HAN SIDO CREADOS Y ACTUALIZADOS
|
||||
|
||||
📝 Credenciales de prueba:
|
||||
|
||||
ADMIN:
|
||||
Email: admin@salonos.com
|
||||
Password: Admin123!
|
||||
|
||||
CUSTOMER (Gold):
|
||||
Email: sofia.ramirez@example.com
|
||||
Password: Customer123!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Si el Puerto 5432 Está Bloqueado
|
||||
|
||||
Si ejecutas `check-connection.sh` y el puerto está bloqueado, tienes estas opciones:
|
||||
|
||||
### Opción A: Usar Supabase Dashboard (Recomendado)
|
||||
1. Ve a: https://supabase.com/dashboard/project/pvvwbnybkadhreuqijsl/sql
|
||||
2. Copia el contenido de: `db/migrations/00_FULL_MIGRATION_FINAL.sql`
|
||||
3. Pega en el SQL Editor
|
||||
4. Haz clic en "Run"
|
||||
|
||||
### Opción B: Usar SQL desde Dashboard
|
||||
Para el seed, ejecuta estas consultas una por una:
|
||||
|
||||
**Crear locations:**
|
||||
```sql
|
||||
INSERT INTO locations (name, timezone, address, phone, is_active)
|
||||
VALUES
|
||||
('Salón Principal - Centro', 'America/Mexico_City', 'Av. Reforma 222', '+52 55 1234 5678', true),
|
||||
('Salón Norte - Polanco', 'America/Mexico_City', 'Av. Masaryk 123', '+52 55 2345 6789', true),
|
||||
('Salón Sur - Coyoacán', 'America/Mexico_City', 'Calle Hidalgo 456', '+52 55 3456 7890', true);
|
||||
```
|
||||
|
||||
**Crear staff:**
|
||||
```sql
|
||||
INSERT INTO staff (user_id, location_id, role, display_name, phone, is_active)
|
||||
VALUES
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'admin', 'Admin Principal', '+52 55 1111 2222', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'manager', 'Manager Centro', '+52 55 2222 3333', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'artist', 'Artist María García', '+52 55 4444 5555', true);
|
||||
```
|
||||
|
||||
**Crear usuarios de Auth manualmente:**
|
||||
1. Ve a: https://supabase.com/dashboard/project/pvvwbnybkadhreuqijsl/auth/users
|
||||
2. Haz clic en "Add user"
|
||||
3. Crea los usuarios con los emails de `scripts/create-auth-users.js`
|
||||
|
||||
---
|
||||
|
||||
## 📝 Flujo de Ejecución Recomendado
|
||||
|
||||
### Si el puerto 5432 está ABIERTO:
|
||||
|
||||
```bash
|
||||
# 1. Verificar conexión
|
||||
./scripts/check-connection.sh
|
||||
|
||||
# 2. Verificar migraciones
|
||||
./scripts/simple-verify.sh
|
||||
|
||||
# 3. Crear datos de prueba
|
||||
./scripts/simple-seed.sh
|
||||
|
||||
# 4. Crear usuarios de Auth
|
||||
node scripts/create-auth-users.js
|
||||
```
|
||||
|
||||
### Si el puerto 5432 está BLOQUEADO:
|
||||
|
||||
```bash
|
||||
# 1. Verificar conexión
|
||||
./scripts/check-connection.sh
|
||||
|
||||
# Esto te dirá que el puerto está bloqueado
|
||||
# Entonces usa Supabase Dashboard
|
||||
```
|
||||
|
||||
**En Supabase Dashboard:**
|
||||
1. Ve a: https://supabase.com/dashboard/project/pvvwbnybkadhreuqijsl/sql
|
||||
2. Copia el contenido de: `db/migrations/00_FULL_MIGRATION_FINAL.sql`
|
||||
3. Pega en el SQL Editor
|
||||
4. Haz clic en "Run"
|
||||
5. Para el seed, ejecuta las consultas de `scripts/simple-seed.sh` una por una
|
||||
6. Para crear usuarios, usa el Dashboard manualmente
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Error: "psql: command not found"
|
||||
**Solución:** Instala PostgreSQL client
|
||||
- macOS: `brew install postgresql`
|
||||
- Ubuntu/Debian: `sudo apt-get install postgresql-client`
|
||||
- Windows: Descargar desde https://www.postgresql.org/download/windows/
|
||||
|
||||
### Error: "connection to server failed"
|
||||
**Solución:**
|
||||
1. Verifica que las variables de entorno estén en `.env.local`
|
||||
2. Verifica que el puerto 5432 no esté bloqueado
|
||||
3. Si está bloqueado, usa Supabase Dashboard
|
||||
|
||||
### Error: "Password authentication failed"
|
||||
**Solución:**
|
||||
1. Verifica que `SUPABASE_SERVICE_ROLE_KEY` sea correcto
|
||||
2. Verifica que no tenga espacios o caracteres especiales
|
||||
3. Regenera el key en Supabase Dashboard si es necesario
|
||||
|
||||
### Error: "relation already exists"
|
||||
**Solución:**
|
||||
- Los datos ya existen. Continúa con el siguiente script
|
||||
- O elimina y recrea la base de datos
|
||||
|
||||
### Error: "User already registered"
|
||||
**Solución:**
|
||||
- El usuario ya existe en Supabase Auth
|
||||
- Borra el usuario en Supabase Dashboard y vuelve a ejecutar el script
|
||||
|
||||
---
|
||||
|
||||
## 📚 Documentación Adicional
|
||||
|
||||
- **`docs/STEP_BY_STEP_VERIFICATION.md`** - Guía detallada paso a paso
|
||||
- **`docs/STEP_BY_STEP_AUTH_CONFIG.md`** - Guía de configuración de Auth
|
||||
- **`docs/POST_MIGRATION_SUCCESS.md`** - Guía post-migración
|
||||
- **`docs/QUICK_START_POST_MIGRATION.md`** - Guía rápida de referencia
|
||||
|
||||
---
|
||||
|
||||
## ✅ Checklist
|
||||
|
||||
### Verificar Conexión
|
||||
- [ ] `check-connection.sh` ejecutado
|
||||
- [ ] Puerto 5432 abierto (o usar Dashboard)
|
||||
- [ ] Conexión a DB exitosa
|
||||
|
||||
### Verificar Migraciones
|
||||
- [ ] `simple-verify.sh` ejecutado
|
||||
- [ ] Todas las tablas creadas (8/8)
|
||||
- [ ] Todas las funciones creadas (14/14)
|
||||
- [ ] Todos los triggers activos (17+)
|
||||
|
||||
### Seed de Datos
|
||||
- [ ] `simple-seed.sh` ejecutado
|
||||
- [ ] Locations creadas (3/3)
|
||||
- [ ] Resources creados (6/6)
|
||||
- [ ] Staff creado (8/8)
|
||||
- [ ] Services creados (6/6)
|
||||
- [ ] Customers creados (4/4)
|
||||
- [ ] Invitaciones creadas (15/15)
|
||||
- [ ] Bookings creados (5/5)
|
||||
|
||||
### Crear Usuarios Auth
|
||||
- [ ] `create-auth-users.js` ejecutado
|
||||
- [ ] Staff creados (8/8)
|
||||
- [ ] Staff actualizados (8/8)
|
||||
- [ ] Customers creados (4/4)
|
||||
- [ ] Customers actualizados (4/4)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Próximos Pasos
|
||||
|
||||
Después de completar todos los scripts:
|
||||
|
||||
1. **Probar login** con las credenciales:
|
||||
- Admin: `admin@salonos.com` / `Admin123!`
|
||||
- Customer: `sofia.ramirez@example.com` / `Customer123!`
|
||||
|
||||
2. **Verificar políticas RLS** en Supabase Dashboard
|
||||
|
||||
3. **Continuar con el desarrollo** de la aplicación
|
||||
|
||||
---
|
||||
|
||||
**¿Necesitas ayuda con alguno de los scripts?**
|
||||
@@ -1,157 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script para verificar conexión a Supabase y desbloquear puertos
|
||||
# Ejecutar con: ./scripts/check-connection.sh
|
||||
|
||||
echo "=========================================="
|
||||
echo "SALONOS - VERIFICACIÓN DE CONEXIÓN"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Cargar variables de entorno
|
||||
set -a
|
||||
source .env.local
|
||||
set +a
|
||||
|
||||
if [ -z "$NEXT_PUBLIC_SUPABASE_URL" ] || [ -z "$SUPABASE_SERVICE_ROLE_KEY" ]; then
|
||||
echo "❌ ERROR: Faltan variables de entorno"
|
||||
echo "Asegúrate de tener NEXT_PUBLIC_SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY en .env.local"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extraer host de la URL
|
||||
DB_HOST="${NEXT_PUBLIC_SUPABASE_URL#https://}"
|
||||
|
||||
echo "📊 Información de conexión:"
|
||||
echo " Host: $DB_HOST"
|
||||
echo " Puerto: 5432"
|
||||
echo ""
|
||||
|
||||
# 1. Verificar si psql está instalado
|
||||
echo "1️⃣ Verificando si psql está instalado..."
|
||||
if command -v psql &> /dev/null; then
|
||||
PSQL_VERSION=$(psql --version)
|
||||
echo " ✅ psql instalado: $PSQL_VERSION"
|
||||
else
|
||||
echo " ❌ psql NO está instalado"
|
||||
echo ""
|
||||
echo " Para instalar psql:"
|
||||
echo " - macOS: brew install postgresql"
|
||||
echo " - Ubuntu/Debian: sudo apt-get install postgresql-client"
|
||||
echo " - Windows: Descargar desde https://www.postgresql.org/download/windows/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# 2. Verificar conectividad con ping
|
||||
echo "2️⃣ Verificando conectividad con ping..."
|
||||
if ping -c 2 -4 $DB_HOST &> /dev/null; then
|
||||
echo " ✅ Host alcanzable"
|
||||
else
|
||||
echo " ❌ Host NO alcanzable"
|
||||
echo " Verifica tu conexión a internet"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# 3. Verificar si el puerto 5432 está abierto
|
||||
echo "3️⃣ Verificando si el puerto 5432 está abierto..."
|
||||
if command -v nc &> /dev/null; then
|
||||
if nc -z -w5 $DB_HOST 5432 2>/dev/null; then
|
||||
echo " ✅ Puerto 5432 está abierto"
|
||||
else
|
||||
echo " ❌ Puerto 5432 está bloqueado"
|
||||
echo ""
|
||||
echo " 📋 SOLUCIÓN:"
|
||||
echo " El puerto 5432 está bloqueado, posiblemente por:"
|
||||
echo " 1. Firewall de tu empresa/ISP"
|
||||
echo " 2. VPN corporativa"
|
||||
echo " 3. Configuración de red local"
|
||||
echo ""
|
||||
echo " Opciones:"
|
||||
echo " a. Usar Supabase Dashboard (recomendado)"
|
||||
echo " b. Configurar VPN para permitir el puerto 5432"
|
||||
echo " c. Usar túnel SSH para bypass del firewall"
|
||||
echo " d. Contactar a tu administrador de red"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo " ⚠️ nc no está disponible, no se puede verificar el puerto"
|
||||
echo " Continuando con la prueba de conexión..."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# 4. Configurar DATABASE_URL
|
||||
DB_URL="postgresql://postgres:${SUPABASE_SERVICE_ROLE_KEY}@${DB_HOST}:5432/postgres"
|
||||
|
||||
# 5. Probar conexión a la base de datos
|
||||
echo "4️⃣ Probar conexión a la base de datos..."
|
||||
if psql "$DB_URL" -c "SELECT 'Connection successful' as status;" &> /dev/null; then
|
||||
echo " ✅ Conexión a base de datos exitosa"
|
||||
else
|
||||
echo " ❌ Conexión a base de datos fallida"
|
||||
echo ""
|
||||
echo " 📋 SOLUCIÓN:"
|
||||
echo " 1. Verifica que las credenciales sean correctas"
|
||||
echo " 2. Verifica que el proyecto de Supabase esté activo"
|
||||
echo " 3. Verifica que el service_role_key sea correcto"
|
||||
echo " 4. Si el puerto está bloqueado, usa Supabase Dashboard"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# 6. Verificar tablas
|
||||
echo "5️⃣ Verificando tablas..."
|
||||
TABLE_COUNT=$(psql "$DB_URL" -t -c "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name IN ('locations', 'resources', 'staff', 'services', 'customers', 'invitations', 'bookings', 'audit_logs');
|
||||
")
|
||||
|
||||
echo " ✅ Tablas encontradas: $TABLE_COUNT/8"
|
||||
|
||||
# 7. Verificar funciones
|
||||
echo "6️⃣ Verificando funciones..."
|
||||
FUNC_COUNT=$(psql "$DB_URL" -t -c "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.routines
|
||||
WHERE routine_schema = 'public';
|
||||
")
|
||||
|
||||
echo " ✅ Funciones encontradas: $FUNC_COUNT"
|
||||
|
||||
echo ""
|
||||
|
||||
# 8. Resumen
|
||||
echo "=========================================="
|
||||
echo "RESUMEN"
|
||||
echo "=========================================="
|
||||
echo "Host: $DB_HOST"
|
||||
echo "Puerto: 5432"
|
||||
echo "psql: ✅ Instalado"
|
||||
echo "Conexión: ✅ Exitosa"
|
||||
echo "Tablas: $TABLE_COUNT/8"
|
||||
echo "Funciones: $FUNC_COUNT"
|
||||
echo "=========================================="
|
||||
|
||||
if [ "$TABLE_COUNT" -eq 8 ] && [ "$FUNC_COUNT" -ge 14 ]; then
|
||||
echo ""
|
||||
echo "🎉 CONEXIÓN VERIFICADA EXITOSAMENTE"
|
||||
echo ""
|
||||
echo "Próximos pasos:"
|
||||
echo "1. Ejecutar: ./scripts/simple-verify.sh"
|
||||
echo "2. Ejecutar: ./scripts/simple-seed.sh"
|
||||
echo "3. Ejecutar: node scripts/create-auth-users.js"
|
||||
echo ""
|
||||
echo "O usar Supabase Dashboard:"
|
||||
echo "https://supabase.com/dashboard/project/pvvwbnybkadhreuqijsl/sql"
|
||||
else
|
||||
echo ""
|
||||
echo "⚠️ ALGUNOS ELEMENTOS FALTAN"
|
||||
echo "Por favor, ejecuta las migraciones nuevamente"
|
||||
fi
|
||||
@@ -1,330 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script simple para crear usuarios de Auth en Supabase
|
||||
* Ejecutar con: node scripts/create-auth-users.js
|
||||
* Requiere: npm install @supabase/supabase-js
|
||||
*/
|
||||
|
||||
require('dotenv').config({ path: '.env.local' })
|
||||
const { createClient } = require('@supabase/supabase-js')
|
||||
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
|
||||
const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY
|
||||
|
||||
if (!supabaseUrl || !supabaseServiceKey) {
|
||||
console.error('❌ ERROR: Faltan variables de entorno')
|
||||
console.error('Asegúrate de tener NEXT_PUBLIC_SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY en .env.local')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const supabase = createClient(supabaseUrl, supabaseServiceKey)
|
||||
|
||||
// Usuarios de staff
|
||||
const staffUsers = [
|
||||
{
|
||||
email: 'admin@salonos.com',
|
||||
password: 'Admin123!',
|
||||
role: 'admin',
|
||||
display_name: 'Admin Principal',
|
||||
phone: '+52 55 1111 2222',
|
||||
location: 'Salón Principal - Centro'
|
||||
},
|
||||
{
|
||||
email: 'manager.centro@salonos.com',
|
||||
password: 'Manager123!',
|
||||
role: 'manager',
|
||||
display_name: 'Manager Centro',
|
||||
phone: '+52 55 2222 3333',
|
||||
location: 'Salón Principal - Centro'
|
||||
},
|
||||
{
|
||||
email: 'manager.polanco@salonos.com',
|
||||
password: 'Manager123!',
|
||||
role: 'manager',
|
||||
display_name: 'Manager Polanco',
|
||||
phone: '+52 55 6666 7777',
|
||||
location: 'Salón Norte - Polanco'
|
||||
},
|
||||
{
|
||||
email: 'staff.coordinadora@salonos.com',
|
||||
password: 'Staff123!',
|
||||
role: 'staff',
|
||||
display_name: 'Staff Coordinadora',
|
||||
phone: '+52 55 3333 4444',
|
||||
location: 'Salón Principal - Centro'
|
||||
},
|
||||
{
|
||||
email: 'artist.maria@salonos.com',
|
||||
password: 'Artist123!',
|
||||
role: 'artist',
|
||||
display_name: 'Artist María García',
|
||||
phone: '+52 55 4444 5555',
|
||||
location: 'Salón Principal - Centro'
|
||||
},
|
||||
{
|
||||
email: 'artist.ana@salonos.com',
|
||||
password: 'Artist123!',
|
||||
role: 'artist',
|
||||
display_name: 'Artist Ana Rodríguez',
|
||||
phone: '+52 55 5555 6666',
|
||||
location: 'Salón Principal - Centro'
|
||||
},
|
||||
{
|
||||
email: 'artist.carla@salonos.com',
|
||||
password: 'Artist123!',
|
||||
role: 'artist',
|
||||
display_name: 'Artist Carla López',
|
||||
phone: '+52 55 7777 8888',
|
||||
location: 'Salón Norte - Polanco'
|
||||
},
|
||||
{
|
||||
email: 'artist.laura@salonos.com',
|
||||
password: 'Artist123!',
|
||||
role: 'artist',
|
||||
display_name: 'Artist Laura Martínez',
|
||||
phone: '+52 55 8888 9999',
|
||||
location: 'Salón Sur - Coyoacán'
|
||||
}
|
||||
]
|
||||
|
||||
// Usuarios de customers
|
||||
const customerUsers = [
|
||||
{
|
||||
email: 'sofia.ramirez@example.com',
|
||||
password: 'Customer123!',
|
||||
tier: 'gold',
|
||||
display_name: 'Sofía Ramírez'
|
||||
},
|
||||
{
|
||||
email: 'valentina.hernandez@example.com',
|
||||
password: 'Customer123!',
|
||||
tier: 'gold',
|
||||
display_name: 'Valentina Hernández'
|
||||
},
|
||||
{
|
||||
email: 'camila.lopez@example.com',
|
||||
password: 'Customer123!',
|
||||
tier: 'free',
|
||||
display_name: 'Camila López'
|
||||
},
|
||||
{
|
||||
email: 'isabella.garcia@example.com',
|
||||
password: 'Customer123!',
|
||||
tier: 'gold',
|
||||
display_name: 'Isabella García'
|
||||
}
|
||||
]
|
||||
|
||||
async function createStaffUser(user) {
|
||||
try {
|
||||
// Crear usuario en Supabase Auth
|
||||
const { data, error } = await supabase.auth.admin.createUser({
|
||||
email: user.email,
|
||||
password: user.password,
|
||||
email_confirm: true,
|
||||
user_metadata: {
|
||||
role: user.role,
|
||||
display_name: user.display_name,
|
||||
location: user.location,
|
||||
phone: user.phone
|
||||
}
|
||||
})
|
||||
|
||||
if (error) {
|
||||
console.error(`❌ Error creando ${user.display_name}:`, error.message)
|
||||
return null
|
||||
}
|
||||
|
||||
console.log(`✅ ${user.display_name} creado (ID: ${data.user.id})`)
|
||||
return data.user
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Error inesperado creando ${user.display_name}:`, error.message)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function createCustomerUser(user) {
|
||||
try {
|
||||
// Crear usuario en Supabase Auth
|
||||
const { data, error } = await supabase.auth.admin.createUser({
|
||||
email: user.email,
|
||||
password: user.password,
|
||||
email_confirm: true,
|
||||
user_metadata: {
|
||||
tier: user.tier,
|
||||
display_name: user.display_name
|
||||
}
|
||||
})
|
||||
|
||||
if (error) {
|
||||
console.error(`❌ Error creando ${user.display_name}:`, error.message)
|
||||
return null
|
||||
}
|
||||
|
||||
console.log(`✅ ${user.display_name} creado (ID: ${data.user.id})`)
|
||||
return data.user
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Error inesperado creando ${user.display_name}:`, error.message)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function updateStaffUserId(user) {
|
||||
try {
|
||||
const { error } = await supabase
|
||||
.from('staff')
|
||||
.update({ user_id: user.id })
|
||||
.eq('display_name', user.display_name)
|
||||
|
||||
if (error) {
|
||||
console.error(`❌ Error actualizando ${user.display_name}:`, error.message)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log(`✅ ${user.display_name} actualizado con user_id`)
|
||||
return true
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Error inesperado actualizando ${user.display_name}:`, error.message)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function updateCustomerUserId(user) {
|
||||
try {
|
||||
const { error } = await supabase
|
||||
.from('customers')
|
||||
.update({ user_id: user.id })
|
||||
.eq('email', user.email)
|
||||
|
||||
if (error) {
|
||||
console.error(`❌ Error actualizando ${user.display_name}:`, error.message)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log(`✅ ${user.display_name} actualizado con user_id`)
|
||||
return true
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Error inesperado actualizando ${user.display_name}:`, error.message)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('==========================================')
|
||||
console.log('SALONOS - CREACIÓN DE USUARIOS AUTH')
|
||||
console.log('==========================================')
|
||||
console.log()
|
||||
|
||||
// 1. Crear usuarios de staff
|
||||
console.log('👥 Creando usuarios de staff (8 usuarios)...')
|
||||
console.log()
|
||||
|
||||
const createdStaff = []
|
||||
for (const user of staffUsers) {
|
||||
const createdUser = await createStaffUser(user)
|
||||
if (createdUser) {
|
||||
createdStaff.push({
|
||||
...user,
|
||||
id: createdUser.id
|
||||
})
|
||||
}
|
||||
// Pequeña pausa para evitar rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
}
|
||||
|
||||
console.log()
|
||||
console.log(`✅ Usuarios de staff creados: ${createdStaff.length}/8`)
|
||||
|
||||
// 2. Actualizar tabla staff con user_ids
|
||||
console.log()
|
||||
console.log('🔄 Actualizando tabla staff con user_ids...')
|
||||
console.log()
|
||||
|
||||
let updatedStaffCount = 0
|
||||
for (const user of createdStaff) {
|
||||
const updated = await updateStaffUserId(user)
|
||||
if (updated) {
|
||||
updatedStaffCount++
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 200))
|
||||
}
|
||||
|
||||
console.log()
|
||||
console.log(`✅ Staff actualizados: ${updatedStaffCount}/8`)
|
||||
|
||||
// 3. Crear usuarios de customers
|
||||
console.log()
|
||||
console.log('👩 Creando usuarios de customers (4 usuarios)...')
|
||||
console.log()
|
||||
|
||||
const createdCustomers = []
|
||||
for (const user of customerUsers) {
|
||||
const createdUser = await createCustomerUser(user)
|
||||
if (createdUser) {
|
||||
createdCustomers.push({
|
||||
...user,
|
||||
id: createdUser.id
|
||||
})
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
}
|
||||
|
||||
console.log()
|
||||
console.log(`✅ Usuarios de customers creados: ${createdCustomers.length}/4`)
|
||||
|
||||
// 4. Actualizar tabla customers con user_ids
|
||||
console.log()
|
||||
console.log('🔄 Actualizando tabla customers con user_ids...')
|
||||
console.log()
|
||||
|
||||
let updatedCustomersCount = 0
|
||||
for (const user of createdCustomers) {
|
||||
const updated = await updateCustomerUserId(user)
|
||||
if (updated) {
|
||||
updatedCustomersCount++
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 200))
|
||||
}
|
||||
|
||||
console.log()
|
||||
console.log(`✅ Customers actualizados: ${updatedCustomersCount}/4`)
|
||||
|
||||
// 5. Resumen final
|
||||
console.log()
|
||||
console.log('==========================================')
|
||||
console.log('RESUMEN FINAL')
|
||||
console.log('==========================================')
|
||||
console.log(`Staff creados: ${createdStaff.length}/8`)
|
||||
console.log(`Staff actualizados: ${updatedStaffCount}/8`)
|
||||
console.log(`Customers creados: ${createdCustomers.length}/4`)
|
||||
console.log(`Customers actualizados: ${updatedCustomersCount}/4`)
|
||||
console.log('==========================================')
|
||||
|
||||
if (createdStaff.length === 8 && updatedStaffCount === 8 && createdCustomers.length === 4 && updatedCustomersCount === 4) {
|
||||
console.log()
|
||||
console.log('🎉 TODOS LOS USUARIOS HAN SIDO CREADOS Y ACTUALIZADOS')
|
||||
console.log()
|
||||
console.log('📝 Credenciales de prueba:')
|
||||
console.log()
|
||||
console.log('ADMIN:')
|
||||
console.log(' Email: admin@salonos.com')
|
||||
console.log(' Password: Admin123!')
|
||||
console.log()
|
||||
console.log('CUSTOMER (Gold):')
|
||||
console.log(' Email: sofia.ramirez@example.com')
|
||||
console.log(' Password: Customer123!')
|
||||
console.log()
|
||||
console.log('Puedes usar estas credenciales para probar el login.')
|
||||
} else {
|
||||
console.log()
|
||||
console.log('⚠️ ALGUNOS USUARIOS NO FUERON CREADOS O ACTUALIZADOS')
|
||||
console.log('Por favor, verifica los errores arriba.')
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -1,439 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script de seed de datos - SalonOS
|
||||
* Crea datos de prueba para development
|
||||
*/
|
||||
|
||||
const { createClient } = require('@supabase/supabase-js')
|
||||
|
||||
// Cargar variables de entorno
|
||||
require('dotenv').config({ path: '.env.local' })
|
||||
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
|
||||
const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY
|
||||
|
||||
if (!supabaseUrl || !supabaseServiceKey) {
|
||||
console.error('❌ ERROR: Faltan variables de entorno')
|
||||
console.error('Asegúrate de tener NEXT_PUBLIC_SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY en .env.local')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const supabase = createClient(supabaseUrl, supabaseServiceKey)
|
||||
|
||||
console.log('==========================================')
|
||||
console.log('SALONOS - SEED DE DATOS')
|
||||
console.log('==========================================')
|
||||
console.log()
|
||||
|
||||
async function seedLocations() {
|
||||
console.log('📍 Creando locations...')
|
||||
|
||||
const { data, error } = await supabase.from('locations').insert([
|
||||
{
|
||||
name: 'Salón Principal - Centro',
|
||||
timezone: 'America/Mexico_City',
|
||||
address: 'Av. Reforma 222, Centro Histórico, Ciudad de México',
|
||||
phone: '+52 55 1234 5678',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
name: 'Salón Norte - Polanco',
|
||||
timezone: 'America/Mexico_City',
|
||||
address: 'Av. Masaryk 123, Polanco, Ciudad de México',
|
||||
phone: '+52 55 2345 6789',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
name: 'Salón Sur - Coyoacán',
|
||||
timezone: 'America/Mexico_City',
|
||||
address: 'Calle Hidalgo 456, Coyoacán, Ciudad de México',
|
||||
phone: '+52 55 3456 7890',
|
||||
is_active: true,
|
||||
},
|
||||
]).select()
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al crear locations:', error)
|
||||
return []
|
||||
}
|
||||
|
||||
console.log(`✅ ${data.length} locations creadas`)
|
||||
return data
|
||||
}
|
||||
|
||||
async function seedResources(locations) {
|
||||
console.log('🪑 Creando resources...')
|
||||
|
||||
const resources = []
|
||||
|
||||
for (const location of locations) {
|
||||
const { data, error } = await supabase.from('resources').insert([
|
||||
{
|
||||
location_id: location.id,
|
||||
name: `Estación ${Math.floor(Math.random() * 100)}`,
|
||||
type: 'station',
|
||||
capacity: 1,
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
location_id: location.id,
|
||||
name: `Sala VIP ${Math.floor(Math.random() * 100)}`,
|
||||
type: 'room',
|
||||
capacity: 2,
|
||||
is_active: true,
|
||||
},
|
||||
]).select()
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al crear resources:', error)
|
||||
continue
|
||||
}
|
||||
|
||||
resources.push(...data)
|
||||
}
|
||||
|
||||
console.log(`✅ ${resources.length} resources creadas`)
|
||||
return resources
|
||||
}
|
||||
|
||||
async function seedStaff(locations) {
|
||||
console.log('👥 Creando staff...')
|
||||
|
||||
const { data, error } = await supabase.from('staff').insert([
|
||||
{
|
||||
user_id: '00000000-0000-0000-0000-000000000001',
|
||||
location_id: locations[0].id,
|
||||
role: 'admin',
|
||||
display_name: 'Admin Principal',
|
||||
phone: '+52 55 1111 2222',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '00000000-0000-0000-0000-000000000002',
|
||||
location_id: locations[0].id,
|
||||
role: 'manager',
|
||||
display_name: 'Manager Centro',
|
||||
phone: '+52 55 2222 3333',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '00000000-0000-0000-0000-000000000003',
|
||||
location_id: locations[0].id,
|
||||
role: 'staff',
|
||||
display_name: 'Staff Coordinadora',
|
||||
phone: '+52 55 3333 4444',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '00000000-0000-0000-0000-000000000004',
|
||||
location_id: locations[0].id,
|
||||
role: 'artist',
|
||||
display_name: 'Artist María García',
|
||||
phone: '+52 55 4444 5555',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '00000000-0000-0000-0000-000000000005',
|
||||
location_id: locations[0].id,
|
||||
role: 'artist',
|
||||
display_name: 'Artist Ana Rodríguez',
|
||||
phone: '+52 55 5555 6666',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '00000000-0000-0000-0000-000000000006',
|
||||
location_id: locations[1].id,
|
||||
role: 'manager',
|
||||
display_name: 'Manager Polanco',
|
||||
phone: '+52 55 6666 7777',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '00000000-0000-0000-0000-000000000007',
|
||||
location_id: locations[1].id,
|
||||
role: 'artist',
|
||||
display_name: 'Artist Carla López',
|
||||
phone: '+52 55 7777 8888',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '00000000-0000-0000-0000-000000000008',
|
||||
location_id: locations[2].id,
|
||||
role: 'artist',
|
||||
display_name: 'Artist Laura Martínez',
|
||||
phone: '+52 55 8888 9999',
|
||||
is_active: true,
|
||||
},
|
||||
]).select()
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al crear staff:', error)
|
||||
return []
|
||||
}
|
||||
|
||||
console.log(`✅ ${data.length} staff creados`)
|
||||
return data
|
||||
}
|
||||
|
||||
async function seedServices() {
|
||||
console.log('💇 Creando services...')
|
||||
|
||||
const { data, error } = await supabase.from('services').insert([
|
||||
{
|
||||
name: 'Corte y Estilizado',
|
||||
description: 'Corte de cabello profesional con lavado y estilizado',
|
||||
duration_minutes: 60,
|
||||
base_price: 500.00,
|
||||
requires_dual_artist: false,
|
||||
premium_fee_enabled: false,
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
name: 'Color Completo',
|
||||
description: 'Tinte completo con protección capilar',
|
||||
duration_minutes: 120,
|
||||
base_price: 1200.00,
|
||||
requires_dual_artist: false,
|
||||
premium_fee_enabled: true,
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
name: 'Balayage Premium',
|
||||
description: 'Técnica de balayage con productos premium',
|
||||
duration_minutes: 180,
|
||||
base_price: 2000.00,
|
||||
requires_dual_artist: true,
|
||||
premium_fee_enabled: true,
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
name: 'Tratamiento Kératina',
|
||||
description: 'Tratamiento de kératina para cabello dañado',
|
||||
duration_minutes: 90,
|
||||
base_price: 1500.00,
|
||||
requires_dual_artist: false,
|
||||
premium_fee_enabled: false,
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
name: 'Peinado Evento',
|
||||
description: 'Peinado para eventos especiales',
|
||||
duration_minutes: 45,
|
||||
base_price: 800.00,
|
||||
requires_dual_artist: false,
|
||||
premium_fee_enabled: true,
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
name: 'Servicio Express (Dual Artist)',
|
||||
description: 'Servicio rápido con dos artists simultáneas',
|
||||
duration_minutes: 30,
|
||||
base_price: 600.00,
|
||||
requires_dual_artist: true,
|
||||
premium_fee_enabled: true,
|
||||
is_active: true,
|
||||
},
|
||||
]).select()
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al crear services:', error)
|
||||
return []
|
||||
}
|
||||
|
||||
console.log(`✅ ${data.length} services creados`)
|
||||
return data
|
||||
}
|
||||
|
||||
async function seedCustomers() {
|
||||
console.log('👩 Creando customers...')
|
||||
|
||||
const { data, error } = await supabase.from('customers').insert([
|
||||
{
|
||||
user_id: '10000000-0000-0000-0000-000000000001',
|
||||
first_name: 'Sofía',
|
||||
last_name: 'Ramírez',
|
||||
email: 'sofia.ramirez@example.com',
|
||||
phone: '+52 55 1111 1111',
|
||||
tier: 'gold',
|
||||
notes: 'Cliente VIP. Prefiere Artists María y Ana.',
|
||||
total_spent: 15000.00,
|
||||
total_visits: 25,
|
||||
last_visit_date: '2025-12-20',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '10000000-0000-0000-0000-000000000002',
|
||||
first_name: 'Valentina',
|
||||
last_name: 'Hernández',
|
||||
email: 'valentina.hernandez@example.com',
|
||||
phone: '+52 55 2222 2222',
|
||||
tier: 'gold',
|
||||
notes: 'Cliente regular. Prefiere horarios de la mañana.',
|
||||
total_spent: 8500.00,
|
||||
total_visits: 15,
|
||||
last_visit_date: '2025-12-15',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '10000000-0000-0000-0000-000000000003',
|
||||
first_name: 'Camila',
|
||||
last_name: 'López',
|
||||
email: 'camila.lopez@example.com',
|
||||
phone: '+52 55 3333 3333',
|
||||
tier: 'free',
|
||||
notes: 'Nueva cliente. Referida por Valentina.',
|
||||
total_spent: 500.00,
|
||||
total_visits: 1,
|
||||
last_visit_date: '2025-12-10',
|
||||
is_active: true,
|
||||
},
|
||||
{
|
||||
user_id: '10000000-0000-0000-0000-000000000004',
|
||||
first_name: 'Isabella',
|
||||
last_name: 'García',
|
||||
email: 'isabella.garcia@example.com',
|
||||
phone: '+52 55 4444 4444',
|
||||
tier: 'gold',
|
||||
notes: 'Cliente VIP. Requiere servicio de Balayage.',
|
||||
total_spent: 22000.00,
|
||||
total_visits: 30,
|
||||
last_visit_date: '2025-12-18',
|
||||
is_active: true,
|
||||
},
|
||||
]).select()
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al crear customers:', error)
|
||||
return []
|
||||
}
|
||||
|
||||
console.log(`✅ ${data.length} customers creados`)
|
||||
return data
|
||||
}
|
||||
|
||||
async function seedInvitations(customers) {
|
||||
console.log('💌 Creando invitations...')
|
||||
|
||||
const weekStart = new Date()
|
||||
weekStart.setDate(weekStart.getDate() - weekStart.getDay() + 1) // Monday
|
||||
weekStart.setHours(0, 0, 0, 0)
|
||||
|
||||
const invitations = []
|
||||
|
||||
for (const customer of customers) {
|
||||
if (customer.tier === 'gold') {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const { data, error } = await supabase.from('invitations').insert({
|
||||
inviter_id: customer.id,
|
||||
code: await generateRandomCode(),
|
||||
status: 'pending',
|
||||
week_start_date: weekStart.toISOString().split('T')[0],
|
||||
expiry_date: new Date(weekStart.getTime() + 6 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
||||
}).select()
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al crear invitations:', error)
|
||||
continue
|
||||
}
|
||||
|
||||
invitations.push(...data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ ${invitations.length} invitations creadas`)
|
||||
return invitations
|
||||
}
|
||||
|
||||
async function generateRandomCode() {
|
||||
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
let code = ''
|
||||
for (let i = 0; i < 10; i++) {
|
||||
code += chars.charAt(Math.floor(Math.random() * chars.length))
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
async function seedBookings(customers, staff, resources, services, locations) {
|
||||
console.log('📅 Creando bookings de prueba...')
|
||||
|
||||
const now = new Date()
|
||||
const bookings = []
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const startTime = new Date(now.getTime() + (i + 1) * 24 * 60 * 60 * 1000)
|
||||
const endTime = new Date(startTime.getTime() + 60 * 60 * 1000)
|
||||
|
||||
const { data, error } = await supabase.from('bookings').insert({
|
||||
customer_id: customers[i % customers.length].id,
|
||||
staff_id: staff.filter(s => s.role === 'artist')[i % staff.filter(s => s.role === 'artist').length].id,
|
||||
location_id: locations[0].id,
|
||||
resource_id: resources[0].id,
|
||||
service_id: services[i % services.length].id,
|
||||
start_time_utc: startTime.toISOString(),
|
||||
end_time_utc: endTime.toISOString(),
|
||||
status: 'confirmed',
|
||||
deposit_amount: 200.00,
|
||||
total_amount: services[i % services.length].base_price,
|
||||
is_paid: true,
|
||||
payment_reference: `pay_${Math.random().toString(36).substring(7)}`,
|
||||
}).select()
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al crear bookings:', error)
|
||||
continue
|
||||
}
|
||||
|
||||
bookings.push(...data)
|
||||
}
|
||||
|
||||
console.log(`✅ ${bookings.length} bookings creados`)
|
||||
return bookings
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const locations = await seedLocations()
|
||||
if (locations.length === 0) throw new Error('No se crearon locations')
|
||||
|
||||
const resources = await seedResources(locations)
|
||||
const staff = await seedStaff(locations)
|
||||
if (staff.length === 0) throw new Error('No se creó staff')
|
||||
|
||||
const services = await seedServices()
|
||||
if (services.length === 0) throw new Error('No se crearon services')
|
||||
|
||||
const customers = await seedCustomers()
|
||||
if (customers.length === 0) throw new Error('No se crearon customers')
|
||||
|
||||
const invitations = await seedInvitations(customers)
|
||||
const bookings = await seedBookings(customers, staff, resources, services, locations)
|
||||
|
||||
console.log()
|
||||
console.log('==========================================')
|
||||
console.log('✅ SEED DE DATOS COMPLETADO')
|
||||
console.log('==========================================')
|
||||
console.log()
|
||||
console.log('📊 Resumen:')
|
||||
console.log(` Locations: ${locations.length}`)
|
||||
console.log(` Resources: ${resources.length}`)
|
||||
console.log(` Staff: ${staff.length}`)
|
||||
console.log(` Services: ${services.length}`)
|
||||
console.log(` Customers: ${customers.length}`)
|
||||
console.log(` Invitations: ${invitations.length}`)
|
||||
console.log(` Bookings: ${bookings.length}`)
|
||||
console.log()
|
||||
console.log('🎉 La base de datos está lista para desarrollo')
|
||||
console.log()
|
||||
console.log('📝 Próximos pasos:')
|
||||
console.log(' 1. Configurar Auth en Supabase Dashboard')
|
||||
console.log(' 2. Probar la API de bookings')
|
||||
console.log(' 3. Implementar endpoints faltantes')
|
||||
} catch (error) {
|
||||
console.error('❌ Error inesperado:', error)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -1,189 +0,0 @@
|
||||
-- ============================================
|
||||
-- SEED DE DATOS - SALONOS
|
||||
-- Ejecutar en Supabase SQL Editor después de las migraciones
|
||||
-- ============================================
|
||||
|
||||
-- 1. Crear Locations
|
||||
INSERT INTO locations (name, timezone, address, phone, is_active)
|
||||
VALUES
|
||||
('Salón Principal - Centro', 'America/Mexico_City', 'Av. Reforma 222, Centro Histórico, Ciudad de México', '+52 55 1234 5678', true),
|
||||
('Salón Norte - Polanco', 'America/Mexico_City', 'Av. Masaryk 123, Polanco, Ciudad de México', '+52 55 2345 6789', true),
|
||||
('Salón Sur - Coyoacán', 'America/Mexico_City', 'Calle Hidalgo 456, Coyoacán, Ciudad de México', '+52 55 3456 7890', true);
|
||||
|
||||
-- 2. Crear Resources
|
||||
INSERT INTO resources (location_id, name, type, capacity, is_active)
|
||||
SELECT
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
'Estación ' || generate_series(1, 3)::TEXT,
|
||||
'station',
|
||||
1,
|
||||
true
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM locations WHERE name = 'Salón Norte - Polanco' LIMIT 1),
|
||||
'Estación ' || generate_series(1, 2)::TEXT,
|
||||
'station',
|
||||
1,
|
||||
true
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM locations WHERE name = 'Salón Sur - Coyoacán' LIMIT 1),
|
||||
'Estación 1',
|
||||
'station',
|
||||
1,
|
||||
true;
|
||||
|
||||
-- 3. Crear Staff
|
||||
INSERT INTO staff (user_id, location_id, role, display_name, phone, is_active)
|
||||
VALUES
|
||||
-- Admin Principal
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'admin', 'Admin Principal', '+52 55 1111 2222', true),
|
||||
-- Managers
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'manager', 'Manager Centro', '+52 55 2222 3333', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Norte - Polanco' LIMIT 1), 'manager', 'Manager Polanco', '+52 55 6666 7777', true),
|
||||
-- Staff
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'staff', 'Staff Coordinadora', '+52 55 3333 4444', true),
|
||||
-- Artists
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'artist', 'Artist María García', '+52 55 4444 5555', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'artist', 'Artist Ana Rodríguez', '+52 55 5555 6666', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Norte - Polanco' LIMIT 1), 'artist', 'Artist Carla López', '+52 55 7777 8888', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Sur - Coyoacán' LIMIT 1), 'artist', 'Artist Laura Martínez', '+52 55 8888 9999', true);
|
||||
|
||||
-- 4. Crear Services
|
||||
INSERT INTO services (name, description, duration_minutes, base_price, requires_dual_artist, premium_fee_enabled, is_active)
|
||||
VALUES
|
||||
('Corte y Estilizado', 'Corte de cabello profesional con lavado y estilizado', 60, 500.00, false, false, true),
|
||||
('Color Completo', 'Tinte completo con protección capilar', 120, 1200.00, false, true, true),
|
||||
('Balayage Premium', 'Técnica de balayage con productos premium', 180, 2000.00, true, true, true),
|
||||
('Tratamiento Kératina', 'Tratamiento de kératina para cabello dañado', 90, 1500.00, false, false, true),
|
||||
('Peinado Evento', 'Peinado para eventos especiales', 45, 800.00, false, true, true),
|
||||
('Servicio Express (Dual Artist)', 'Servicio rápido con dos artists simultáneas', 30, 600.00, true, true, true);
|
||||
|
||||
-- 5. Crear Customers
|
||||
INSERT INTO customers (user_id, first_name, last_name, email, phone, tier, notes, total_spent, total_visits, last_visit_date, is_active)
|
||||
VALUES
|
||||
(uuid_generate_v4(), 'Sofía', 'Ramírez', 'sofia.ramirez@example.com', '+52 55 1111 1111', 'gold', 'Cliente VIP. Prefiere Artists María y Ana.', 15000.00, 25, '2025-12-20', true),
|
||||
(uuid_generate_v4(), 'Valentina', 'Hernández', 'valentina.hernandez@example.com', '+52 55 2222 2222', 'gold', 'Cliente regular. Prefiere horarios de la mañana.', 8500.00, 15, '2025-12-15', true),
|
||||
(uuid_generate_v4(), 'Camila', 'López', 'camila.lopez@example.com', '+52 55 3333 3333', 'free', 'Nueva cliente. Referida por Valentina.', 500.00, 1, '2025-12-10', true),
|
||||
(uuid_generate_v4(), 'Isabella', 'García', 'isabella.garcia@example.com', '+52 55 4444 4444', 'gold', 'Cliente VIP. Requiere servicio de Balayage.', 22000.00, 30, '2025-12-18', true);
|
||||
|
||||
-- 6. Crear Invitaciones (para clientes Gold)
|
||||
-- Resetear invitaciones para clientes Gold de la semana actual
|
||||
SELECT reset_weekly_invitations_for_customer((SELECT id FROM customers WHERE email = 'sofia.ramirez@example.com' LIMIT 1));
|
||||
SELECT reset_weekly_invitations_for_customer((SELECT id FROM customers WHERE email = 'valentina.hernandez@example.com' LIMIT 1));
|
||||
SELECT reset_weekly_invitations_for_customer((SELECT id FROM customers WHERE email = 'isabella.garcia@example.com' LIMIT 1));
|
||||
|
||||
-- 7. Crear Bookings de Prueba
|
||||
INSERT INTO bookings (
|
||||
customer_id,
|
||||
staff_id,
|
||||
location_id,
|
||||
resource_id,
|
||||
service_id,
|
||||
start_time_utc,
|
||||
end_time_utc,
|
||||
status,
|
||||
deposit_amount,
|
||||
total_amount,
|
||||
is_paid,
|
||||
payment_reference,
|
||||
notes
|
||||
)
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'sofia.ramirez@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist María García' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Balayage Premium' LIMIT 1),
|
||||
NOW() + INTERVAL '1 day',
|
||||
NOW() + INTERVAL '4 hours',
|
||||
'confirmed',
|
||||
200.00,
|
||||
2000.00,
|
||||
true,
|
||||
'pay_test_001',
|
||||
'Balayage Premium para Sofía'
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'valentina.hernandez@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist Ana Rodríguez' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Color Completo' LIMIT 1),
|
||||
NOW() + INTERVAL '2 days',
|
||||
NOW() + INTERVAL '4 hours',
|
||||
'confirmed',
|
||||
200.00,
|
||||
1200.00,
|
||||
true,
|
||||
'pay_test_002',
|
||||
'Color Completo para Valentina'
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'camila.lopez@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist María García' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Corte y Estilizado' LIMIT 1),
|
||||
NOW() + INTERVAL '3 days',
|
||||
NOW() + INTERVAL '1 hour',
|
||||
'confirmed',
|
||||
50.00,
|
||||
500.00,
|
||||
true,
|
||||
'pay_test_003',
|
||||
'Primer corte para Camila'
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'isabella.garcia@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist María García' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Servicio Express (Dual Artist)' LIMIT 1),
|
||||
NOW() + INTERVAL '4 days',
|
||||
NOW() + INTERVAL '30 minutes',
|
||||
'confirmed',
|
||||
200.00,
|
||||
600.00,
|
||||
true,
|
||||
'pay_test_004',
|
||||
'Servicio Express Dual Artist - Necesita secondary_artist'
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'sofia.ramirez@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist Ana Rodríguez' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) OFFSET 1 LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Peinado Evento' LIMIT 1),
|
||||
NOW() + INTERVAL '5 days',
|
||||
NOW() + INTERVAL '45 minutes',
|
||||
'pending',
|
||||
200.00,
|
||||
800.00,
|
||||
false,
|
||||
NULL,
|
||||
'Peinado para evento especial';
|
||||
|
||||
-- 8. Actualizar booking con secondary_artist (prueba de validación)
|
||||
UPDATE bookings
|
||||
SET secondary_artist_id = (SELECT id FROM staff WHERE display_name = 'Artist Carla López' LIMIT 1)
|
||||
WHERE payment_reference = 'pay_test_004';
|
||||
|
||||
-- 9. Resumen de datos creados
|
||||
DO $$
|
||||
BEGIN
|
||||
RAISE NOTICE '==========================================';
|
||||
RAISE NOTICE 'SALONOS - SEED DE DATOS COMPLETADO';
|
||||
RAISE NOTICE '==========================================';
|
||||
RAISE NOTICE 'Locations: %', (SELECT COUNT(*) FROM locations);
|
||||
RAISE NOTICE 'Resources: %', (SELECT COUNT(*) FROM resources);
|
||||
RAISE NOTICE 'Staff: %', (SELECT COUNT(*) FROM staff);
|
||||
RAISE NOTICE 'Services: %', (SELECT COUNT(*) FROM services);
|
||||
RAISE NOTICE 'Customers: %', (SELECT COUNT(*) FROM customers);
|
||||
RAISE NOTICE 'Invitations: %', (SELECT COUNT(*) FROM invitations WHERE status = 'pending');
|
||||
RAISE NOTICE 'Bookings: %', (SELECT COUNT(*) FROM bookings);
|
||||
RAISE NOTICE '==========================================';
|
||||
RAISE NOTICE '✅ Base de datos lista para desarrollo';
|
||||
RAISE NOTICE '==========================================';
|
||||
END
|
||||
$$;
|
||||
@@ -1,276 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script simple para seed de datos de SalonOS
|
||||
# Ejecutar con: ./scripts/simple-seed.sh
|
||||
# Requiere: psql instalado y variables de entorno en .env.local
|
||||
|
||||
# Cargar variables de entorno
|
||||
set -a
|
||||
source .env.local
|
||||
set +a
|
||||
|
||||
if [ -z "$NEXT_PUBLIC_SUPABASE_URL" ] || [ -z "$SUPABASE_SERVICE_ROLE_KEY" ]; then
|
||||
echo "❌ ERROR: Faltan variables de entorno"
|
||||
echo "Asegúrate de tener NEXT_PUBLIC_SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY en .env.local"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Configurar DATABASE_URL
|
||||
DB_HOST="${NEXT_PUBLIC_SUPABASE_URL#https://}"
|
||||
DB_URL="postgresql://postgres:${SUPABASE_SERVICE_ROLE_KEY}@${DB_HOST}:5432/postgres"
|
||||
|
||||
echo "=========================================="
|
||||
echo "SALONOS - SEED DE DATOS"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# 1. Crear Locations
|
||||
echo "📍 Creando locations..."
|
||||
psql "$DB_URL" -c "
|
||||
INSERT INTO locations (name, timezone, address, phone, is_active)
|
||||
VALUES
|
||||
('Salón Principal - Centro', 'America/Mexico_City', 'Av. Reforma 222, Centro Histórico, Ciudad de México', '+52 55 1234 5678', true),
|
||||
('Salón Norte - Polanco', 'America/Mexico_City', 'Av. Masaryk 123, Polanco, Ciudad de México', '+52 55 2345 6789', true),
|
||||
('Salón Sur - Coyoacán', 'America/Mexico_City', 'Calle Hidalgo 456, Coyoacán, Ciudad de México', '+52 55 3456 7890', true)
|
||||
ON CONFLICT DO NOTHING;
|
||||
" 2>&1 | grep -v "NOTICE"
|
||||
|
||||
LOCATIONS_COUNT=$(psql "$DB_URL" -t -c "SELECT COUNT(*) FROM locations;")
|
||||
echo "✅ Locations: $LOCATIONS_COUNT/3"
|
||||
|
||||
# 2. Crear Resources
|
||||
echo ""
|
||||
echo "🪑 Creando resources..."
|
||||
psql "$DB_URL" -c "
|
||||
INSERT INTO resources (location_id, name, type, capacity, is_active)
|
||||
SELECT
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
'Estación ' || generate_series(1, 3)::TEXT,
|
||||
'station',
|
||||
1,
|
||||
true
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM locations WHERE name = 'Salón Norte - Polanco' LIMIT 1),
|
||||
'Estación ' || generate_series(1, 2)::TEXT,
|
||||
'station',
|
||||
1,
|
||||
true
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM locations WHERE name = 'Salón Sur - Coyoacán' LIMIT 1),
|
||||
'Estación 1',
|
||||
'station',
|
||||
1,
|
||||
true
|
||||
ON CONFLICT DO NOTHING;
|
||||
" 2>&1 | grep -v "NOTICE"
|
||||
|
||||
RESOURCES_COUNT=$(psql "$DB_URL" -t -c "SELECT COUNT(*) FROM resources;")
|
||||
echo "✅ Resources: $RESOURCES_COUNT/6"
|
||||
|
||||
# 3. Crear Staff
|
||||
echo ""
|
||||
echo "👥 Creando staff..."
|
||||
psql "$DB_URL" -c "
|
||||
INSERT INTO staff (user_id, location_id, role, display_name, phone, is_active)
|
||||
VALUES
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'admin', 'Admin Principal', '+52 55 1111 2222', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'manager', 'Manager Centro', '+52 55 2222 3333', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Norte - Polanco' LIMIT 1), 'manager', 'Manager Polanco', '+52 55 6666 7777', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'staff', 'Staff Coordinadora', '+52 55 3333 4444', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'artist', 'Artist María García', '+52 55 4444 5555', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1), 'artist', 'Artist Ana Rodríguez', '+52 55 5555 6666', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Norte - Polanco' LIMIT 1), 'artist', 'Artist Carla López', '+52 55 7777 8888', true),
|
||||
(uuid_generate_v4(), (SELECT id FROM locations WHERE name = 'Salón Sur - Coyoacán' LIMIT 1), 'artist', 'Artist Laura Martínez', '+52 55 8888 9999', true)
|
||||
ON CONFLICT DO NOTHING;
|
||||
" 2>&1 | grep -v "NOTICE"
|
||||
|
||||
STAFF_COUNT=$(psql "$DB_URL" -t -c "SELECT COUNT(*) FROM staff;")
|
||||
echo "✅ Staff: $STAFF_COUNT/8"
|
||||
|
||||
# 4. Crear Services
|
||||
echo ""
|
||||
echo "💇 Creando services..."
|
||||
psql "$DB_URL" -c "
|
||||
INSERT INTO services (name, description, duration_minutes, base_price, requires_dual_artist, premium_fee_enabled, is_active)
|
||||
VALUES
|
||||
('Corte y Estilizado', 'Corte de cabello profesional con lavado y estilizado', 60, 500.00, false, false, true),
|
||||
('Color Completo', 'Tinte completo con protección capilar', 120, 1200.00, false, true, true),
|
||||
('Balayage Premium', 'Técnica de balayage con productos premium', 180, 2000.00, true, true, true),
|
||||
('Tratamiento Kératina', 'Tratamiento de kératina para cabello dañado', 90, 1500.00, false, false, true),
|
||||
('Peinado Evento', 'Peinado para eventos especiales', 45, 800.00, false, true, true),
|
||||
('Servicio Express (Dual Artist)', 'Servicio rápido con dos artists simultáneas', 30, 600.00, true, true, true)
|
||||
ON CONFLICT DO NOTHING;
|
||||
" 2>&1 | grep -v "NOTICE"
|
||||
|
||||
SERVICES_COUNT=$(psql "$DB_URL" -t -c "SELECT COUNT(*) FROM services;")
|
||||
echo "✅ Services: $SERVICES_COUNT/6"
|
||||
|
||||
# 5. Crear Customers
|
||||
echo ""
|
||||
echo "👩 Creando customers..."
|
||||
psql "$DB_URL" -c "
|
||||
INSERT INTO customers (user_id, first_name, last_name, email, phone, tier, notes, total_spent, total_visits, last_visit_date, is_active)
|
||||
VALUES
|
||||
(uuid_generate_v4(), 'Sofía', 'Ramírez', 'sofia.ramirez@example.com', '+52 55 1111 1111', 'gold', 'Cliente VIP. Prefiere Artists María y Ana.', 15000.00, 25, '2025-12-20', true),
|
||||
(uuid_generate_v4(), 'Valentina', 'Hernández', 'valentina.hernandez@example.com', '+52 55 2222 2222', 'gold', 'Cliente regular. Prefiere horarios de la mañana.', 8500.00, 15, '2025-12-15', true),
|
||||
(uuid_generate_v4(), 'Camila', 'López', 'camila.lopez@example.com', '+52 55 3333 3333', 'free', 'Nueva cliente. Referida por Valentina.', 500.00, 1, '2025-12-10', true),
|
||||
(uuid_generate_v4(), 'Isabella', 'García', 'isabella.garcia@example.com', '+52 55 4444 4444', 'gold', 'Cliente VIP. Requiere servicio de Balayage.', 22000.00, 30, '2025-12-18', true)
|
||||
ON CONFLICT (email) DO NOTHING;
|
||||
" 2>&1 | grep -v "NOTICE"
|
||||
|
||||
CUSTOMERS_COUNT=$(psql "$DB_URL" -t -c "SELECT COUNT(*) FROM customers;")
|
||||
echo "✅ Customers: $CUSTOMERS_COUNT/4"
|
||||
|
||||
# 6. Crear Invitaciones (para clientes Gold)
|
||||
echo ""
|
||||
echo "💌 Creando invitations..."
|
||||
psql "$DB_URL" -c "
|
||||
SELECT reset_weekly_invitations_for_customer((SELECT id FROM customers WHERE email = 'sofia.ramirez@example.com' LIMIT 1));
|
||||
SELECT reset_weekly_invitations_for_customer((SELECT id FROM customers WHERE email = 'valentina.hernandez@example.com' LIMIT 1));
|
||||
SELECT reset_weekly_invitations_for_customer((SELECT id FROM customers WHERE email = 'isabella.garcia@example.com' LIMIT 1));
|
||||
" 2>&1 | grep -v "NOTICE"
|
||||
|
||||
INVITATIONS_COUNT=$(psql "$DB_URL" -t -c "SELECT COUNT(*) FROM invitations WHERE status = 'pending';")
|
||||
echo "✅ Invitaciones: $INVITATIONS_COUNT/15"
|
||||
|
||||
# 7. Crear Bookings de Prueba
|
||||
echo ""
|
||||
echo "📅 Creando bookings..."
|
||||
psql "$DB_URL" -c "
|
||||
INSERT INTO bookings (
|
||||
customer_id,
|
||||
staff_id,
|
||||
location_id,
|
||||
resource_id,
|
||||
service_id,
|
||||
start_time_utc,
|
||||
end_time_utc,
|
||||
status,
|
||||
deposit_amount,
|
||||
total_amount,
|
||||
is_paid,
|
||||
payment_reference,
|
||||
notes
|
||||
)
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'sofia.ramirez@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist María García' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Balayage Premium' LIMIT 1),
|
||||
NOW() + INTERVAL '1 day',
|
||||
NOW() + INTERVAL '4 hours',
|
||||
'confirmed',
|
||||
200.00,
|
||||
2000.00,
|
||||
true,
|
||||
'pay_test_001',
|
||||
'Balayage Premium para Sofía'
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'valentina.hernandez@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist Ana Rodríguez' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Color Completo' LIMIT 1),
|
||||
NOW() + INTERVAL '2 days',
|
||||
NOW() + INTERVAL '4 hours',
|
||||
'confirmed',
|
||||
200.00,
|
||||
1200.00,
|
||||
true,
|
||||
'pay_test_002',
|
||||
'Color Completo para Valentina'
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'camila.lopez@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist María García' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Corte y Estilizado' LIMIT 1),
|
||||
NOW() + INTERVAL '3 days',
|
||||
NOW() + INTERVAL '1 hour',
|
||||
'confirmed',
|
||||
50.00,
|
||||
500.00,
|
||||
true,
|
||||
'pay_test_003',
|
||||
'Primer corte para Camila'
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'isabella.garcia@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist María García' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Servicio Express (Dual Artist)' LIMIT 1),
|
||||
NOW() + INTERVAL '4 days',
|
||||
NOW() + INTERVAL '30 minutes',
|
||||
'confirmed',
|
||||
200.00,
|
||||
600.00,
|
||||
true,
|
||||
'pay_test_004',
|
||||
'Servicio Express Dual Artist - Necesita secondary_artist'
|
||||
UNION ALL
|
||||
SELECT
|
||||
(SELECT id FROM customers WHERE email = 'sofia.ramirez@example.com' LIMIT 1),
|
||||
(SELECT id FROM staff WHERE display_name = 'Artist Ana Rodríguez' LIMIT 1),
|
||||
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1),
|
||||
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro' LIMIT 1) OFFSET 1 LIMIT 1),
|
||||
(SELECT id FROM services WHERE name = 'Peinado Evento' LIMIT 1),
|
||||
NOW() + INTERVAL '5 days',
|
||||
NOW() + INTERVAL '45 minutes',
|
||||
'pending',
|
||||
200.00,
|
||||
800.00,
|
||||
false,
|
||||
NULL,
|
||||
'Peinado para evento especial'
|
||||
ON CONFLICT DO NOTHING;
|
||||
" 2>&1 | grep -v "NOTICE"
|
||||
|
||||
BOOKINGS_COUNT=$(psql "$DB_URL" -t -c "SELECT COUNT(*) FROM bookings;")
|
||||
echo "✅ Bookings: $BOOKINGS_COUNT/5"
|
||||
|
||||
# 8. Actualizar booking con secondary_artist
|
||||
echo ""
|
||||
echo "🔄 Actualizando booking con secondary_artist..."
|
||||
psql "$DB_URL" -c "
|
||||
UPDATE bookings
|
||||
SET secondary_artist_id = (SELECT id FROM staff WHERE display_name = 'Artist Carla López' LIMIT 1)
|
||||
WHERE payment_reference = 'pay_test_004';
|
||||
" 2>&1 | grep -v "NOTICE"
|
||||
|
||||
SECONDARY_ARTIST_COUNT=$(psql "$DB_URL" -t -c "SELECT COUNT(*) FROM bookings WHERE secondary_artist_id IS NOT NULL;")
|
||||
echo "✅ Bookings con secondary_artist: $SECONDARY_ARTIST_COUNT/1"
|
||||
|
||||
# Resumen
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "RESUMEN"
|
||||
echo "=========================================="
|
||||
echo "Locations: $LOCATIONS_COUNT/3"
|
||||
echo "Resources: $RESOURCES_COUNT/6"
|
||||
echo "Staff: $STAFF_COUNT/8"
|
||||
echo "Services: $SERVICES_COUNT/6"
|
||||
echo "Customers: $CUSTOMERS_COUNT/4"
|
||||
echo "Invitations: $INVITATIONS_COUNT/15"
|
||||
echo "Bookings: $BOOKINGS_COUNT/5"
|
||||
echo "Sec. Artist: $SECONDARY_ARTIST_COUNT/1"
|
||||
echo "=========================================="
|
||||
|
||||
if [ "$LOCATIONS_COUNT" -eq 3 ] && [ "$RESOURCES_COUNT" -eq 6 ] && [ "$STAFF_COUNT" -eq 8 ] && [ "$SERVICES_COUNT" -eq 6 ] && [ "$CUSTOMERS_COUNT" -eq 4 ] && [ "$INVITATIONS_COUNT" -eq 15 ] && [ "$BOOKINGS_COUNT" -eq 5 ]; then
|
||||
echo ""
|
||||
echo "🎉 SEED DE DATOS COMPLETADO EXITOSAMENTE"
|
||||
echo ""
|
||||
echo "Próximos pasos:"
|
||||
echo "1. Configurar Auth en Supabase Dashboard"
|
||||
echo "2. Crear usuarios de staff y customers"
|
||||
echo "3. Actualizar tablas staff y customers con user_ids"
|
||||
else
|
||||
echo ""
|
||||
echo "⚠️ ALGUNOS DATOS NO SE CREARON CORRECTAMENTE"
|
||||
echo "Por favor, verifica los errores arriba."
|
||||
fi
|
||||
@@ -1,124 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script simple para verificar migraciones de SalonOS
|
||||
# Ejecutar con: ./scripts/simple-verify.sh
|
||||
# Requiere: psql instalado y variables de entorno en .env.local
|
||||
|
||||
# Cargar variables de entorno
|
||||
set -a
|
||||
source .env.local
|
||||
set +a
|
||||
|
||||
if [ -z "$NEXT_PUBLIC_SUPABASE_URL" ] || [ -z "$SUPABASE_SERVICE_ROLE_KEY" ]; then
|
||||
echo "❌ ERROR: Faltan variables de entorno"
|
||||
echo "Asegúrate de tener NEXT_PUBLIC_SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY en .env.local"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Configurar DATABASE_URL
|
||||
DB_HOST="${NEXT_PUBLIC_SUPABASE_URL#https://}"
|
||||
DB_URL="postgresql://postgres:${SUPABASE_SERVICE_ROLE_KEY}@${DB_HOST}:5432/postgres"
|
||||
|
||||
echo "=========================================="
|
||||
echo "SALONOS - VERIFICACIÓN DE MIGRACIONES"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# 1. Verificar Tablas
|
||||
echo "📊 Verificando tablas..."
|
||||
TABLE_COUNT=$(psql "$DB_URL" -t -c "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name IN ('locations', 'resources', 'staff', 'services', 'customers', 'invitations', 'bookings', 'audit_logs');
|
||||
")
|
||||
|
||||
echo "✅ Tablas: ${TABLE_COUNT}/8"
|
||||
if [ "$TABLE_COUNT" -lt 8 ]; then
|
||||
echo "⚠️ Faltan tablas por crear"
|
||||
fi
|
||||
|
||||
# 2. Verificar Funciones
|
||||
echo ""
|
||||
echo "📊 Verificando funciones..."
|
||||
FUNC_COUNT=$(psql "$DB_URL" -t -c "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.routines
|
||||
WHERE routine_schema = 'public';
|
||||
")
|
||||
|
||||
echo "✅ Funciones: ${FUNC_COUNT}/14"
|
||||
if [ "$FUNC_COUNT" -lt 14 ]; then
|
||||
echo "⚠️ Faltan funciones por crear"
|
||||
fi
|
||||
|
||||
# 3. Verificar Triggers
|
||||
echo ""
|
||||
echo "📊 Verificando triggers..."
|
||||
TRIGGER_COUNT=$(psql "$DB_URL" -t -c "
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.triggers
|
||||
WHERE trigger_schema = 'public';
|
||||
")
|
||||
|
||||
echo "✅ Triggers: ${TRIGGER_COUNT}/17+"
|
||||
if [ "$TRIGGER_COUNT" -lt 17 ]; then
|
||||
echo "⚠️ Faltan triggers por crear"
|
||||
fi
|
||||
|
||||
# 4. Verificar Políticas RLS
|
||||
echo ""
|
||||
echo "📊 Verificando políticas RLS..."
|
||||
POLICY_COUNT=$(psql "$DB_URL" -t -c "
|
||||
SELECT COUNT(*)
|
||||
FROM pg_policies
|
||||
WHERE schemaname = 'public';
|
||||
")
|
||||
|
||||
echo "✅ Políticas RLS: ${POLICY_COUNT}/20+"
|
||||
if [ "$POLICY_COUNT" -lt 20 ]; then
|
||||
echo "⚠️ Faltan políticas RLS por crear"
|
||||
fi
|
||||
|
||||
# 5. Probar Short ID
|
||||
echo ""
|
||||
echo "📊 Probando generación de Short ID..."
|
||||
SHORT_ID=$(psql "$DB_URL" -t -c "SELECT generate_short_id();")
|
||||
|
||||
echo "✅ Short ID: ${SHORT_ID} (${#SHORT_ID} caracteres)"
|
||||
|
||||
# 6. Probar Código de Invitación
|
||||
echo ""
|
||||
echo "📊 Probando generación de código de invitación..."
|
||||
INV_CODE=$(psql "$DB_URL" -t -c "SELECT generate_invitation_code();")
|
||||
|
||||
echo "✅ Código de invitación: ${INV_CODE} (${#INV_CODE} caracteres)"
|
||||
|
||||
# Resumen
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "RESUMEN"
|
||||
echo "=========================================="
|
||||
if [ "$TABLE_COUNT" -ge 8 ] && [ "$FUNC_COUNT" -ge 14 ] && [ "$TRIGGER_COUNT" -ge 17 ] && [ "$POLICY_COUNT" -ge 20 ]; then
|
||||
echo "Tablas: ✅ ${TABLE_COUNT}/8"
|
||||
echo "Funciones: ✅ ${FUNC_COUNT}/14"
|
||||
echo "Triggers: ✅ ${TRIGGER_COUNT}/17+"
|
||||
echo "Políticas RLS: ✅ ${POLICY_COUNT}/20+"
|
||||
echo "Short ID: ✅ Generable"
|
||||
echo "Cód. Invit.: ✅ Generable"
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "🎉 TODAS LAS MIGRACIONES ESTÁN CORRECTAS"
|
||||
echo "Puedes continuar con el seed de datos."
|
||||
echo "=========================================="
|
||||
else
|
||||
echo "Tablas: ❌ ${TABLE_COUNT}/8"
|
||||
echo "Funciones: ❌ ${FUNC_COUNT}/14"
|
||||
echo "Triggers: ❌ ${TRIGGER_COUNT}/17+"
|
||||
echo "Políticas RLS: ❌ ${POLICY_COUNT}/20+"
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "⚠️ ALGUNAS MIGRACIONES FALTAN"
|
||||
echo "Por favor, verifica los errores arriba."
|
||||
echo "=========================================="
|
||||
fi
|
||||
@@ -1,225 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script de verificación de migraciones - SalonOS
|
||||
* Verifica que todas las tablas, funciones, triggers y políticas RLS estén creados
|
||||
*/
|
||||
|
||||
const { createClient } = require('@supabase/supabase-js')
|
||||
|
||||
// Cargar variables de entorno
|
||||
require('dotenv').config({ path: '.env.local' })
|
||||
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
|
||||
const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY
|
||||
|
||||
if (!supabaseUrl || !supabaseServiceKey) {
|
||||
console.error('❌ ERROR: Faltan variables de entorno')
|
||||
console.error('Asegúrate de tener NEXT_PUBLIC_SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY en .env.local')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const supabase = createClient(supabaseUrl, supabaseServiceKey)
|
||||
|
||||
console.log('==========================================')
|
||||
console('SALONOS - VERIFICACIÓN DE MIGRACIONES')
|
||||
console.log('==========================================')
|
||||
console.log()
|
||||
|
||||
const expectedTables = [
|
||||
'locations',
|
||||
'resources',
|
||||
'staff',
|
||||
'services',
|
||||
'customers',
|
||||
'invitations',
|
||||
'bookings',
|
||||
'audit_logs',
|
||||
]
|
||||
|
||||
const expectedFunctions = [
|
||||
'generate_short_id',
|
||||
'generate_invitation_code',
|
||||
'reset_weekly_invitations_for_customer',
|
||||
'reset_all_weekly_invitations',
|
||||
'log_audit',
|
||||
'get_current_user_role',
|
||||
'is_staff_or_higher',
|
||||
'is_artist',
|
||||
'is_customer',
|
||||
'is_admin',
|
||||
'update_updated_at',
|
||||
'generate_booking_short_id',
|
||||
'get_week_start',
|
||||
]
|
||||
|
||||
const expectedEnums = [
|
||||
'user_role',
|
||||
'customer_tier',
|
||||
'booking_status',
|
||||
'invitation_status',
|
||||
'resource_type',
|
||||
'audit_action',
|
||||
]
|
||||
|
||||
async function verifyTables() {
|
||||
console.log('📊 Verificando tablas...')
|
||||
|
||||
const { data: tables, error } = await supabase.rpc('verify_tables_exist', {
|
||||
table_names: expectedTables,
|
||||
})
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al verificar tablas:', error)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log(`✅ Tablas creadas: ${tables.length}/${expectedTables.length}`)
|
||||
|
||||
if (tables.length !== expectedTables.length) {
|
||||
console.log('⚠️ Tablas faltantes:')
|
||||
expectedTables.forEach(table => {
|
||||
if (!tables.includes(table)) {
|
||||
console.log(` - ${table}`)
|
||||
}
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function verifyFunctions() {
|
||||
console.log('📊 Verificando funciones...')
|
||||
|
||||
const { data: functions, error } = await supabase.rpc('verify_functions_exist', {
|
||||
function_names: expectedFunctions,
|
||||
})
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al verificar funciones:', error)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log(`✅ Funciones creadas: ${functions.length}/${expectedFunctions.length}`)
|
||||
|
||||
if (functions.length !== expectedFunctions.length) {
|
||||
console.log('⚠️ Funciones faltantes:')
|
||||
expectedFunctions.forEach(func => {
|
||||
if (!functions.includes(func)) {
|
||||
console.log(` - ${func}`)
|
||||
}
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function verifyEnums() {
|
||||
console.log('📊 Verificando tipos ENUM...')
|
||||
|
||||
const { data: enums, error } = await supabase.rpc('verify_enums_exist', {
|
||||
enum_names: expectedEnums,
|
||||
})
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al verificar tipos ENUM:', error)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log(`✅ Tipos ENUM creados: ${enums.length}/${expectedEnums.length}`)
|
||||
|
||||
if (enums.length !== expectedEnums.length) {
|
||||
console.log('⚠️ Tipos ENUM faltantes:')
|
||||
expectedEnums.forEach(enumName => {
|
||||
if (!enums.includes(enumName)) {
|
||||
console.log(` - ${enumName}`)
|
||||
}
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function testShortID() {
|
||||
console.log('🧪 Probando generación de Short ID...')
|
||||
|
||||
const { data, error } = await supabase.rpc('generate_short_id')
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al generar Short ID:', error)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log(`✅ Short ID generado: ${data}`)
|
||||
console.log(` Longitud: ${data.length} caracteres`)
|
||||
|
||||
if (data.length !== 6) {
|
||||
console.error('❌ ERROR: El Short ID debe tener 6 caracteres')
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function testInvitationCode() {
|
||||
console.log('🧪 Probando generación de código de invitación...')
|
||||
|
||||
const { data, error } = await supabase.rpc('generate_invitation_code')
|
||||
|
||||
if (error) {
|
||||
console.error('❌ Error al generar código de invitación:', error)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log(`✅ Código de invitación generado: ${data}`)
|
||||
console.log(` Longitud: ${data.length} caracteres`)
|
||||
|
||||
if (data.length !== 10) {
|
||||
console.error('❌ ERROR: El código de invitación debe tener 10 caracteres')
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const tablesOk = await verifyTables()
|
||||
const functionsOk = await verifyFunctions()
|
||||
const enumsOk = await verifyEnums()
|
||||
const shortIdOk = await testShortID()
|
||||
const invitationCodeOk = await testInvitationCode()
|
||||
|
||||
console.log()
|
||||
console.log('==========================================')
|
||||
|
||||
if (tablesOk && functionsOk && enumsOk && shortIdOk && invitationCodeOk) {
|
||||
console.log('✅ TODAS LAS VERIFICACIONES PASARON')
|
||||
console.log('==========================================')
|
||||
console.log()
|
||||
console.log('🎉 La base de datos está lista para usar')
|
||||
console.log()
|
||||
console.log('📝 Próximos pasos:')
|
||||
console.log(' 1. Configurar Auth en Supabase Dashboard')
|
||||
console.log(' 2. Crear usuarios de prueba con roles específicos')
|
||||
console.log(' 3. Ejecutar seeds de datos de prueba')
|
||||
console.log(' 4. Probar la API de bookings')
|
||||
process.exit(0)
|
||||
} else {
|
||||
console.log('❌ ALGUNAS VERIFICACIONES FALLARON')
|
||||
console.log('==========================================')
|
||||
console.log()
|
||||
console.log('Por favor, revisa los errores arriba y ejecuta nuevamente:')
|
||||
console.log(' npm run db:migrate')
|
||||
process.exit(1)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Error inesperado:', error)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -1,89 +0,0 @@
|
||||
-- ============================================
|
||||
-- VERIFICACIÓN POST-MIGRACIÓN - SALONOS
|
||||
-- Ejecutar en Supabase SQL Editor después de las migraciones
|
||||
-- ============================================
|
||||
|
||||
-- 1. Verificar Tablas Creadas
|
||||
SELECT 'TABLAS' as verification_type, table_name as item
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name IN ('locations', 'resources', 'staff', 'services', 'customers', 'invitations', 'bookings', 'audit_logs')
|
||||
ORDER BY table_name;
|
||||
|
||||
-- 2. Verificar Funciones Creadas
|
||||
SELECT 'FUNCIONES' as verification_type, routine_name as item
|
||||
FROM information_schema.routines
|
||||
WHERE routine_schema = 'public'
|
||||
ORDER BY routine_name;
|
||||
|
||||
-- 3. Verificar Triggers Activos
|
||||
SELECT 'TRIGGERS' as verification_type, trigger_name as item
|
||||
FROM information_schema.triggers
|
||||
WHERE trigger_schema = 'public'
|
||||
ORDER BY event_object_table, trigger_name;
|
||||
|
||||
-- 4. Verificar Políticas RLS
|
||||
SELECT 'POLÍTICAS RLS' as verification_type, policyname as item
|
||||
FROM pg_policies
|
||||
WHERE schemaname = 'public'
|
||||
ORDER BY tablename, policyname;
|
||||
|
||||
-- 5. Verificar Tipos ENUM
|
||||
SELECT 'ENUM TYPES' as verification_type, typname as item
|
||||
FROM pg_type
|
||||
WHERE typtype = 'e'
|
||||
AND typname IN ('user_role', 'customer_tier', 'booking_status', 'invitation_status', 'resource_type', 'audit_action')
|
||||
ORDER BY typname;
|
||||
|
||||
-- 6. Probar Short ID Generation
|
||||
SELECT 'SHORT ID TEST' as verification_type, generate_short_id() as item;
|
||||
|
||||
-- 7. Probar Invitation Code Generation
|
||||
SELECT 'INVITATION CODE TEST' as verification_type, generate_invitation_code() as item;
|
||||
|
||||
-- 8. Verificar Trigger de Validación de Secondary Artist
|
||||
SELECT 'SECONDARY ARTIST TRIGGER' as verification_type, trigger_name as item
|
||||
FROM information_schema.triggers
|
||||
WHERE trigger_name = 'validate_booking_secondary_artist';
|
||||
|
||||
-- 9. Verificar Función de Reset de Invitaciones
|
||||
SELECT 'RESET INVITATIONS FUNCTION' as verification_type, routine_name as item
|
||||
FROM information_schema.routines
|
||||
WHERE routine_name = 'reset_all_weekly_invitations';
|
||||
|
||||
-- 10. Verificar Función de Validación de Secondary Artist
|
||||
SELECT 'VALIDATE SECONDARY ARTIST' as verification_type, routine_name as item
|
||||
FROM information_schema.routines
|
||||
WHERE routine_name = 'validate_secondary_artist_role';
|
||||
|
||||
-- 11. Verificar Week Start Function
|
||||
SELECT 'WEEK START FUNCTION' as verification_type, get_week_start(CURRENT_DATE) as item;
|
||||
|
||||
-- 12. Contar elementos por tipo
|
||||
SELECT
|
||||
'RESUMEN' as verification_type,
|
||||
'Tablas: ' || (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public' AND table_name IN ('locations', 'resources', 'staff', 'services', 'customers', 'invitations', 'bookings', 'audit_logs')) as item
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'RESUMEN' as verification_type,
|
||||
'Funciones: ' || (SELECT COUNT(*) FROM information_schema.routines WHERE routine_schema = 'public') as item
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'RESUMEN' as verification_type,
|
||||
'Triggers: ' || (SELECT COUNT(*) FROM information_schema.triggers WHERE trigger_schema = 'public') as item
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'RESUMEN' as verification_type,
|
||||
'Políticas RLS: ' || (SELECT COUNT(*) FROM pg_policies WHERE schemaname = 'public') as item
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
'RESUMEN' as verification_type,
|
||||
'Tipos ENUM: ' || (SELECT COUNT(*) FROM pg_type WHERE typtype = 'e' AND typname IN ('user_role', 'customer_tier', 'booking_status', 'invitation_status', 'resource_type', 'audit_action')) as item;
|
||||
Reference in New Issue
Block a user