Guía Rápida - Sistema B2B
Sección titulada «Guía Rápida - Sistema B2B»Resumen Ejecutivo
Sección titulada «Resumen Ejecutivo»El sistema B2B permite a empresas comprar suscripciones de equipo y gestionar el acceso de sus empleados a los cursos de TalentBricksAI.
Jerarquía de Roles
Sección titulada «Jerarquía de Roles»Platform Admin (isAdmin = true en User) └─ Acceso completo a todas las organizaciones
Organization OWNER └─ Control total: facturación, miembros, cursos
Organization ADMIN └─ Gestión de equipo: invitar, remover, asignar cursos
Organization MEMBER └─ Acceso usuario final: solo ver cursos asignadosSetup Rápido (5 minutos)
Sección titulada «Setup Rápido (5 minutos)»1. Crear Datos de Prueba
Sección titulada «1. Crear Datos de Prueba»cd app
# Opción A: Seed completo (incluye todo)wasp db seed seedAllDummyData
# Opción B: Solo organizaciones (si ya tienes cursos)wasp db seed seedOrganizationTestData2. Iniciar la Aplicación
Sección titulada «2. Iniciar la Aplicación»# Terminal 1: Base de datoswasp db start
# Terminal 2: Aplicaciónwasp start3. Iniciar Sesión
Sección titulada «3. Iniciar Sesión»Abre http://localhost:3000 y usa estas credenciales:
Platform Admin
Sección titulada «Platform Admin»| Password | Dashboard | |
|---|---|---|
admin@talentbricks.ai | Admin123! | /admin/organizations |
Usuarios de Organizaciones (Password: Test123!)
Sección titulada «Usuarios de Organizaciones (Password: Test123!)»| Rol | Organización | Seats | |
|---|---|---|---|
owner@talentbricks.test | OWNER | TalentBricks Corp | 10 |
admin@talentbricks.test | ADMIN | TalentBricks Corp | 10 |
member1@talentbricks.test | MEMBER | TalentBricks Corp | 10 |
member2@talentbricks.test | MEMBER | TalentBricks Corp | 10 |
owner@acme.test | OWNER | Acme Inc | 25 |
admin@acme.test | ADMIN | Acme Inc | 25 |
owner@startup.test | OWNER | StartupXYZ | 5 |
Para obtener el organizationId de cada organización:
psql $DATABASE_URL -c "SELECT id, name, \"maxSeats\" FROM \"Organization\";"Flujos de Prueba Esenciales
Sección titulada «Flujos de Prueba Esenciales»Flujo 1: Como Platform Admin
Sección titulada «Flujo 1: Como Platform Admin»- Login como
admin@talentbricks.ai - Ir a
/admin/organizations - Ver lista de todas las organizaciones
- Hacer clic en “TalentBricks Corp”
- Ver detalles: miembros, cursos, analíticas
- Editar: cambiar nombre o maxSeats
Verificar en BD:
psql $DATABASE_URL -c "SELECT id, name, \"maxSeats\", \"usedSeats\", \"subscriptionStatus\" FROM \"Organization\";"Flujo 2: Como OWNER - Invitar Miembro
Sección titulada «Flujo 2: Como OWNER - Invitar Miembro»- Login como
owner@talentbricks.test - Obtener organizationId:
psql $DATABASE_URL -c "SELECT id, name FROM \"Organization\" WHERE name = 'TalentBricks Corp';"- Ir a
/team/{organizationId}/members - Click en “Invitar Miembro”
- Email:
newuser@test.com, Rol: MEMBER - Click “Enviar Invitación”
Obtener token de invitación:
psql $DATABASE_URL -c "SELECT token, email, role, \"expiresAt\" FROM \"OrganizationInvitation\" WHERE email = 'newuser@test.com';"Flujo 3: Aceptar Invitación
Sección titulada «Flujo 3: Aceptar Invitación»- Crear cuenta en
/signupconnewuser@test.com - Login
- Ir a
/invitation/{token}(usa el token del paso anterior) - Click “Aceptar Invitación”
- Verificar que ahora eres miembro
Verificar:
psql $DATABASE_URL -c "SELECT u.email, om.role, om.\"joinedAt\" FROM \"OrganizationMember\" om JOIN \"User\" u ON om.\"userId\" = u.id WHERE u.email = 'newuser@test.com';"Flujo 4: Como ADMIN - Asignar Curso
Sección titulada «Flujo 4: Como ADMIN - Asignar Curso»- Login como
admin@talentbricks.test - Ir a
/team/{organizationId}/courses - Click “Asignar Curso”
- Seleccionar un curso
- Click “Asignar”
Verificar:
psql $DATABASE_URL -c "SELECT c.title, u.email as \"assignedBy\", oe.\"assignedAt\" FROM \"OrganizationEnrollment\" oe JOIN \"Course\" c ON oe.\"courseId\" = c.id JOIN \"User\" u ON oe.\"assignedById\" = u.id WHERE oe.\"organizationId\" = '{organizationId}';"Flujo 5: Como MEMBER - Acceder a Curso
Sección titulada «Flujo 5: Como MEMBER - Acceder a Curso»- Login como
member1@talentbricks.test - Ir a
/courses - Buscar un curso asignado a tu organización
- Verificar que muestra “Acceso con Equipo”
- Click “Ir al Curso”
- Ir a
/courses/{slug}/learn - Reproducir una lección
- Verificar que el progreso se guarda
Flujo 6: Límite de Asientos
Sección titulada «Flujo 6: Límite de Asientos»Setup:
# Establecer maxSeats = 3 para pruebapsql $DATABASE_URL -c "UPDATE \"Organization\" SET \"maxSeats\" = 3 WHERE name = 'TalentBricks Corp';"
# Ver seats actualespsql $DATABASE_URL -c "SELECT \"usedSeats\", \"maxSeats\", \"maxSeats\" - \"usedSeats\" as available FROM \"Organization\" WHERE name = 'TalentBricks Corp';"- Login como OWNER
- Intentar invitar un miembro cuando
usedSeats >= maxSeats - Verificar que se muestre error: “No hay asientos disponibles”
- Remover un miembro
- Verificar que ahora sí puedas invitar
Estructura de Permisos
Sección titulada «Estructura de Permisos»Matriz de Permisos Detallada
Sección titulada «Matriz de Permisos Detallada»| Acción | Platform Admin | OWNER | ADMIN | MEMBER |
|---|---|---|---|---|
| Gestión de Miembros | ||||
| Ver lista de miembros | ✅ | ✅ | ✅ | ❌ |
| Invitar miembros | ✅ | ✅ | ✅ | ❌ |
| Remover miembros | ✅ | ✅ | ✅ | ❌ |
| Cambiar roles | ✅ | ✅ | ❌ | ❌ |
| Gestión de Cursos | ||||
| Ver cursos asignados | ✅ | ✅ | ✅ | ✅ |
| Asignar cursos | ✅ | ✅ | ✅ | ❌ |
| Desasignar cursos | ✅ | ✅ | ✅ | ❌ |
| Acceder a cursos | ✅ | ✅ | ✅ | ✅ |
| Facturación | ||||
| Ver facturación | ✅ | ✅ | ❌ | ❌ |
| Gestionar suscripción | ✅ | ✅ | ❌ | ❌ |
| Ver portal de Stripe | ✅ | ✅ | ❌ | ❌ |
| Administración | ||||
| Ver analíticas | ✅ | ✅ | ✅ | ❌ |
| Editar organización | ✅ | ✅ | ❌ | ❌ |
| Eliminar organización | ✅ | ✅ | ❌ | ❌ |
Comandos SQL Útiles
Sección titulada «Comandos SQL Útiles»Ver Estado de una Organización
Sección titulada «Ver Estado de una Organización»psql $DATABASE_URL -c "SELECT o.name, o.\"maxSeats\", o.\"usedSeats\", o.\"subscriptionStatus\", o.\"subscriptionPlan\", o.\"datePaid\", COUNT(DISTINCT om.id) as member_count, COUNT(DISTINCT oe.id) as course_countFROM \"Organization\" oLEFT JOIN \"OrganizationMember\" om ON o.id = om.\"organizationId\"LEFT JOIN \"OrganizationEnrollment\" oe ON o.id = oe.\"organizationId\"WHERE o.name = 'TalentBricks Corp'GROUP BY o.id;"Ver Miembros con Roles
Sección titulada «Ver Miembros con Roles»psql $DATABASE_URL -c "SELECT u.email, u.username, om.role, om.\"joinedAt\", o.name as organizationFROM \"OrganizationMember\" omJOIN \"User\" u ON om.\"userId\" = u.idJOIN \"Organization\" o ON om.\"organizationId\" = o.idWHERE o.name = 'TalentBricks Corp'ORDER BY om.role, om.\"joinedAt\";"Ver Cursos Asignados
Sección titulada «Ver Cursos Asignados»psql $DATABASE_URL -c "SELECT c.title, c.slug, u.email as assigned_by, oe.\"assignedAt\"FROM \"OrganizationEnrollment\" oeJOIN \"Course\" c ON oe.\"courseId\" = c.idJOIN \"User\" u ON oe.\"assignedById\" = u.idJOIN \"Organization\" o ON oe.\"organizationId\" = o.idWHERE o.name = 'TalentBricks Corp';"Ver Invitaciones Pendientes
Sección titulada «Ver Invitaciones Pendientes»psql $DATABASE_URL -c "SELECT oi.email, oi.role, oi.token, u.email as invited_by, oi.\"invitedAt\", oi.\"expiresAt\", oi.\"acceptedAt\"FROM \"OrganizationInvitation\" oiJOIN \"User\" u ON oi.\"invitedBy\" = u.idJOIN \"Organization\" o ON oi.\"organizationId\" = o.idWHERE o.name = 'TalentBricks Corp'ORDER BY oi.\"invitedAt\" DESC;"Recalcular usedSeats (Fix)
Sección titulada «Recalcular usedSeats (Fix)»# Si usedSeats está desincronizadopsql $DATABASE_URL -c "UPDATE \"Organization\" oSET \"usedSeats\" = ( SELECT COUNT(*) FROM \"OrganizationMember\" om WHERE om.\"organizationId\" = o.id);"Troubleshooting
Sección titulada «Troubleshooting»Problema: “403 Forbidden” al acceder a /team/{organizationId}
Sección titulada «Problema: “403 Forbidden” al acceder a /team/{organizationId}»Causa: Usuario no es miembro de la organización.
Verificar:
psql $DATABASE_URL -c "SELECT * FROM \"OrganizationMember\" WHERE \"userId\" = '{user_id}' AND \"organizationId\" = '{org_id}';"Solución: Invitar al usuario o verificar que aceptó la invitación.
Problema: No se puede invitar más miembros
Sección titulada «Problema: No se puede invitar más miembros»Causa: usedSeats >= maxSeats
Verificar:
psql $DATABASE_URL -c "SELECT \"usedSeats\", \"maxSeats\" FROM \"Organization\" WHERE id = '{org_id}';"Solución temporal (solo dev):
psql $DATABASE_URL -c "UPDATE \"Organization\" SET \"maxSeats\" = 20 WHERE id = '{org_id}';"Problema: Miembro no puede acceder a curso asignado
Sección titulada «Problema: Miembro no puede acceder a curso asignado»Causa: subscriptionStatus != 'active' o curso no asignado.
Verificar subscription:
psql $DATABASE_URL -c "SELECT \"subscriptionStatus\" FROM \"Organization\" WHERE id = '{org_id}';"Verificar enrollment:
psql $DATABASE_URL -c "SELECT * FROM \"OrganizationEnrollment\" WHERE \"organizationId\" = '{org_id}' AND \"courseId\" = {course_id};"Problema: usedSeats incorrecto
Sección titulada «Problema: usedSeats incorrecto»Solución:
psql $DATABASE_URL -c "UPDATE \"Organization\"SET \"usedSeats\" = ( SELECT COUNT(*) FROM \"OrganizationMember\" WHERE \"organizationId\" = \"Organization\".id);"Próximos Pasos
Sección titulada «Próximos Pasos»- ✅ Prueba los flujos básicos con los usuarios de prueba
- ✅ Verifica los permisos con cada rol
- 📖 Lee la guía completa en Guía de Pruebas para casos edge
- 🏗️ Revisa la arquitectura en Arquitectura
- 🚀 Integra con Stripe para pruebas de checkout (usa test keys)
- 📧 Configura emails para invitaciones (opcional en dev)