El informe docente tiene SIETE ejes, no uno: implante/reconstructivo/protesis, edad, maxilar, numero de dientes y marca de implante - dictados en audio, nunca escritos
El cliente dicto las dimensiones del informe docente en un audio de WhatsApp del 3/9/2026 19:08 (PTT-20260903-WA0024, 37s) que nunca escribio por texto: el profe "puede ver la historia de cada alumno, de todo lo que hizo, y lo puede separar por lo que dijimos: implante, reconstructivo, protesis, edad de los pacientes, maxilar, numero de dientes, marca de implante". Siete ejes, no uno. El unico pedido escrito equivalente, del 30/8 11:31, dice solo "hay q poner q el docente PUEDA PONER EN LOS FILTROS los alumnos" - o sea que el pedido escrito es el PRIMERO de una lista de siete y quien leyo solo el export de texto vio un septimo del alcance. La transcripcion se hizo local con Whisper large-v3-turbo; el audio original y la cadena reconstruida completa estan en /data-venus/terra/client-communications/2026-09-05-whatsapp-chain-reconstruida.md. Falta contrastar cada eje contra lo que /informes ya filtra hoy antes de estimar nada: algunos ya existen. La palabra que el ASR dio como "prestaciones" es "practicas" por contexto.
Activity
-
Contraste de los siete ejes contra lo que /informes ya hace hoy, medido 2026-09-05 sobre src/lib/informe-query.ts y la base. CUATRO YA ESTAN: implante / reconstructivo / protesis salen del breakdown "Por modulo" (los tres son modulos, no una dimension aparte, asi que ese eje ya esta cubierto y no hay que construirlo), y marca de implante existe como filtro y como breakdown, con las cuatro marcas que el cliente nombro en el audio del 14/8 ya cargadas en lookupOptions: fia|FIA, implantsim|IMPLANTSIM, inspiral|INSPIRAL, nuvo|NUVO. TRES FALTAN: edad del paciente, maxilar y numero de dientes; no aparecen ni en FILTER_SQL ni en ningun breakdown. Lo que el cliente pidio en el audio es AGRUPAR, no filtrar: "lo puede separar por". Los pedidos de filtro son otros y son los escritos del 23/8 y del 30/8, y ya estan construidos. Asi que los tres ejes que faltan entran como breakdowns nuevos y FILTER_SQL no se toca: sigue con nueve parametros. De donde sale cada uno. Maxilar es piezasDentarias.arcada (superior/inferior), que se alcanza desde terraPracticasPiezasDentarias por codigoFdi - la tabla de la practica NO tiene arcada, solo practicaId, codigoFdi, createdAt, id, deletedAt. Numero de dientes es un histograma sobre un agregado por practica: hay que contar piezas por practica primero y recien despues agrupar por ese numero; es el unico de los tres que tiene dos niveles y no se puede copiar de campoBreakdown, que es de uno solo. Edad se calcula de vTerraPracticas.pacienteDob contra p.fecha, o sea la edad AL MOMENTO de la practica, no la de hoy. Restriccion que manda sobre el eje de edad: el encabezado del archivo dice, y es una decision deliberada, que ahi no se selecciona ningun paciente, ningun documento y ninguna fecha de nacimiento. La fecha de nacimiento no puede salir proyectada a una etiqueta; la edad se bucketea DENTRO del CTE y solo sale el bucket. Los buckets van gruesos a proposito: hoy hay 12 filas vivas en terraPracticasPiezasDentarias, y con esos volumenes un bucket fino con n=1 es un identificador en una pantalla que es agregada justamente para no serlo. Hay que ampliar el comentario del encabezado dejando escrita la excepcion y su limite.
-
Implementado y pusheado en 52d5e92 (codigo) y 6dc951a (bump de version). /informes ahora trae tres paneles nuevos: Edad del paciente, Maxilar y Cantidad de piezas. Con eso los siete ejes que el cliente dicto en el audio del 3/9 estan cubiertos: los tres tipos de practica ya salian en Por modulo, marca de implante ya existia, y estos tres eran los que faltaban. Son breakdowns, no filtros: el pedido del audio es separar, no filtrar, y los filtros que pidio por escrito son los nueve que FILTER_SQL ya sirve. Ese predicado y sus nueve parametros no se tocaron. Edad se calcula contra la fecha de la practica, no contra hoy, para que un informe del anio pasado no se reescriba solo en cada cumpleanios. Es lo unico en el archivo que lee pacienteDob, y como el encabezado dice que ahi no se lee ninguna fecha de nacimiento, la fecha se consume DENTRO del CTE, se bucketea ahi y solo sale el bucket. Los buckets van anchos a proposito - menos de 30, 30 a 49, 50 a 64, 65 o mas, mas "Sin fecha de nacimiento" - porque en una pantalla agregada un bucket con una sola practica es un identificador. El comentario del encabezado ahora deja escrita esa excepcion y su limite. Cantidad de piezas es el unico breakdown de dos niveles del archivo: primero se cuentan piezas por practica, despues se agrupan las practicas por ese numero. El join es LEFT porque una practica sin piezas cargadas es una respuesta real a "cuantos dientes" y descartarla inflaria todas las demas proporciones. Maxilar lee piezasDentarias.arcada por codigoFdi - la tabla del lado de la practica no tiene arcada propia - y cuenta practicas DISTINCT, asi que una con piezas en ambas arcadas cuenta una vez en cada una y no dos en una. Medido contra la base viva antes de pushear: 6 practicas, edad 3 y 3 en los dos buckets mas jovenes, arcada devuelve Superior con 5, y el histograma de piezas suma 6 con una practica sin ninguna. tsc --noEmit sale 0. Lo que NO esta ejercitado: no hay datos con arcada inferior ni con paciente de 50 o mas, asi que esas ramas estan escritas y no observadas.
-
Tres breakdowns nuevos en /informes: edad, maxilar y cantidad de piezas. 52d5e92 + 6dc951a.