Reportes
Los reportes de la consola web son Excel generados por un stored procedure. La buena noticia: agregar uno no requiere tocar el frontend.
Cómo funciona
- Una fila en
configuration.REPORTSconname,description,iconystoreProcedureName(esa columna no se serializa hacia afuera). - El SP vive en
migrations/finances/store/y recibe siempre la misma firma:CALL <sp>(startDate, endDate, userId). - Una fila en
configuration.REPORTUSERSpor cada usuario que puede verlo. services/v2/ReportService.tsresuelve, valida, ejecuta, arma el Excel y registra la ejecución.
Reportes actuales: sp_report_deliverys, sp_view_stocks_report, sp_view_stocks_serial_report.
Checklist para agregar uno
- Escribir el SP con la firma
(IN startDate DATETIME, IN endDate DATETIME, IN userId INT). -
INSERTenREPORTScon elstoreProcedureName. -
INSERTenREPORTUSERSpara los usuarios que lo necesitan. - Nada en el front.
Los dos gotchas que ya rompieron todo
REPORTUSERS es invisibleNo hay error ni log: get-types simplemente no lo lista, y find responde "el usuario no tiene
acceso al reporte".
Si te dicen "el reporte no aparece", empezá por acá antes de mirar el SP.
El front manda Date.toISOString() ("2026-07-01T03:00:00.000Z"), y los parámetros de los SPs están
declarados DATETIME. Con STRICT_TRANS_TABLES, MySQL rechaza el sufijo Z al asignar el
parámetro — o sea que el CALL explota antes de ejecutar el cuerpo, incluso en los SPs que ni
miran las fechas.
ReportService.normalizeDateParam() lo arregla: pasa la fecha por getMoment() y la reformatea; si
no parsea, devuelve un mensaje claro en vez de dejar que MySQL falle con un error opaco.
No bypasees ese normalizador.
Como bonus del segundo caso: CustomResponse.error(e) no llena message, así que
ReportController tiene un helper privado failure() que preserva el motivo real de MySQL/TypeORM
(por ejemplo Incorrect datetime value: …). Sin eso, el front recibía un body sin nada que mostrar e
inventaba un "Error de conexión" genérico.
No confundir con el otro ReportService
services/v1/ReportService.ts es otra cosa: un cliente axios (con cookie jar) contra un servicio
externo de reportes (REPORT_API_URL) que devuelve el PDF del remito. Nada que ver con el Excel.
Power BI
La pantalla de reportes también embebe dashboards de Power BI. La configuración vive en
powerBiTenantId (front) y POWER_BI_CLIENT_SECRET / CLIENT_ID / TENANT_ID (backend).