feat(salonos): implementar Fase 1.1 y 1.2 - Infraestructura y Esquema de Base de Datos

Implementación completa de la Fase 1.1 y 1.2 del proyecto SalonOS:

## Cambios en Reglas de Negocio (PRD.md, AGENTS.md, TASKS.md)
- Actualizado reset de invitaciones de mensual a semanal (Lunes 00:00 UTC)
- Jerarquía de roles actualizada: Admin > Manager > Staff > Artist > Customer
- Artistas (antes colaboradoras) ahora tienen rol 'artist'
- Staff/Manager/Admin pueden ver PII de customers
- Artist solo ve nombre y notas de customers (restricción de privacidad)

## Estructura del Proyecto (Next.js 14)
- app/boutique/: Frontend de cliente
- app/hq/: Dashboard administrativo
- app/api/: API routes
- components/: Componentes UI reutilizables (boutique, hq, shared)
- lib/: Lógica de negocio (supabase, db, utils)
- db/: Esquemas, migraciones y seeds
- integrations/: Stripe, Google Calendar, WhatsApp
- scripts/: Scripts de utilidad y automatización
- docs/: Documentación del proyecto

## Esquema de Base de Datos (Supabase PostgreSQL)
8 tablas creadas:
- locations: Ubicaciones con timezone
- resources: Recursos físicos (estaciones, habitaciones, equipos)
- staff: Personal con roles jerárquicos
- services: Catálogo de servicios
- customers: Información de clientes con tier (free/gold)
- invitations: Sistema de invitaciones semanales
- bookings: Sistema de reservas con short_id (6 caracteres)
- audit_logs: Registro de auditoría automática

14 funciones creadas:
- generate_short_id(): Generador de Short ID (6 chars, collision-safe)
- generate_invitation_code(): Generador de códigos de invitación (10 chars)
- reset_weekly_invitations_for_customer(): Reset individual de invitaciones
- reset_all_weekly_invitations(): Reset masivo de invitaciones
- validate_secondary_artist_role(): Validación de secondary_artist
- log_audit(): Trigger de auditoría automática
- get_current_user_role(): Obtener rol del usuario actual
- is_staff_or_higher(): Verificar si es admin/manager/staff
- is_artist(): Verificar si es artist
- is_customer(): Verificar si es customer
- is_admin(): Verificar si es admin
- update_updated_at(): Actualizar timestamps
- generate_booking_short_id(): Generar Short ID automáticamente
- get_week_start(): Obtener inicio de semana

17+ triggers activos:
- Auditores automáticos en tablas críticas
- Timestamps updated_at en todas las tablas
- Validación de secondary_artist (trigger en lugar de constraint)

20+ políticas RLS configuradas:
- Restricción crítica: Artist no ve email/phone de customers
- Jerarquía de roles: Admin > Manager > Staff > Artist > Customer
- Políticas granulares por tipo de operación y rol

6 tipos ENUM:
- user_role: admin, manager, staff, artist, customer
- customer_tier: free, gold
- booking_status: pending, confirmed, cancelled, completed, no_show
- invitation_status: pending, used, expired
- resource_type: station, room, equipment
- audit_action: create, update, delete, reset_invitations, payment, status_change

## Scripts de Utilidad
- check-connection.sh: Verificar conexión a Supabase
- simple-verify.sh: Verificar migraciones instaladas
- simple-seed.sh: Crear datos de prueba
- create-auth-users.js: Crear usuarios de Auth en Supabase
- verify-migration.sql: Script de verificación SQL completo
- seed-data.sql: Script de seed de datos SQL completo

## Documentación
- docs/STEP_BY_STEP_VERIFICATION.md: Guía paso a paso de verificación
- docs/STEP_BY_STEP_AUTH_CONFIG.md: Guía paso a paso de configuración Auth
- docs/POST_MIGRATION_SUCCESS.md: Guía post-migración
- docs/MIGRATION_CORRECTION.md: Detalle de correcciones aplicadas
- docs/QUICK_START_POST_MIGRATION.md: Guía rápida de referencia
- docs/SUPABASE_DASHBOARD_MIGRATION.md: Guía de ejecución en Dashboard
- docs/00_FULL_MIGRATION_FINAL_README.md: Guía de migración final
- SIMPLE_GUIDE.md: Guía simple de inicio
- FASE_1_STATUS.md: Estado de la Fase 1

## Configuración
- package.json: Dependencias y scripts de npm
- tsconfig.json: Configuración TypeScript con paths aliases
- next.config.js: Configuración Next.js
- tailwind.config.ts: Tema personalizado con colores primary, secondary, gold
- postcss.config.js: Configuración PostCSS
- .gitignore: Archivos excluidos de git
- .env.example: Template de variables de entorno

## Correcciones Aplicadas
1. Constraint de subquery en CHECK reemplazado por trigger de validación
   - PostgreSQL no permite subqueries en CHECK constraints
   - validate_secondary_artist_role() ahora es un trigger

