2 Commits

Author SHA1 Message Date
Beldor 91112862a5 fix: los cuatro hallazgos reales de la revision con IA
Revisión con IA / ai-review (pull_request) Successful in 29s
- crearTurno verificaba disponibilidad y creaba el turno en dos operaciones
  sueltas: dos clientes podian pasar la verificacion a la vez y sobrevender el
  mismo horario. Ahora va todo en una transaccion, serializada por jefe con
  pg_advisory_xact_lock. slotEstaDisponible acepta el cliente de la transaccion.
  Probado contra un Postgres real: 5 reservas simultaneas del mismo slot con
  capacidad 1 dan 1 ok + 4 conflictos y una sola fila; sacando el lock, entran
  las 5.
- La deduplicacion del webhook estaba en memoria y solo servia con una
  instancia. Pasa a la base con el modelo MensajeWhatsappProcesado: el insert
  del id es atomico por el indice unico, asi que aguanta reintentos
  concurrentes de Meta (verificado). Se limpian los ids de mas de 7 dias.
- postMensaje no reintentaba: ahora reintenta 3 veces ante 429, 5xx y fallas
  de red, con backoff exponencial y jitter. Un 4xx nuestro no se reintenta.
- /api/cliente/servicios devolvia los trabajos de un jefe dado de baja; ahora
  responde 404 si el jefe no existe o no esta activo.

test:envio suma los casos de reintento (35 asserts). El Prisma en memoria del
test del bot ahora entiende $transaction y $executeRaw.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 11:21:35 -03:00
jpbeldomenico 15d6e8a2ee feat(whatsapp): webhook + envio por Graph API (F0)
Ultima fase del bot de reservas: conecta la maquina de conversacion ya
existente (whatsapp-bot.ts) con la WhatsApp Business Cloud API.

- src/lib/whatsapp.ts: traduce RespuestaBot -> payloads de Meta (texto e
  interactive/button, con los limites de 3 botones / 20 chars / 4096 chars),
  aplana el payload del webhook y valida X-Hub-Signature-256 en tiempo
  constante.
- src/app/api/whatsapp/webhook/route.ts: GET de verificacion y POST de
  mensajes. Valida la firma sobre el cuerpo crudo, deduplica por message id
  (Meta reintenta) y siempre devuelve 200 para no entrar en loop de retries.
- scripts/test-whatsapp-envio.ts (npm run test:envio): 30 asserts sobre la
  capa Meta con fetch stubbeado, sin DB ni credenciales.
- docs/whatsapp.md con el alta en el panel de Meta y las 4 env vars.

Falta solo cargar las credenciales de Meta en el .env de produccion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 09:55:47 -03:00