Ir al contenido

El sistema de organizaciones permite a empresas comprar suscripciones de equipo con múltiples asientos (seats) y gestionar el acceso de sus miembros a los cursos de TalentBricksAI.

RolDescripciónPermisos
Platform AdminAdministrador de la plataforma• Ver todas las organizaciones
• Gestionar cualquier organización
• Acceso completo al admin dashboard
OWNERDueño de la organización• Gestionar suscripción y facturación
• Invitar/remover miembros
• Asignar cursos
• Cambiar roles de miembros
• Eliminar organización
• Ver analíticas
ADMINAdministrador de equipo• Invitar/remover miembros
• Asignar cursos
• Ver analíticas
NO puede gestionar facturación ni eliminar la organización
MEMBERMiembro del equipo• Acceder a cursos asignados a la organización
• Ver progreso personal
NO puede invitar usuarios ni gestionar el equipo
Ventana de terminal
cd app
wasp db seed seedOrganizationTestData
EmailPasswordDashboard
admin@talentbricks.aiAdmin123!/admin/organizations

Usuarios de Organizaciones (Password: Test123!)

Sección titulada «Usuarios de Organizaciones (Password: Test123!)»
EmailPasswordRolOrganizaciónSeats
owner@talentbricks.testTest123!OWNERTalentBricks Corp10
admin@talentbricks.testTest123!ADMINTalentBricks Corp10
member1@talentbricks.testTest123!MEMBERTalentBricks Corp10
member2@talentbricks.testTest123!MEMBERTalentBricks Corp10
owner@acme.testTest123!OWNERAcme Inc25
admin@acme.testTest123!ADMINAcme Inc25
owner@startup.testTest123!OWNERStartupXYZ5
  • 3 organizaciones de prueba:

    • TalentBricks Corp (10 seats)
    • Acme Inc (25 seats)
    • StartupXYZ (5 seats)
  • 7 usuarios de prueba (ver tabla arriba)

  • Cursos asignados:

    • TalentBricks Corp tiene acceso a los primeros 2 cursos
    • Acme Inc tiene acceso al primer curso

Objetivo: Verificar el flujo completo de compra de una suscripción de equipo.

Pasos:

  1. Inicia sesión con un usuario regular
  2. Navega a /teams/purchase
  3. Selecciona un plan de equipo (ej: 10 seats)
  4. Completa el formulario (nombre de org, email de facturación)
  5. Haz clic en “Continuar al checkout”
  6. Completa el checkout de Stripe (tarjeta de prueba: 4242 4242 4242 4242)
  7. Verifica redirección a /team/{organizationId}

Verificaciones:

Ventana de terminal
# Verificar nueva organización
psql $DATABASE_URL -c "SELECT id, name, maxSeats, subscriptionStatus FROM \"Organization\" ORDER BY \"createdAt\" DESC LIMIT 1;"
# Verificar membresía
psql $DATABASE_URL -c "SELECT om.role, u.email FROM \"OrganizationMember\" om JOIN \"User\" u ON om.\"userId\" = u.id WHERE om.\"organizationId\" = '{organization_id}';"

Resultados esperados:

  • ✅ Nueva organización creada
  • subscriptionStatus = 'active'
  • maxSeats coincide con plan
  • ✅ Usuario es OWNER
  • usedSeats = 1

Objetivo: Verificar que OWNER y ADMIN pueden invitar miembros.

  1. Inicia sesión como owner@talentbricks.test
  2. Navega a /team/{organizationId}/members
  3. Haz clic en “Invitar Miembro”
  4. Ingresa email: newmember@test.com, Rol: MEMBER
  5. Envía la invitación
  6. Verifica que aparezca en “Invitaciones Pendientes”
  1. Inicia sesión como member1@talentbricks.test
  2. Verifica que NO aparezca el botón “Invitar Miembro”

Verificaciones:

Ventana de terminal
psql $DATABASE_URL -c "SELECT email, role, \"invitedBy\", \"expiresAt\" FROM \"OrganizationInvitation\" WHERE \"organizationId\" = '{organization_id}';"

Resultados esperados:

  • ✅ OWNER puede invitar miembros
  • ✅ ADMIN puede invitar miembros
  • ✅ MEMBER NO puede invitar miembros
  • ✅ Token único generado
  • ✅ Expiración = 7 días

Objetivo: Verificar que usuarios invitados puedan unirse.

Pasos:

  1. Obtén el token de invitación:
Ventana de terminal
psql $DATABASE_URL -c "SELECT token FROM \"OrganizationInvitation\" WHERE email = 'newmember@test.com' LIMIT 1;"
  1. Si el usuario no existe, créalo en /signup
  2. Navega a /invitation/{token}
  3. Acepta la invitación
  4. Verifica redirección a /team/{organizationId}

Verificaciones:

