Reglas de negocio
La fuente oficial de cómo funciona Royal Clean dentro del sistema.
Este documento es la fuente oficial. Si el código y este documento se contradicen, uno de los dos tiene un error y hay que resolverlo, no ignorarlo.
Las reglas sin confirmar están en PENDING_BUSINESS_RULES.md.
1. Propiedades y servicios
Una propiedad es permanente. Un servicio es una limpieza concreta.
Villa Tamarindo #3 existe siempre; sus limpiezas del 1, el 8 y el 15 de septiembre son tres registros históricos independientes. La propiedad acumula cientos de servicios a lo largo del tiempo.
- Toda propiedad pertenece a un cliente.
- Todo servicio pertenece a una propiedad.
- Los servicios se crean manualmente. No hay recurrencias automáticas.
2. Estados del servicio
DRAFT ──→ ASSIGNED ──→ IN_PROGRESS ──→ COMPLETED
│ │ │ │
│ │ │ └──→ IN_PROGRESS (retomar trabajo)
└───────────┴──────────────┴──→ CANCELLEDTransiciones permitidas y sus condiciones:
| Desde | Hacia | Quién | Condiciones |
|---|---|---|---|
DRAFT | ASSIGNED | ADMIN | Al menos un empleado asignado |
ASSIGNED | DRAFT | ADMIN | — |
ASSIGNED | IN_PROGRESS | Empleado | Tiene empleados y tareas |
IN_PROGRESS | COMPLETED | Empleado | Todas las tareas completas, con evidencia, sin sesiones abiertas |
COMPLETED | IN_PROGRESS | Empleado | «Retomar trabajo» |
| Cualquiera activo | CANCELLED | ADMIN | Con motivo escrito |
CANCELLED es terminal absoluto. Un servicio completado no puede
cancelarse: primero habría que retomarlo.
Implementado en
src/modules/services/status-machine.ts.
Toda transición pasa por ahí, incluido arrastrar una tarjeta en el Kanban.
3. Tareas: la plantilla y el snapshot
Cada propiedad tiene una plantilla de tareas editable. Al crear un servicio, las tareas se copian a registros propios de ese servicio.
La plantilla de Villa Tamarindo dice «Limpiar cocina». Se crea el servicio #422, que copia esa tarea. Mañana la plantilla cambia a «Limpiar y desinfectar cocina». El servicio #422 sigue diciendo «Limpiar cocina».
Esto no es un detalle técnico: es la garantía de que un reporte de hace seis meses describe lo que realmente se pidió aquel día.
- Todas las tareas configuradas son obligatorias. No hay tareas opcionales.
- Un administrador puede añadir, editar o eliminar tareas de un servicio concreto sin tocar la plantilla.
- Una tarea ya completada no se elimina en silencio: hay que reabrirla primero.
4. Evidencia fotográfica
Una tarea no puede completarse sin al menos una fotografía «después».
- Evidencia BEFORE: 0 o más, opcional.
- Evidencia AFTER: 1 o más, obligatoria.
La validación es del servidor, dentro de la transacción que completa la tarea. La interfaz deshabilita el botón y explica por qué, pero no es la autoridad.
Sólo cuenta la evidencia en estado CONFIRMED, es decir, aquella cuyo objeto se
verificó en el almacenamiento. Una subida a medias deja la tarea incompleta,
que es lo correcto.
5. Tiempo de trabajo
No existe ningún contador acumulativo. El tiempo se deriva de las sesiones.
Sesión A: 08:00 – 11:00 = 3 h
Sesión B: 11:10 – 11:30 = 20 min
───────
Total: 3 h 20 min- Iniciar un servicio abre una
WorkSession. - Finalizar la participación la cierra.
- Retomar el trabajo abre una sesión NUEVA. El tiempo previo nunca se pierde ni se reinicia. La acción se llama «Retomar trabajo», nunca «Reiniciar».
- Un empleado no puede tener dos sesiones abiertas a la vez. Lo impide un índice único en la base de datos, no sólo la aplicación.
Servicios olvidados abiertos
Si una sesión supera el umbral configurado (6 horas por defecto), el servicio se
marca con hasTimeWarning y aparece destacado en el panel.
El sistema nunca inventa una hora de finalización. Un administrador corrige el horario a mano, con motivo obligatorio, y queda auditado.
Varios empleados
Cada empleado tiene sus propias sesiones y cobra sus horas con su propia tarifa. Nunca se usa una duración global del servicio para pagar a varios.
Para finalizar un servicio, todas las participaciones deben estar cerradas. Cada persona cierra la suya con «Finalizar mi participación»; quien cierre el servicio cierra la propia en el mismo acto.
6. Tarifas y nómina
Resolución de la tarifa
tarifa = empleado.hourlyRateOverride ?? configuración.defaultHourlyRateCongelado
La tarifa se congela al asignar el empleado al servicio. Un aumento posterior no recalcula el pasado.
En agosto María cobraba ₡5.000/h. En octubre pasa a ₡5.500/h. Los servicios de agosto se siguen pagando a ₡5.000/h.
Cálculo
costo = redondeo(tarifa_congelada × minutos_facturables ÷ 60)El redondeo se aplica por servicio, no sobre el total del período, para que el desglose siempre sume exactamente el total mostrado.
La política de redondeo por defecto es EXACT (tiempo exacto). Es configurable
y está pendiente de confirmación por parte de Royal Clean.
Pagos
La aplicación no transfiere dinero. Calcula, desglosa y registra que un pago se realizó fuera del sistema.
Al marcar un período como pagado se congela el desglose completo en
PayrollPaymentItem: fecha, propiedad, minutos, tarifa e importe de cada
servicio. Si más adelante se corrigen horas, el recibo emitido no cambia.
Detalle en PAYROLL.md.
7. Precios y rentabilidad
- Cada propiedad tiene un
defaultServicePrice. - Cada servicio copia ese precio como
basePriceal crearse. - Cambiar el precio de la propiedad no modifica servicios existentes.
- Un administrador puede ajustar el precio de un servicio concreto; queda auditado aparte.
Ingresos = precio base + insumos cobrados (sólo los aprobados)
Costos = costo laboral + costo interno de insumos
Margen = Ingresos − CostosCuando falta un costo interno, la rentabilidad se marca como parcial y se dice por qué. Nunca se asume que un costo desconocido vale cero.
8. Insumos
Royal Clean repone productos durante un servicio (café, papel, jabón, amenidades) y puede cobrarlos al cliente.
- Un administrador registra insumos con costo interno y precio de cobro.
- Si la configuración lo permite, el personal también puede registrarlos, pero
quedan en
PENDING_REVIEWy no cuentan en las cifras hasta que un administrador los aprueba. - El personal nunca ve costos ni márgenes de los insumos.
9. Incidentes
El personal reporta lo que encuentra: daños, objetos faltantes, suciedad excesiva, problemas de acceso, problemas con insumos u otros.
- Puede adjuntar fotografías.
- Un incidente marca el servicio con
hasIncident. - Un administrador lo revisa y lo resuelve con una nota.
- Al resolverlo, quien lo reportó recibe una notificación. Cerrar el círculo es lo que hace que la gente siga reportando.
10. Cancelaciones
Sólo un administrador cancela, y siempre con motivo escrito. Los empleados asignados reciben un aviso.
Si ya había tiempo trabajado, el servicio queda marcado con
requiresAdminReview: ese trabajo se hizo y hay que decidir qué hacer con él.
El sistema no lo descarta por su cuenta.
11. Archivado
Nada se borra. Archivar es marcar archivedAt.
- Cliente archivado: se archivan también sus propiedades.
- Propiedad archivada: no admite servicios nuevos; su historial permanece. No se puede archivar con un servicio en progreso.
- Empleado desactivado: pierde el acceso de inmediato y no recibe asignaciones nuevas. Conserva servicios, horas, nómina y auditoría. No se puede desactivar con trabajo en curso.
12. Moneda
El colón costarricense es la moneda oficial de cálculo. Todo importe se almacena como entero de céntimos.
El dólar aparece como equivalente informativo, calculado con un tipo de cambio que un administrador fija a mano. No se guarda ningún histórico en USD ni se depende de ningún servicio externo de cotización.
13. Retención de evidencia
Por defecto, 12 meses. Al expirar:
- Se elimina el objeto del almacenamiento.
- La metadata se marca como
EXPIRED. - El historial del servicio se conserva íntegro.
El plazo es configurable.
14. Lo que el personal de campo nunca ve
- Su tarifa por hora
- Lo que gana
- El precio cobrado al cliente
- Costos internos y márgenes
- Otros empleados, salvo sus compañeros en un servicio compartido
- Propiedades a las que no está asignado
15. Reporte para el cliente
El PDF incluye la marca de Royal Clean, los datos del servicio, las tareas realizadas con sus fotografías, los incidentes relevantes, los insumos repuestos y el precio del servicio.
No incluye tarifas, salarios, costo laboral, costos internos ni márgenes. Hay un test que lo comprueba buscando esos valores en los datos del reporte.