Ir al contenido

Plantel

Plantel es el módulo donde el cuerpo técnico mantiene la lista de atletas de la organización: alta y edición, foto, equipo, número, estado deportivo, historial de lesiones e invitación al portal del jugador. Es el punto de entrada del resto del sistema — sin un jugador cargado acá, ningún otro módulo lo ve. Lo usan principalmente HoP y Director Deportivo; el resto del staff lee y edita lo de su área desde el perfil individual.

  • Problema que resuelve: unificar en un único lugar el master del plantel que normalmente vive en planillas sueltas (Excel del PF, contactos del médico, fotos en WhatsApp del utilero).
  • Casos de uso típicos: alta del plantel a inicio de temporada, bajas y altas a mitad de año, transferencias entre sub-equipos (primer equipo / reserva / juveniles), invitación masiva al portal del jugador.
  • Planes que lo incluyen: todos. El plan esencial limita el plantel a 40 atletas; pro y enterprise son ilimitados. Ver Planes y features.
  • Diferenciador: [NEEDS_USER: PRODUCT_DECISION posicionamiento vs competencia].

Todos los roles del staff ven Plantel y pueden abrir el perfil individual de un jugador. Lo que cambia entre roles es qué sub-pestañas del perfil ven y qué acciones tienen habilitadas:

  • hop / dir: todo. Alta, edición, foto, transferencia entre equipos, eliminación y restauración en bulk, invitación al portal, configuración de tabs visibles desde Settings.
  • med / rtp: además de los roles base, pueden cambiar el estado deportivo de un jugador (disponible / lesionado / recuperación / suspendido / inactivo).
  • sc / ss / fisio / nut / psi: lectura del plantel, escritura acotada a su área dentro del perfil individual.

Ver el detalle por rol en Roles del staff.

Las tabs del perfil del jugador (general, tactico, fisico, medica, mental, mensajes) se filtran adicionalmente por la configuración organizations.visible_player_tabs que define la org en Settings.

  • Alta de un jugador: Plantel → “Agregar jugador” → completar nombre, posición, dorsal, fecha de nacimiento, equipo. El dorsal se valida contra conflictos dentro del mismo team_id (jugadores inactive no bloquean). [NEEDS_USER: SCREENSHOT].
  • Cargar foto: desde el perfil del jugador, panel izquierdo → subir JPG, PNG o WebP de hasta 10 MB. Las URLs de scrapers (Sofascore, Transfermarkt, etc.) están bloqueadas por un CHECK constraint en players.photo_url.
  • Cambiar estado deportivo: desde la grilla o el perfil → selector de estado. El cambio queda registrado en player_status_history y la fecha del último cambio se muestra en la grilla. Solo hop, dir, med y rtp pueden hacerlo.
  • Eliminar / restaurar en bulk: seleccionar varios jugadores desde la grilla → eliminar (soft delete: pasa a inactive y cierra sus lesiones activas) o restaurar (vuelve a available). Máximo 100 por operación. Solo hop y dir. [NEEDS_USER] screenshot de la vista de inactivos.
  • Transferir entre equipos: modal de multi-transferencia, mueve un set de jugadores a otro team_id de la misma org.
  • Invitar al portal (individual, legacy): perfil → “Invitar” → el sistema genera un link via auth.admin.generateLink y lo envía con Resend al email del jugador.
  • Onboarding masivo (recomendado): la baja masiva del plantel al portal se hace desde el Onboarding link grupal, no desde Plantel. Requiere que el email del jugador esté pre-cargado en players.email por el cuerpo técnico.
  • Sub-equipos: Settings → Equipos define los teams que aparecen al asignar un jugador. El plan esencial permite hasta 2 sub-equipos.
  • Tabs visibles en el perfil: Settings → Tabs visibles ajusta organizations.visible_player_tabs. Un club que no usa psicología puede ocultar la tab mental para todo el staff.
  • Colores y logo: branding de la org (primary_color, secondary_color, logo_url) — no es exclusivo de Plantel pero el módulo lo respeta. Ver Settings.
  • Dorsal repetido: dos jugadores pueden compartir dorsal si están en sub-equipos distintos. Dentro del mismo team_id, un jugador inactive no bloquea el alta de otro con el mismo número.
  • Eliminar borra datos históricos: no. La “eliminación” es soft delete (status = 'inactive') y se puede revertir. Las lesiones activas del jugador se cierran automáticamente con fecha del día para no quedar huérfanas en Médico.
  • Cambio de email del jugador: [NEEDS_USER: PRODUCT_DECISION flujo recomendado cuando el jugador ya activó su portal.

Player surface: N/A. Plantel es un módulo administrativo solo del staff. El jugador no ve esta pantalla. Lo más cercano desde su portal es /player/perfil, donde lee sus datos personales pero no gestiona la lista del plantel ni edita su propio estado deportivo.

Plantel es un módulo CRUD — no calcula métricas propias. Las métricas que se muestran en el perfil (ACWR, %MD, Hooper, riesgo) son agregados consumidos desde otros módulos. Para fórmulas, ver el Glosario y las páginas de Carga, Riesgo y Wellness.

  • players — fila por atleta. Campos clave: full_name, preferred_name, position, jersey_number, status, photo_url (con CHECK anti-scrapers), team_id, email, auth_user_id, wellness_token, last_wellness_score, current_acwr, onboarding_consumed_at, organization_id.
  • teams — sub-equipos dentro de una org (name, category, sort_order).
  • player_status_history — log de cambios de status por jugador. Alimenta la fecha “último cambio” en la grilla.
  • injuries — historial de lesiones del jugador (consumido por Médico y Fisio, escrito también desde Plantel al cerrar un jugador eliminado).
  • Storage bucket player-photos — fotos subidas por el staff con upsert por ${playerId}.${ext} y cache-bust por querystring ?v={timestamp}.

Plantel es la fuente de verdad de la lista de atletas, así que prácticamente todos los módulos lo consumen:

  • Calendario — convocatorias y ausencias apuntan a player_id.
  • Wellnesswellness_token y wellness_entries por jugador.
  • Cargagps_player_data se asocia por jugador; ACWR y %MD por jugador.
  • Riesgorisk_snapshots diarios.
  • Fisio y Médico — lesiones, consultas, sesiones de fisio, fases de RTP.
  • Nutrición y Psicología — registros y targets por jugador.
  • Rendimiento — stats de partido y análisis táctico.
  • Mensajería — chat staff ↔ jugador, push notifications.
  • Usuarios — link grupal de self-onboarding que da acceso al portal /player.
  • Resend — emails de invitación individual (invitePlayer). Si RESEND_API_KEY no está configurada, la invitación falla silenciosamente.
  • Supabase Storage — bucket player-photos para fotos del plantel, escrito con service-role.
  • Supabase Authauth.admin.generateLink para invitar al portal del jugador.
  • Export Excel del plantel: prometido en planes pro y enterprise (feature flag excel_export) pero no está implementado. Solo existe importación. Ver Planes.
  • Bug #10 — linkeo del jugador post-onboarding: reportes anecdóticos de jugadores que completan el onboarding masivo pero quedan sin auth_user_id ligado. Sin repro reproducible; investigar caso a caso.
  • Cambio de organización de un jugador: no soportado. La transferencia entre team_id funciona solo dentro de la misma org.
  • Hard delete: no existe en la UI. El soft delete via status = 'inactive' es la única vía y es deliberada (preserva historial de carga, lesiones e informes).
  • Wellness links legacy: el wellness_token por jugador sigue generándose por trigger de DB para retrocompatibilidad de Nacional. Para clubes nuevos, el flujo recomendado es PWA + push.