Ventana de terminal
# Verificar nuevo miembro
psql $DATABASE_URL -c "SELECT om.role, u.email FROM \"OrganizationMember\" om JOIN \"User\" u ON om.\"userId\" = u.id WHERE u.email = 'newmember@test.com';"
# Verificar usedSeats incrementado
psql $DATABASE_URL -c "SELECT \"usedSeats\", \"maxSeats\" FROM \"Organization\" WHERE id = '{organization_id}';"

Resultados esperados:

  • ✅ Usuario es miembro
  • usedSeats incrementado
  • acceptedAt establecido
  • ✅ Rol correcto

Objetivo: Verificar que admins pueden asignar cursos.

  1. Inicia sesión como owner@talentbricks.test
  2. Navega a /team/{organizationId}/courses
  3. Asigna un curso
  1. Verifica que NO aparezca el botón “Asignar Curso”
  2. Solo ve los cursos ya asignados

Verificaciones:

Ventana de terminal
psql $DATABASE_URL -c "SELECT c.title, u.email as \"assignedBy\" FROM \"OrganizationEnrollment\" oe JOIN \"Course\" c ON oe.\"courseId\" = c.id JOIN \"User\" u ON oe.\"assignedById\" = u.id WHERE oe.\"organizationId\" = '{organization_id}';"

Resultados esperados:

  • ✅ OWNER y ADMIN pueden asignar
  • ✅ MEMBER NO puede asignar
  • assignedById registra quién asignó

Objetivo: Verificar que miembros pueden acceder a cursos asignados.

Pasos:

  1. Asigna un curso a la organización
  2. Inicia sesión como member1@talentbricks.test
  3. Navega a /courses/{slug}/learn
  4. Reproduce una lección
  5. Verifica que el progreso se guarde

Como usuario sin membresía:

  1. Inicia sesión con un usuario NO miembro
  2. Intenta acceder al curso
  3. Verifica denegación de acceso (403)

Resultados esperados:

  • ✅ Miembros pueden acceder
  • ✅ No-miembros NO pueden
  • ✅ Progreso se guarda
  • ✅ Videos se cargan

Objetivo: Verificar que solo OWNER puede cambiar roles.

  1. Promover MEMBER a ADMIN
  2. Degradar ADMIN a MEMBER
  3. Verificar cambios en BD
  1. Verificar que NO aparezca “Cambiar Rol”

Verificaciones:

Ventana de terminal
psql $DATABASE_URL -c "SELECT u.email, om.role FROM \"OrganizationMember\" om JOIN \"User\" u ON om.\"userId\" = u.id WHERE om.\"organizationId\" = '{organization_id}' ORDER BY om.role;"

Resultados esperados:

  • ✅ Solo OWNER puede cambiar roles
  • ✅ Cambios se reflejan en BD y UI

Objetivo: Verificar que OWNER y ADMIN pueden remover.

Pasos:

  1. Como OWNER, remueve un miembro
  2. Verifica que usedSeats decrementa
  3. Inicia sesión como usuario removido
  4. Verifica pérdida de acceso a /team/{organizationId} (403)
  5. Verifica pérdida de acceso a cursos

Verificaciones:

Ventana de terminal
# Verificar usuario removido
psql $DATABASE_URL -c "SELECT * FROM \"OrganizationMember\" WHERE \"organizationId\" = '{organization_id}' AND \"userId\" = '{removed_user_id}';"
# Verificar usedSeats
psql $DATABASE_URL -c "SELECT \"usedSeats\" FROM \"Organization\" WHERE id = '{organization_id}';"

Resultados esperados:

  • ✅ OWNER y ADMIN pueden remover
  • usedSeats decrementa
  • ✅ Usuario pierde acceso
  • ✅ Registro eliminado

Objetivo: Verificar que platform admins pueden gestionar organizaciones.

Pasos:

  1. Inicia sesión como admin@talentbricks.ai
  2. Navega a /admin/organizations
  3. Usa filtros (nombre, subscription status)
  4. Haz clic en una organización
  5. Edita: cambia nombre o maxSeats
  6. Verifica actualización en BD

Resultados esperados:

  • ✅ Admin ve todas las organizaciones
  • ✅ Filtros funcionan
  • ✅ Admin puede editar
  • ✅ Analíticas correctas

Objetivo: Verificar que no se pueden exceder los seats.

Setup:

Ventana de terminal
psql $DATABASE_URL -c "UPDATE \"Organization\" SET \"maxSeats\" = 3 WHERE name = 'TalentBricks Corp';"

Pasos:

  1. Con 2 miembros actuales (owner + 1)
  2. Invita a 1 usuario → Debe funcionar (3/3)
  3. Intenta invitar otro → Debe fallar
  4. Verifica error: “No hay asientos disponibles”

Resultados esperados:

  • ✅ Invitación falla cuando usedSeats >= maxSeats
  • ✅ Mensaje de error claro
  • ✅ UI muestra contador de seats

Objetivo: Verificar que OWNER puede gestionar facturación.

