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

View File

@@ -0,0 +1,370 @@
# 🎉 Migraciones Exitosas - SalonOS
## ✅ Estado: Migraciones Completadas
¡Excelente! Las migraciones de base de datos se han ejecutado exitosamente en Supabase.
---
## 🔍 Paso 1: Verificar la Instalación
Vamos a ejecutar un script de verificación para confirmar que todo se creó correctamente.
### Ejecutar Script de Verificación
1. Ve a: **https://supabase.com/dashboard/project/pvvwbnybkadhreuqijsl/sql**
2. Haz clic en **"New query"**
3. Copia el contenido de: **`scripts/verify-migration.sql`**
4. Pega el contenido en el SQL Editor
5. Haz clic en **"Run"**
### Resultado Esperado
Deberías ver:
```
TABLAS | locations
TABLAS | resources
TABLAS | staff
TABLAS | services
TABLAS | customers
TABLAS | invitations
TABLAS | bookings
TABLAS | audit_logs
...
FUNCIONES | generate_short_id
FUNCIONES | generate_invitation_code
FUNCIONES | reset_all_weekly_invitations
FUNCIONES | validate_secondary_artist_role
...
TRIGGERS | locations_updated_at
TRIGGERS | validate_booking_secondary_artist
...
POLÍTICAS RLS | customers_select_admin_manager
...
ENUM TYPES | user_role
ENUM TYPES | customer_tier
...
SHORT ID TEST | A3F7X2
INVITATION CODE TEST | X9J4K2M5N8
...
RESUMEN | Tablas: 8
RESUMEN | Funciones: 14
RESUMEN | Triggers: 17+
RESUMEN | Políticas RLS: 20+
RESUMEN | Tipos ENUM: 6
```
---
## 🌱 Paso 2: Crear Datos de Prueba
Ahora vamos a crear datos de prueba para poder desarrollar y probar el sistema.
### Ejecutar Script de Seed
1. En el mismo SQL Editor, haz clic en **"New query"**
2. Copia el contenido de: **`scripts/seed-data.sql`**
3. Pega el contenido en el SQL Editor
4. Haz clic en **"Run"**
### Resultado Esperado
Deberías ver:
```
==========================================
SALONOS - SEED DE DATOS COMPLETADO
==========================================
Locations: 3
Resources: 6
Staff: 8
Services: 6
Customers: 4
Invitations: 15
Bookings: 5
==========================================
✅ Base de datos lista para desarrollo
==========================================
```
### Datos Creados
**Locations (3):**
- Salón Principal - Centro
- Salón Norte - Polanco
- Salón Sur - Coyoacán
**Resources (6):**
- 3 estaciones en Centro
- 2 estaciones en Polanco
- 1 estación en Coyoacán
**Staff (8):**
- 1 Admin
- 2 Managers
- 1 Staff
- 4 Artists (María, Ana, Carla, Laura)
**Services (6):**
- Corte y Estilizado ($500)
- Color Completo ($1,200)
- Balayage Premium ($2,000) - **Dual Artist**
- Tratamiento Kératina ($1,500)
- Peinado Evento ($800)
- Servicio Express ($600) - **Dual Artist**
**Customers (4):**
- Sofía Ramírez (Gold) - VIP
- Valentina Hernández (Gold)
- Camila López (Free)
- Isabella García (Gold) - VIP
**Invitations (15):**
- 5 para cada cliente Gold (Sofía, Valentina, Isabella)
**Bookings (5):**
- 1 Balayage Premium para Sofía
- 1 Color Completo para Valentina
- 1 Corte y Estilizado para Camila
- 1 Servicio Express Dual Artist para Isabella (con secondary_artist)
- 1 Peinado Evento para Sofía
---
## 🧪 Paso 3: Probar Funcionalidades
### Probar Short ID
```sql
SELECT generate_short_id();
```
**Resultado esperado:** String de 6 caracteres (ej: "A3F7X2")
### Probar Código de Invitación
```sql
SELECT generate_invitation_code();
```
**Resultado esperado:** String de 10 caracteres (ej: "X9J4K2M5N8")
### Verificar Bookings Creados
```sql
SELECT
b.short_id,
c.first_name || ' ' || c.last_name as customer,
s.display_name as artist,
svc.name as service,
b.start_time_utc,
b.end_time_utc,
b.status,
b.total_amount
FROM bookings b
JOIN customers c ON b.customer_id = c.id
JOIN staff s ON b.staff_id = s.id
JOIN services svc ON b.service_id = svc.id
ORDER BY b.start_time_utc;
```
### Verificar Invitaciones
```sql
SELECT
i.code,
inv.first_name || ' ' || inv.last_name as inviter,
i.status,
i.week_start_date,
i.expiry_date
FROM invitations i
JOIN customers inv ON i.inviter_id = inv.id
WHERE i.status = 'pending'
ORDER BY inv.first_name, i.expiry_date;
```
### Verificar Staff y Roles
```sql
SELECT
s.display_name,
s.role,
l.name as location,
s.phone,
s.is_active
FROM staff s
JOIN locations l ON s.location_id = l.id
ORDER BY l.name, s.role, s.display_name;
```
### Verificar Auditoría
```sql
SELECT
entity_type,
action,
new_values->>'operation' as operation,
new_values->>'table_name' as table_name,
created_at
FROM audit_logs
ORDER BY created_at DESC
LIMIT 10;
```
### Probar Validación de Secondary Artist
**Test 1: Intentar crear booking con secondary_artist válido**
```sql
-- Este debe funcionar
INSERT INTO bookings (
customer_id,
staff_id,
secondary_artist_id,
location_id,
resource_id,
service_id,
start_time_utc,
end_time_utc,
status,
deposit_amount,
total_amount,
is_paid,
notes
)
SELECT
(SELECT id FROM customers WHERE email = 'sofia.ramirez@example.com'),
(SELECT id FROM staff WHERE display_name = 'Artist María García'),
(SELECT id FROM staff WHERE display_name = 'Artist Ana Rodríguez'),
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro'),
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro') LIMIT 1 OFFSET 2 LIMIT 1),
(SELECT id FROM services WHERE name = 'Balayage Premium'),
NOW() + INTERVAL '7 days',
NOW() + INTERVAL '7 days' + INTERVAL '3 hours',
'confirmed',
200.00,
2000.00,
true,
'Test de validación - secondary_artist válido'
RETURNING short_id;
```
**Resultado esperado:** ✅ Booking creado exitosamente
**Test 2: Intentar crear booking con secondary_artist inválido**
```sql
-- Este debe fallar
INSERT INTO bookings (
customer_id,
staff_id,
secondary_artist_id,
location_id,
resource_id,
service_id,
start_time_utc,
end_time_utc,
status,
deposit_amount,
total_amount,
is_paid,
notes
)
SELECT
(SELECT id FROM customers WHERE email = 'sofia.ramirez@example.com'),
(SELECT id FROM staff WHERE display_name = 'Artist María García'),
(SELECT id FROM staff WHERE display_name = 'Manager Centro'), -- ❌ Esto NO es 'artist'
(SELECT id FROM locations WHERE name = 'Salón Principal - Centro'),
(SELECT id FROM resources WHERE location_id = (SELECT id FROM locations WHERE name = 'Salón Principal - Centro') LIMIT 1 OFFSET 2 LIMIT 1),
(SELECT id FROM services WHERE name = 'Balayage Premium'),
NOW() + INTERVAL '8 days',
NOW() + INTERVAL '8 days' + INTERVAL '3 hours',
'confirmed',
200.00,
2000.00,
true,
'Test de validación - secondary_artist inválido';
```
**Resultado esperado:** ❌ Error: `secondary_artist_id must reference an active staff member with role 'artist'`
---
## ✅ Paso 4: Verificar Checklist
Antes de continuar con el desarrollo, asegúrate de:
- [x] Migraciones ejecutadas exitosamente
- [ ] Script de verificación ejecutado y todo correcto
- [ ] Script de seed ejecutado y datos creados
- [ ] Short ID generable
- [ ] Código de invitación generable
- [ ] Validación de secondary_artist funcionando
- [ ] Auditoría registrando correctamente
---
## 🎓 Próximos Pasos
### Configurar Auth en Supabase Dashboard
1. Ve a: **Authentication → Providers**
2. Habilita **Email Provider**
3. Configura **Email Templates** (opcional)
4. Habilita **SMS Provider** si usas Twilio (opcional)
### Crear Usuarios en Auth
Para los datos de seed, necesitas crear usuarios en Supabase Auth:
1. Ve a: **Authentication → Users**
2. Haz clic en **"Add user"** para cada usuario de staff y customer
3. Usa los mismos UUIDs que están en el seed para los `user_id` de staff y customers
### Continuar con el Desarrollo
Ahora que la base de datos está lista, puedes continuar con:
1. **Tarea 1.3:** Short ID & Invitations
- Implementar endpoints de API
- Tests unitarios
- Edge Function o Cron Job para reset semanal
2. **Tarea 1.4:** CRM Base
- Endpoints CRUD de customers
- Lógica de cálculo automático de Tier
- Sistema de referidos
3. **Fase 2:** Motor de Agendamiento
- Validación Staff/Artist
- Validación Recursos
- Servicios Express (Dual Artist)
---
## 📚 Documentación Disponible
- **`docs/00_FULL_MIGRATION_FINAL_README.md`** - Guía de migración final
- **`docs/MIGRATION_CORRECTION.md`** - Detalle de correcciones
- **`docs/SUPABASE_DASHBOARD_MIGRATION.md`** - Guía de ejecución
- **`scripts/verify-migration.sql`** - Script de verificación
- **`scripts/seed-data.sql`** - Script de datos de prueba
- **`FASE_1_STATUS.md`** - Estado de la Fase 1
---
## 🆘 Soporte
Si encuentras problemas:
1. Revisa los logs de Supabase Dashboard
2. Ejecuta el script de verificación
3. Consulta la documentación arriba
4. Verifica que las funciones y triggers estén creados correctamente
---
**¡Felicidades!** 🎉 Tu base de datos de SalonOS está completamente configurada y lista para el desarrollo.
**¿Listo para configurar Auth en Supabase Dashboard o continuar con el desarrollo de la aplicación?**