Ir al contenido

El sistema B2B permite a empresas comprar suscripciones de equipo y gestionar el acceso de sus empleados a los cursos de TalentBricksAI.

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 asignados
Ventana de terminal
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 seedOrganizationTestData
Ventana de terminal
# Terminal 1: Base de datos
wasp db start
# Terminal 2: Aplicación
wasp start

Abre http://localhost:3000 y usa estas credenciales:

EmailPasswordDashboard
admin@talentbricks.aiAdmin123!/admin/organizations

Usuarios de Organizaciones (Password: Test123!)

Sección titulada «Usuarios de Organizaciones (Password: Test123!)»
EmailRolOrganizaciónSeats
owner@talentbricks.testOWNERTalentBricks Corp10
admin@talentbricks.testADMINTalentBricks Corp10
member1@talentbricks.testMEMBERTalentBricks Corp10
member2@talentbricks.testMEMBERTalentBricks Corp10
owner@acme.testOWNERAcme Inc25
admin@acme.testADMINAcme Inc25
owner@startup.testOWNERStartupXYZ5

Para obtener el organizationId de cada organización:

Ventana de terminal
psql $DATABASE_URL -c "SELECT id, name, \"maxSeats\" FROM \"Organization\";"
  1. Login como admin@talentbricks.ai
  2. Ir a /admin/organizations
  3. Ver lista de todas las organizaciones
  4. Hacer clic en “TalentBricks Corp”
  5. Ver detalles: miembros, cursos, analíticas
  6. Editar: cambiar nombre o maxSeats

Verificar en BD:

Ventana de terminal
psql $DATABASE_URL -c "SELECT id, name, \"maxSeats\", \"usedSeats\", \"subscriptionStatus\" FROM \"Organization\";"
  1. Login como owner@talentbricks.test
  2. Obtener organizationId:
Ventana de terminal
psql $DATABASE_URL -c "SELECT id, name FROM \"Organization\" WHERE name = 'TalentBricks Corp';"
  1. Ir a /team/{organizationId}/members
  2. Click en “Invitar Miembro”
  3. Email: newuser@test.com, Rol: MEMBER
  4. Click “Enviar Invitación”

Obtener token de invitación:

Ventana de terminal
psql $DATABASE_URL -c "SELECT token, email, role, \"expiresAt\" FROM \"OrganizationInvitation\" WHERE email = 'newuser@test.com';"
  1. Crear cuenta en /signup con newuser@test.com
  2. Login
  3. Ir a /invitation/{token} (usa el token del paso anterior)
  4. Click “Aceptar Invitación”
  5. Verificar que ahora eres miembro

Verificar:

Ventana de terminal
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';"
  1. Login como admin@talentbricks.test
  2. Ir a /team/{organizationId}/courses
  3. Click “Asignar Curso”
  4. Seleccionar un curso
  5. Click “Asignar”

Verificar:

Ventana de terminal
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}';"
  1. Login como member1@talentbricks.test
  2. Ir a /courses
  3. Buscar un curso asignado a tu organización
  4. Verificar que muestra “Acceso con Equipo”
  5. Click “Ir al Curso”
  6. Ir a /courses/{slug}/learn
  7. Reproducir una lección
  8. Verificar que el progreso se guarda

Setup:

Ventana de terminal
# Establecer maxSeats = 3 para prueba
psql $DATABASE_URL -c "UPDATE \"Organization\" SET \"maxSeats\" = 3 WHERE name = 'TalentBricks Corp';"
# Ver seats actuales
psql $DATABASE_URL -c "SELECT \"usedSeats\", \"maxSeats\", \"maxSeats\" - \"usedSeats\" as available FROM \"Organization\" WHERE name = 'TalentBricks Corp';"
  1. Login como OWNER
  2. Intentar invitar un miembro cuando usedSeats >= maxSeats
  3. Verificar que se muestre error: “No hay asientos disponibles”
  4. Remover un miembro
  5. Verificar que ahora sí puedas invitar
AcciónPlatform AdminOWNERADMINMEMBER
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✅✅❌❌
Ventana de terminal
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_count
FROM \"Organization\" o
LEFT 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;
"
Ventana de terminal
psql $DATABASE_URL -c "
SELECT
u.email,
u.username,
om.role,
om.\"joinedAt\",
o.name as organization
FROM \"OrganizationMember\" om
JOIN \"User\" u ON om.\"userId\" = u.id
JOIN \"Organization\" o ON om.\"organizationId\" = o.id
WHERE o.name = 'TalentBricks Corp'
ORDER BY om.role, om.\"joinedAt\";
"
Ventana de terminal
psql $DATABASE_URL -c "
SELECT
c.title,
c.slug,
u.email as assigned_by,
oe.\"assignedAt\"
FROM \"OrganizationEnrollment\" oe
JOIN \"Course\" c ON oe.\"courseId\" = c.id
JOIN \"User\" u ON oe.\"assignedById\" = u.id
JOIN \"Organization\" o ON oe.\"organizationId\" = o.id
WHERE o.name = 'TalentBricks Corp';
"
Ventana de terminal
psql $DATABASE_URL -c "
SELECT
oi.email,
oi.role,
oi.token,
u.email as invited_by,
oi.\"invitedAt\",
oi.\"expiresAt\",
oi.\"acceptedAt\"
FROM \"OrganizationInvitation\" oi
JOIN \"User\" u ON oi.\"invitedBy\" = u.id
JOIN \"Organization\" o ON oi.\"organizationId\" = o.id
WHERE o.name = 'TalentBricks Corp'
ORDER BY oi.\"invitedAt\" DESC;
"
Ventana de terminal
# Si usedSeats está desincronizado
psql $DATABASE_URL -c "
UPDATE \"Organization\" o
SET \"usedSeats\" = (
SELECT COUNT(*)
FROM \"OrganizationMember\" om
WHERE om.\"organizationId\" = o.id
);
"

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:

Ventana de terminal
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.

Causa: usedSeats >= maxSeats

Verificar:

Ventana de terminal
psql $DATABASE_URL -c "SELECT \"usedSeats\", \"maxSeats\" FROM \"Organization\" WHERE id = '{org_id}';"

Solución temporal (solo dev):

Ventana de terminal
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:

Ventana de terminal
psql $DATABASE_URL -c "SELECT \"subscriptionStatus\" FROM \"Organization\" WHERE id = '{org_id}';"

Verificar enrollment:

Ventana de terminal
psql $DATABASE_URL -c "SELECT * FROM \"OrganizationEnrollment\" WHERE \"organizationId\" = '{org_id}' AND \"courseId\" = {course_id};"

Solución:

Ventana de terminal
psql $DATABASE_URL -c "
UPDATE \"Organization\"
SET \"usedSeats\" = (
SELECT COUNT(*)
FROM \"OrganizationMember\"
WHERE \"organizationId\" = \"Organization\".id
);
"
  1. ✅ Prueba los flujos básicos con los usuarios de prueba
  2. ✅ Verifica los permisos con cada rol
  3. 📖 Lee la guía completa en Guía de Pruebas para casos edge
  4. 🏗️ Revisa la arquitectura en Arquitectura
  5. 🚀 Integra con Stripe para pruebas de checkout (usa test keys)
  6. 📧 Configura emails para invitaciones (opcional en dev)