Pasos:

  1. Como OWNER, navega a /team/{organizationId}/billing
  2. Verifica información mostrada (plan, seats, próxima facturación)
  3. Haz clic en “Gestionar en Stripe”
  4. Verifica apertura del portal
  1. Intenta acceder a /team/{organizationId}/billing
  2. Verifica denegación (403) u ocultamiento

Resultados esperados:

  • ✅ Solo OWNER puede acceder
  • ✅ Información correcta
  • ✅ Portal de Stripe funciona

Objetivo: Verificar que el acceso se revoca al expirar.

Setup:

Ventana de terminal
psql $DATABASE_URL -c "UPDATE \"Organization\" SET \"subscriptionStatus\" = 'past_due' WHERE name = 'TalentBricks Corp';"

Pasos:

  1. Como MEMBER, intenta acceder a curso
  2. Verifica denegación
  3. Verifica mensaje: “Problemas de pago”
  1. Verifica banner de advertencia
  2. Haz clic en “Actualizar método de pago”
Ventana de terminal
psql $DATABASE_URL -c "UPDATE \"Organization\" SET \"subscriptionStatus\" = 'active' WHERE name = 'TalentBricks Corp';"

Resultados esperados:

  • ✅ Acceso se revoca cuando != 'active'
  • ✅ Banner para OWNER
  • ✅ Acceso se restaura al reactivar

Ventana de terminal
psql $DATABASE_URL -c "UPDATE \"OrganizationInvitation\" SET \"expiresAt\" = NOW() - INTERVAL '1 day' WHERE email = 'test@example.com';"
  • Verifica mensaje “Invitación expirada”
  • OWNER puede reenviar
  • Invita a usuario existente
  • Verifica error
  • Envía dos invitaciones al mismo email
  • Verifica comportamiento
  • Intenta remover o cambiar rol del único OWNER
  • Verifica error: “Debe haber al menos un OWNER”

Cambio de Seats:

  • Modifica quantity en Stripe
  • Verifica actualización de maxSeats

Cancelación:

  • Cancela suscripción
  • Verifica subscriptionStatus = 'cancel_at_period_end'
  • Acceso persiste hasta fecha de fin

Pago Fallido:

  • Fuerza pago fallido
  • Verifica subscriptionStatus = 'past_due'
  • Email al OWNER

Ventana de terminal
psql $DATABASE_URL -c "
SELECT
o.id, o.name, o.\"maxSeats\", o.\"usedSeats\", o.\"subscriptionStatus\",
json_agg(json_build_object('email', u.email, 'role', om.role)) as members
FROM \"Organization\" o
LEFT JOIN \"OrganizationMember\" om ON o.id = om.\"organizationId\"
LEFT JOIN \"User\" u ON om.\"userId\" = u.id
WHERE o.name = 'TalentBricks Corp'
GROUP BY o.id;
"
Ventana de terminal
psql $DATABASE_URL -c "
SELECT
o.name as organization,
c.title as course,
u.email as assigned_by
FROM \"OrganizationEnrollment\" oe
JOIN \"Organization\" o ON oe.\"organizationId\" = o.id
JOIN \"Course\" c ON oe.\"courseId\" = c.id
JOIN \"User\" u ON oe.\"assignedById\" = u.id
ORDER BY oe.\"assignedAt\" DESC;
"
Ventana de terminal
psql $DATABASE_URL -c "DELETE FROM \"OrganizationInvitation\" WHERE \"organizationId\" IN (SELECT id FROM \"Organization\" WHERE name LIKE '%Test%');"
psql $DATABASE_URL -c "DELETE FROM \"OrganizationEnrollment\" WHERE \"organizationId\" IN (SELECT id FROM \"Organization\" WHERE name LIKE '%Test%');"
psql $DATABASE_URL -c "DELETE FROM \"OrganizationMember\" WHERE \"organizationId\" IN (SELECT id FROM \"Organization\" WHERE name LIKE '%Test%');"
psql $DATABASE_URL -c "DELETE FROM \"Organization\" WHERE name LIKE '%Test%';"

  • Platform admin puede ver todas las organizaciones
  • OWNER tiene acceso completo
  • ADMIN puede gestionar miembros y cursos
  • MEMBER solo ve cursos asignados
  • OWNER puede invitar
  • ADMIN puede invitar
  • MEMBER no puede invitar
  • Tokens únicos generados
  • Invitaciones expiran (7 días)
  • usedSeats incrementa/decrementa
  • No se puede exceder maxSeats
  • OWNER y ADMIN pueden asignar
  • Miembros acceden a cursos asignados
  • No-miembros no pueden acceder
  • Progreso se guarda correctamente
  • Solo OWNER ve facturación
  • Portal de Stripe funciona
  • Webhooks actualizan subscriptionStatus
  • Webhooks actualizan maxSeats
  • Acceso se revoca al expirar
  • Lista de organizaciones
  • Filtros funcionan
  • Edición funciona
  • Analíticas correctas

Ver la Guía Rápida - Troubleshooting para soluciones comunes.