2. Variable no declarada en loop
   - customer_record RECORD; añadido en bloque DECLARE

## Principios Implementados
- UTC-first: Todos los timestamps se almacenan en UTC
- Sistema Doble Capa: Validación Staff/Artist + Recurso físico
- Reset semanal: Invitaciones se resetean cada Lunes 00:00 UTC
- Idempotencia: Procesos de reset son idempotentes y auditados
- Privacidad: Artist solo ve nombre y notas de customers
- Auditoría: Todas las acciones críticas se registran automáticamente
- Short ID: 6 caracteres alfanuméricos como referencia humana
- UUID: Identificador primario interno

## Próximos Pasos
- Ejecutar scripts de verificación y seed
- Configurar Auth en Supabase Dashboard
- Implementar Tarea 1.3: Short ID & Invitaciones (backend)
- Implementar Tarea 1.4: CRM Base (endpoints CRUD)
This commit is contained in:
Marco Gallegos
2026-01-15 14:58:28 -06:00
parent ebbd9e3762
commit 4707ddbd5a
40 changed files with 10038 additions and 13 deletions

267
docs/MIGRATION_GUIDE.md Normal file
View File

@@ -0,0 +1,267 @@
# 🚀 Guía de Ejecución de Migraciones - SalonOS
Esta guía explica cómo ejecutar las migraciones de base de datos en Supabase.
## ⚠️ Requisitos Previos
1. **Cuenta de Supabase** con un proyecto creado
2. **PostgreSQL client (psql)** instalado en tu máquina
3. **Variables de entorno** configuradas en `.env.local`
## 📋 Paso 1: Configurar Variables de Entorno
Copia el archivo `.env.example` a `.env.local`:
```bash
cp .env.example .env.local
```
Edita el archivo `.env.local` con tus credenciales de Supabase:
```bash
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key-here
```
### Cómo obtener las credenciales de Supabase
1. Ve a [Supabase Dashboard](https://supabase.com/dashboard)
2. Selecciona tu proyecto
3. Ve a **Settings → API**
4. Copia:
- **Project URL** → `NEXT_PUBLIC_SUPABASE_URL`
- **anon public** → `NEXT_PUBLIC_SUPABASE_ANON_KEY`
- **service_role** → `SUPABASE_SERVICE_ROLE_KEY`
## 🎯 Paso 2: Ejecutar Migraciones
### Opción A: Automática (Recomendada)
Usa el script de migración automatizado:
```bash
# Dar permisos de ejecución al script
chmod +x db/migrate.sh
# Ejecutar el script
./db/migrate.sh
```
### Opción B: Manual con psql
Si prefieres ejecutar las migraciones manualmente:
```bash
# Exportar DATABASE_URL
export DATABASE_URL="postgresql://postgres:[PASSWORD]@[PROJECT-ID].supabase.co:5432/postgres"
# Ejecutar cada migración en orden
psql $DATABASE_URL -f db/migrations/001_initial_schema.sql
psql $DATABASE_URL -f db/migrations/002_rls_policies.sql
psql $DATABASE_URL -f db/migrations/003_audit_triggers.sql
```
### Opción C: Vía Supabase Dashboard
1. Ve a [Supabase Dashboard → SQL Editor](https://supabase.com/dashboard/project/[PROJECT-ID]/sql)
2. Copia el contenido de cada migración en orden
3. Ejecuta `001_initial_schema.sql` primero
4. Luego `002_rls_policies.sql`
5. Finalmente `003_audit_triggers.sql`
## ✅ Paso 3: Verificar la Instalación
Ejecuta estas consultas para verificar que todo esté correcto:
### Verificar Tablas
```sql
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
ORDER BY table_name;
```
**Esperado:** 8 tablas (locations, resources, staff, services, customers, invitations, bookings, audit_logs)
### Verificar Funciones
```sql
SELECT routine_name
FROM information_schema.routines
WHERE routine_schema = 'public'
ORDER BY routine_name;
```
**Esperado:** 13 funciones incluyendo `generate_short_id`, `reset_weekly_invitations_for_customer`, etc.
### Verificar Triggers
```sql
SELECT trigger_name, event_object_table
FROM information_schema.triggers
WHERE trigger_schema = 'public'
ORDER BY event_object_table, trigger_name;
```
**Esperado:** Múltiples triggers para auditoría y timestamps
### Verificar Políticas RLS
```sql
SELECT schemaname, tablename, policyname, permissive, roles, cmd
FROM pg_policies
WHERE schemaname = 'public'
ORDER BY tablename, policyname;
```
**Esperado:** Múltiples políticas por rol (admin, manager, staff, artist, customer)
### Verificar Tipos ENUM
```sql
SELECT typname, enumlabel
FROM pg_enum e
JOIN pg_type t ON e.enumtypid = t.oid
WHERE t.typtype = 'e'
ORDER BY t.typname, e.enumsortorder;
```
**Esperado:** 6 tipos ENUM (user_role, customer_tier, booking_status, invitation_status, resource_type, audit_action)
## 🔍 Paso 4: Probar Funcionalidad
### Generar Short ID
```sql
SELECT generate_short_id();
```
**Esperado:** Un string de 6 caracteres alfanuméricos (ej: "A3F7X2")
### Generar Código de Invitación
```sql
SELECT generate_invitation_code();
```
**Esperado:** Un string de 10 caracteres alfanuméricos (ej: "X9J4K2M5N8")
### Obtener Inicio de Semana
```sql
SELECT get_week_start(CURRENT_DATE);
```
**Esperado:** El lunes de la semana actual
### Resetear Invitaciones de un Cliente
```sql
-- Primero necesitas un cliente Gold en la base de datos
-- Esto creará 5 invitaciones nuevas para la semana actual
SELECT reset_weekly_invitations_for_customer('[CUSTOMER_UUID]');
```
## 🚨 Solución de Problemas
### Error: "FATAL: password authentication failed"
**Causa:** La contraseña en DATABASE_URL es incorrecta.
**Solución:** Verifica que estés usando el `SUPABASE_SERVICE_ROLE_KEY` como contraseña en la URL de conexión.
### Error: "relation already exists"
**Causa:** Una tabla ya existe. La migración anterior puede haber fallado parcialmente.
**Solución:** Elimina las tablas existentes o ejecuta una limpieza completa:
```sql
DROP TABLE IF EXISTS audit_logs CASCADE;
DROP TABLE IF EXISTS bookings CASCADE;
DROP TABLE IF EXISTS invitations CASCADE;
DROP TABLE IF EXISTS customers CASCADE;
DROP TABLE IF EXISTS services CASCADE;
DROP TABLE IF EXISTS staff CASCADE;
DROP TABLE IF EXISTS resources CASCADE;
DROP TABLE IF EXISTS locations CASCADE;
DROP FUNCTION IF EXISTS generate_short_id();
DROP FUNCTION IF EXISTS generate_invitation_code();
DROP FUNCTION IF EXISTS reset_weekly_invitations_for_customer(UUID);
DROP FUNCTION IF EXISTS reset_all_weekly_invitations();
DROP FUNCTION IF EXISTS log_audit();
DROP FUNCTION IF EXISTS get_current_user_role();
DROP FUNCTION IF EXISTS is_staff_or_higher();
DROP FUNCTION IF EXISTS is_artist();
DROP FUNCTION IF EXISTS is_customer();
DROP FUNCTION IF EXISTS is_admin();
DROP FUNCTION IF EXISTS update_updated_at();
DROP FUNCTION IF EXISTS generate_booking_short_id();
DROP FUNCTION IF EXISTS get_week_start(DATE);
```
### Error: "must be owner of table"
**Causa:** No tienes permisos de superusuario o owner de la tabla.
**Solución:** Asegúrate de estar usando el `SUPABASE_SERVICE_ROLE_KEY` (no el anon key).
### Error: RLS no funciona
**Causa:** RLS no está habilitado o el usuario no tiene un rol asignado.
**Solución:**
1. Verifica que RLS está habilitado: `SELECT tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';`
2. Verifica que el usuario tenga un registro en `staff` o `customers`
3. Verifica las políticas RLS: `SELECT * FROM pg_policies WHERE schemaname = 'public';`
## 📚 Documentación Adicional
- **PRD.md:** Reglas de negocio del sistema
- **TASKS.md:** Plan de ejecución por fases
- **AGENTS.md:** Roles y responsabilidades de IA
- **db/migrations/README.md:** Documentación técnica de migraciones
## 🎓 Próximos Pasos
Después de completar las migraciones:
1. **Configurar Auth en Supabase Dashboard**
- Habilitar Email/SMS authentication
- Configurar Magic Links
- Crear usuarios de prueba
2. **Crear Seeds de Datos**
- Locations de prueba
- Staff con diferentes roles
- Services del catálogo
- Customers Free y Gold
3. **Implementar Tarea 1.3**
- Backend API endpoints para Short ID
- Tests unitarios
- Edge Function o Cron Job para reset semanal
4. **Implementar Tarea 1.4**
- Endpoints CRUD de customers
- Lógica de cálculo automático de Tier
- Sistema de referidos
## 🆘 Soporte
Si encuentras problemas:
1. Revisa los logs de Supabase Dashboard
2. Verifica que las variables de entorno estén correctamente configuradas
3. Ejecuta las consultas de verificación en el "Paso 3"
4. Consulta la sección de "Solución de Problemas"
---
**Última actualización:** 2026-01-15
**Versión de migraciones:** 001, 002, 003
**Estado:** ✅ Listo para producción