Royal Clean CRM · Documentación
Operación

Diagnóstico

Síntomas concretos, su causa habitual y cómo confirmarla.

Desarrollo

Variables de entorno inválidas o faltantes

Falta .env o alguna variable obligatoria.

cp .env.example .env

AUTH_SECRET necesita al menos 32 caracteres:

openssl rand -base64 48

Can't reach database server at localhost:5433

PostgreSQL no está levantado.

docker compose up -d
docker compose ps

El puerto es 5433, no 5432, para no chocar con una instalación local de PostgreSQL. Si cambiaste el puerto, ajusta DATABASE_URL.

Cannot find module '@/generated/prisma/client'

El cliente de Prisma no está generado. Se genera en postinstall y en build, pero si borraste src/generated:

pnpm exec prisma generate

El cronómetro no avanza

Comprueba que el servicio está IN_PROGRESS y que el empleado tiene una sesión abierta. El cronómetro sólo corre para quien está trabajando.

Las fotos no suben en desarrollo

MinIO no está corriendo o el bucket no existe:

docker compose up -d
docker compose logs storage-init

Debe decir «Bucket royal-clean-evidence listo y privado». Consola web en http://localhost:9001 (royalclean / royalclean_dev_secret).

This module cannot be imported from a Client Component

Un componente cliente está importando un módulo server-only. Suele pasar con las etiquetas: modules/audit/service.ts es server-only, pero modules/audit/labels.ts no. Importa desde el módulo compartido.

Los tests de integración no encuentran la base

Falta crearla:

docker compose exec db psql -U royalclean -d postgres -c "CREATE DATABASE royalclean_test OWNER royalclean;"

El servidor de desarrollo se queda colgado

Ocurre tras suspender el equipo o dejarlo mucho tiempo inactivo. Reinícialo:

pnpm dev

Si el puerto sigue ocupado, localiza el proceso que escucha en el 3000 y termínalo antes de volver a arrancar.


Producción

El contenedor no arranca

Mira los logs. Las causas habituales, en orden:

1. Fallo de migración.

Error: P3009 migrate found failed migrations

Una migración anterior quedó a medias. Revisa la tabla _prisma_migrations, corrige el estado y despliega de nuevo. Si la base quedó inconsistente, restaura el respaldo (OPERATIONS.md).

2. Variable faltante.

Variables de entorno inválidas o faltantes:
  - AUTH_SECRET: ...

Revisa la configuración en Dokploy.

3. Base de datos inalcanzable.

Can't reach database server

El DATABASE_URL debe usar el host interno de Docker (el nombre del servicio), no localhost ni una IP pública.

exec ./entrypoint.sh: no such file or directory

El script tiene finales de línea CRLF. El Dockerfile ya los normaliza y .gitattributes fuerza LF, así que esto sólo pasa si el archivo se copió sin pasar por git. Reconstruye la imagen.

El healthcheck falla pero la app responde

/api/health verifica la aplicación y la base de datos. Un 503 significa que la aplicación vive pero no alcanza PostgreSQL.

docker ps
docker logs royalclean-db

Las fotos no cargan en producción

Comprueba las variables de R2. Si faltan, la aplicación arranca igual pero la evidencia falla con un mensaje claro.

Comprueba el token. Necesita Object Read & Write sobre el bucket.

Comprueba el bucket. Debe existir y llamarse igual que R2_BUCKET_NAME.

Si una imagen concreta devuelve 410, esa evidencia expiró por retención o fue eliminada: es el comportamiento esperado.

Failed to fetch Inter from Google Fonts al construir

No debería ocurrir: el proyecto usa la pila de fuentes del sistema precisamente para no depender de esa red (DECISIONS.md DEC-015). Si aparece, alguien reintrodujo next/font/google.

El despliegue tarda mucho

El primer build compila todo. Los siguientes aprovechan la caché de capas siempre que package.json y pnpm-lock.yaml no cambien.


Datos

«El empleado dice que trabajó más horas»

Revisa Servicios → (servicio) → Tiempos. Verás cada sesión con su inicio y su fin.

Causas frecuentes:

  • Olvidó pulsar «Iniciar servicio» al llegar.
  • Olvidó finalizar y la sesión quedó abierta (aparece la alerta de tiempo).
  • Retomó el trabajo y no cuenta la segunda sesión.

Corrige con Corregir, indicando el motivo. Queda auditado.

«El margen de este servicio parece muy alto»

Probablemente falten costos internos de insumos. Cuando ocurre, el sistema lo dice explícitamente: «2 insumos no tienen costo interno registrado».

El sistema nunca asume que un costo desconocido vale cero. Registra los costos y la cifra dejará de ser parcial.

«Cambié la tarifa y los servicios viejos no cambiaron»

Es el comportamiento correcto. La tarifa se congela al asignar (BUSINESS_RULES.md §6). Un servicio de agosto se paga a la tarifa de agosto.

Lo mismo vale para el precio de las propiedades y para las plantillas de tareas.

«Corregí unas horas y el pago no cambió»

También es correcto. Al registrar un pago, el desglose se congela: el recibo documenta lo que realmente se pagó.

El sistema avisa al corregir horas de un servicio ya liquidado y lo anota en auditoría. Si hay que ajustar el pago, revierte el pago y vuelve a registrarlo.

«Un empleado no puede iniciar un servicio»

Comprueba, en orden:

  1. ¿Está asignado a ese servicio?
  2. ¿El servicio está en ASSIGNED o IN_PROGRESS?
  3. ¿Tiene tareas definidas?
  4. ¿Tiene ya trabajo abierto en otro servicio? Sólo puede tener una sesión abierta a la vez; el mensaje lo indica.

«No puedo archivar una propiedad»

Tiene un servicio en progreso. Espera a que termine: archivarla dejaría a alguien trabajando en una propiedad que la aplicación considera inexistente.

«No puedo desactivar a un empleado»

Tiene trabajo en curso. Cierra su participación primero.


Acceso

«Usuario o contraseña incorrectos» con las credenciales correctas

El mensaje es único a propósito: no revela si el usuario existe. Comprueba:

  • ¿La cuenta está desactivada? En ese caso el mensaje sí es distinto.
  • ¿Superó el límite de intentos? 5 fallos por usuario en 15 minutos.
  • Restablece la contraseña desde Empleados.

«Demasiados intentos fallidos»

Rate limiting. Espera 15 minutos o restablece la contraseña, lo que también limpia los intentos previos.

«Debe cambiar su contraseña» y no puede salir de esa pantalla

Es lo esperado tras un restablecimiento. Debe elegir una contraseña propia para continuar.

Un empleado ve 404 en un servicio que sí existe

Correcto: no está asignado. El sistema devuelve 404 en lugar de 403 para no confirmar que el recurso existe (AUTHORIZATION.md).


Cómo pedir ayuda

Al reportar un problema, incluye:

  1. Qué intentabas hacer.
  2. Qué esperabas y qué pasó.
  3. El mensaje exacto.
  4. Rol del usuario e identificador del servicio si aplica.
  5. Los logs relevantes:
docker logs royalclean-app 2>&1 | tail -50

La auditoría (/admin/auditoria) suele responder «quién cambió qué y cuándo» sin necesidad de mirar logs.

On this page