Royal Clean CRM · Documentación
Negocio

Reportes

El PDF que se entrega al cliente y qué nunca aparece en él.

Hay dos clases de reporte, con audiencias opuestas.

1. Reportes internos

Sólo para administración. Muestran todo, incluidos costos y márgenes.

PantallaQué responde
Panel (/admin)¿Cómo va hoy? ¿Y el mes?
Detalle de servicio¿Qué se hizo, quién, cuánto tiempo, cuánto dejó?
Ficha de propiedad¿Es rentable esta propiedad?
Ficha de cliente¿Cuánto factura este cliente?
Ficha de empleado¿Cuántas horas y cuánto se le debe?
Reportes (/admin/reportes)¿Qué propiedades y clientes dejan más margen?
Pagos¿Qué hay que pagar y qué ya se pagó?

Rentabilidad

Ingresos = precio base + insumos cobrados (sólo aprobados)
Costos   = costo laboral + costo interno de insumos
Margen   = Ingresos − Costos
Margen % = Margen ÷ Ingresos × 100

Todo el cálculo está en src/modules/finance/calculations.ts, con tests.

Cifras parciales. Cuando falta un costo interno, el resultado se marca como parcial y se explica por qué:

«2 insumos no tienen costo interno registrado.»

Nunca se asume que un costo desconocido vale cero. Presentar un margen inflado como si fuera exacto sería peor que no presentarlo.

El margen es null, no cero, cuando los ingresos son cero: un margen sobre cero no está definido y mostrar «0 %» sería una afirmación falsa.

Línea de tiempo

El detalle de servicio muestra una línea de tiempo derivada del registro de auditoría, no de una tabla de eventos paralela. Duplicar el historial garantizaría que algún día las dos versiones se contradigan.

09:58  Trabajo iniciado          María
10:17  Tarea completada          María · Limpiar cocina
10:52  Incidente reportado       María
11:40  Servicio completado       María
12:15  Horario corregido         admin
       «La empleada olvidó finalizar el servicio.»

2. Reporte PDF para el cliente

Documento profesional pensado para compartir por correo o WhatsApp.

Qué incluye

  • Marca, dirección y contacto de Royal Clean
  • Cliente, propiedad y dirección
  • Fecha, hora programada, horario real y duración
  • Personal que atendió
  • Cada tarea realizada, con sus fotografías antes y después
  • Notas del personal
  • Incidentes relevantes
  • Insumos repuestos, con lo que se cobra por ellos
  • Precio del servicio
  • Sello «SERVICIO COMPLETADO»

Qué NO incluye

  • Tarifas por hora
  • Salarios ni costo laboral
  • Costos internos de insumos
  • Márgenes ni rentabilidad
  • Notas administrativas
  • Cualquier dato de otros clientes

Esto no se deja a la disciplina de quien programe: hay un test que lo comprueba. Se crea un servicio con una tarifa distintiva (₡7.777/h) y un costo interno distintivo (₡1.804), se generan los datos del reporte y se verifica que esos números no aparecen por ninguna parte (tests/integration/service-report.test.ts).

Imágenes incrustadas

El servidor descarga las fotografías de R2 y las incrusta en el PDF como datos.

La alternativa —enlazar a URLs firmadas— produciría un documento que deja de funcionar en cuanto expira la firma. Un reporte que el cliente abre tres días después mostraría huecos. Incrustar hace el documento autosuficiente.

Se incrustan hasta 4 fotografías por tarea para acotar el tamaño. Una imagen que no se puede recuperar se omite en lugar de romper la generación: es preferible un reporte con una foto menos que ningún reporte.

Generación

GET /api/reportes/servicio/{id}

Sólo ADMIN. Se genera bajo demanda y no se almacena (ver DECISIONS.md DEC-010).

Cada generación incrementa reportVersion y anota reportGeneratedAt, con una entrada de auditoría, para poder trazar cuántas veces se emitió un reporte y cuándo.

El PDF se sirve con Content-Disposition: inline, así que se abre en el navegador: el administrador lo revisa antes de decidir si lo comparte.

Paginación

Un servicio con muchas tareas ocupa varias páginas. Cada tarea se marca con wrap={false} para que no se parta por la mitad, y el pie repite «Página X de Y» en todas.

Hay un test con 25 tareas que verifica que el documento tiene más de una página, es decir, que el contenido se reparte en lugar de recortarse.

Tipografía

Se usan las fuentes estándar de PDF (Helvetica), disponibles en todos los lectores sin incrustar nada. Mantiene el archivo pequeño y elimina cualquier dependencia de red durante la generación.

Filtros por rango de fechas

Pagos y Reportes ofrecen atajos —hoy, esta semana, este mes, últimos 30 días— y un rango libre.

No se asume una quincena fija: Royal Clean todavía no ha confirmado su ciclo de pago (PENDING_BUSINESS_RULES.md #1).

Rendimiento

  • Ningún listado descarga imágenes a resolución completa: las miniaturas se cargan de forma diferida y sólo las visibles.
  • Todos los listados están paginados.
  • Las agregaciones financieras se calculan en el servidor, dentro de un Suspense propio, para que la parte operativa de la página aparezca antes.

On this page