Namespace KadicErp.WebApi.Controllers.Academy
Classes
- AcademicPeriodsController
Períodos académicos (decisiones del owner, 13/08/2026 — spec-periodo-academico): catálogo por Tenant+Sucursal (P6) con solapamiento permitido (P5). El listado con
branchIdalimenta el selector del wizard de inscripción y el filtro del hub; el CRUD es la pantalla de administración (Master Data), mismo molde que Disciplines.
- AcademyGendersController
Fase 2 (§2.1, 05/08/2026) —
core.Genderalcanzable desde ACADEMY para poblar el selector de género del wizard de alumno (antes 'M'/'F' hardcodeado en el front; ahora StudentProfile exige GenderId real). Mismo patrón que AcademyPaymentMethodsController.
- AcademyPaymentMethodsController
US#0 CA14 —
core.PaymentMethodsalcanzable desde el módulo ACADEMY. El único endpoint existente (GET api/sales/payment-methods) está tras[RequireModule("SALES")], inalcanzable para un tenant de academia sin Sales contratado. US#8/US#16 (registro de pago) dependen de este catálogo.
- AcademySettingsController
US#26 (#8977, corrección de modelo del 02/08/2026) — Branch Defaults Academy. Configuración por Branch de prorrateo, make-ups, reservas, capacidad y comisiones. Consumida internamente por US#6/US#7/US#12/US#13/US#14/US#20 vía IAcademyBranchDefaultsResolver, nunca directo a academy.AcademyBranch (CA7).
- AutomationsController
US#17 (#8497) — Automatización de envíos WhatsApp por eventos del sistema. Las 7 rutas son exactamente las que
automations.service.tsya construye.
- AvailabilitiesController
Catálogo global de días de la semana (decisión de David — "Availability debe ser una tabla donde se guarden Lunes, Martes...."). Solo lectura: son 7 filas fijas sembradas por migración, iguales para todos los tenants — sin CRUD, sin permisos propios (se gatea con el mismo permiso de lectura de Instructors, ya que su único consumidor hoy es el picker de disponibilidad del modal de Instructor).
- ClassScheduleController
US#32 (#8990) — catálogo, asignación y adherencia del Programa de Clases. Renombrado de
TrainingPlansControllerpor US#39 (US-105, #9070) CA1: el nombre técnico ahora coincide con el nombre de negocio "Programa de Clases" (branding UI "360", fuera del código, DA-01). El registro por clase vive en SessionsController (embebido en el roster de asistencia de US#7, no en pantalla propia).
- CollectionsController
US#8 (#8488) — Cobranza: deudores, pagos (parciales), planes y vista 360. Campos condicionados por permiso (
ncf, saldos de la 360) vannull, nunca se filtra la fila.
- CommissionsController
US#20 (#8500) — liquidación de comisiones de instructores. Calcular reconstruye las líneas Pending de un período abierto; liquidar marca como pagado; cerrar el período congela todo (CA4, siempre manual).
- CommunicationsController
US#10 (#8490) — Comunicaciones WhatsApp (plantillas + envío). Reusa la infraestructura de WhatsApp ya existente (
IModuleNotificationDispatcher) — no se agrega ningún cliente HTTP.
- DisciplinesController
US#1 (#8481) Task #8875, addendum 07/08/2026 — CRUD completo del catálogo de disciplinas. Separado de
ProgramsController(donde vivía como sub-recurso con solo Create+GetAll, reusando permisos de Programs) para tener permisos propios (Academy.Disciplines) y una pantalla de administración en Master Data → Catálogo.
- EnrollmentsController
US#6 (#8486) — inscripciones: wizard (Alumno→Grupo→Resumen) y hub. El importe sale siempre de
quote(GET, no persiste); el alta real vive enPOST /enrollments.
- ExerciseCatalogController
US#40 (US-106, #9071) — CRUD del catálogo reutilizable de ejercicios (tipo, distancia, tiempo objetivo y repeticiones), para no retipear el mismo ejercicio en cada Programa de Clases o en una sustitución ad-hoc. Baja lógica (
IsActive) vía el endpoint DELETE.
- FamiliesController
US#4 — familias: listado, ficha y estado de cuenta. US#5 (#8485) añade el alta atómica (POST /families, POST /families/{id}/students) — el resto de la frontera sigue vigente.
- FreezesController
US#13 (#8493) — Congelar inscripción. Las 3 rutas son exactamente las que
freezes.service.tsya construye — no se inventan rutas nuevas ni se cambia POST por PATCH.
- GroupsController
US#46 (US-201, #9077) — CRUD del Grupo (padre, patrón de días). Reemplaza el CRUD viejo que, desde US#35 (US-101), seguía apuntando a la composición Group+Section+SectionLevel para no romper el contrato plano congelado.
GetSchedule/CheckConflictsse mudaron aSectionsController(US#47, US-202) — siempre operaron sobre horario/conflictos de Sección, no de Grupo; vivían aquí solo porque US-202 no existía todavía.
- InstructorsController
US#25 — catálogo mínimo de instructores. Desbloquea US#3 (creación de grupos), que exige
instructorId. US#19 (#8499) enriquece el DTO, añade/agenday los campos ricos de alta/edición — mismo controlador, misma tabla, sin duplicar nada.
- LaneHistoryController
US#36 (US-102, #9067) CA5 — consulta del historial de carril usado por Sesión x Nivel, para trazabilidad histórica.
- LevelsController
US#2 — niveles del "camino del alumno" y su malla de habilidades. La regla dura del módulo:
SkillIdes inmutable, reordenar solo tocaOrder(CA3/CA6).
- MakeupsController
US#14 (#8494) — Make-ups (recuperación de clases). Los verbos siguen exactamente lo que
makeups.service.tsya construye:PATCHpara las acciones (a diferencia de US#13, que usaPOST) — se respeta lo declarado por cada servicio del front, no se homogeniza.
- OnboardingController
US#8989 (Academy US#31) — wizard de onboarding del tenant (5 pasos: Institución, Disciplinas, Modalidad, Configuración de cobro, Primer grupo). Corre una sola vez por tenant de Academia, la primera vez que el admin entra. Reemplaza el marcador
POST /api/academies/onboardingque vivía enEnrollmentsControllersin estado persistido ni pasos reales.
- ProgramsController
US#1 — catálogo de programas. Bloquea a US#3 (grupos) y US#6 (inscripciones).
- ProgressController
US#18 (#8498) — Progreso: matriz de habilidades, catálogo de ejercicios, bitácora de clases y certificados de nivel. Esta US no tenía servicio ni endpoints previos — el contrato completo se diseñó en la US misma.
- RelationshipsController
US#34 (#9050) — catálogo de parentesco (Padre, Madre, Tutor legal…), CRUD calcado de DisciplinesController.
- ReportsController
US#8502 — Galería de reportes operativos.
Viewda acceso al catálogo,Previewa la vista previa (máximo 50 filas, resuelta enGetReportPreviewHandler) yExporta la descarga completa en CSV/Excel/PDF.
- ResourcesController
US#11 (#8491, CA18/CA22) — árbol de recursos físicos por sede (Piscina → Carril). Sin ella, US#3 no detecta conflictos de recurso (CA6).
[RequireTenantBranch]aislamiento por sucursal; el aislamiento por sede (VenueId) lo resuelven los handlers vía tenant + pertenencia.
- SeatReservationsController
US#6 (#8486) Decisión 3 — apartar/liberar plaza (
academy.SeatReservation,Reason=PRE_ENROLLMENT). Comparte la entidad con US#13 (Reason=FREEZE).
- SectionInstructorsController
US#65 — asignación N:N Sección↔Instructor. Recurso propio, distinto de
SectionsController(CRUD de la Sección, ya no toca instructor) yInstructorsController(perfil/catálogo del instructor) — CA9/CA10 son instructor-céntricas, CA11 es group-céntrica, ninguna encaja 100% en los otros dos controladores.
- SectionsController
US#47 (US-202, #9078) — CRUD de la Sección (horario dentro de un Grupo) + sus
SectionLevel(nivel + carril por defecto), con detección de conflictos de horario/carril y validación de capacidad de carril ≤ capacidad de piscina.GetSchedule/CheckConflictsse mudan aquí desdeGroupsController(US#46 los había dejado ahí con el comentario "US-202, no tocar"): ya operaban sobreSection/SectionLeveldesde US#35 (US-101) — vivían mal ubicados bajo el Grupo.CheckConflictsse reemplaza porCheckSectionConflictsCommand, con granularidad real por Nivel/carril en vez delResourceIdúnico que exigía el contrato viejo de Grupo.
- SessionReportsController
US#20 (#8500) CA5 — reporte + aprobación de sesiones cerradas, la base de la elegibilidad de pago que
CalculateCommissionsHandlerconsulta.
- SessionsController
US#7 (#8487) — asistencia (roster diario). Contrato 100% nuevo: ninguna de estas rutas existía en el frontend antes de esta US.
- SpecialtiesController
Catálogo de especialidades de Instructor, por tenant (decisión de David — "Speciality debe ser un CATALOGO y aquí un DropDown que se alimente de ese catálogo"). Mismo molde que
DisciplinesController.
- StudentsController
US#5 — expediente completo del alumno: perfil, datos médicos, contactos de emergencia, autorizados a recoger y tarjeta de seguridad auditada. CA13: el alta con alumnos vive en FamiliesController (POST /families, POST /families/{id}/students), que es US#5, no US#4.
- TransfersController
US#12 (#8492) — Transferir alumno entre grupos. CA12: no hay flujo de aprobación,
POST /transfersejecuta de inmediato y es irreversible — la confirmación vive en el cliente.
- TutorTypesController
US#34 (#9050) — catálogo de tipo de tutor (Económico, Contacto de emergencia, Autorizado para recoger, Legal…), CRUD calcado de DisciplinesController.
- UpdateStudentBody
Fase 3 (12/08/2026) — dejó de traer Name/Birth/GenderId: se resuelven siempre desde el Business Partner vinculado del alumno, ya no son editables desde este endpoint.
- VenuesController
US#11 (#8491, CA16/CA22) — catálogo de Sedes (
academy.Venue), entidad propia con FK alBranchde core.[RequireTenantBranch]es obligatorio: una Venue cuelga siempre de la sucursal fiscal resuelta en el token, igual queRentCarBranchConfigController. Reemplaza al antiguoBranchesController, que exponíaAcademyBranchcomo si fuera la sede — no lo era (verDocs/Academy/DECISIONES-02-08-2026.md§1).
- WaitlistController
US#3 (#8483) — lista de espera por grupo.