← Volver al catálogo

📦 Recordatorio de reparto por voz

Archivo: /Users/user/rifai-agents/agentes/voice/voice-delivery-reminder.ts · Plist: ninguno (no existe com.rifai.voice-delivery-reminder.plist ni en cron/ ni en ~/Library/LaunchAgents/) · Horario: no programado actualmente. El comentario de cabecera dice "cron cada 1h", pero no hay plist cargado, así que hoy solo corre si se ejecuta a mano. Como el resto, solo llamaría dentro de 10:00–22:00 Madrid y nunca en domingo.

Qué hace

Llama a los clientes cuyo pedido COD está EN REPARTO con GLS (estado out_for_delivery) para recordarles que tengan el efectivo exacto preparado, mantengan el teléfono encendido, dejen quien lo reciba si no están, y no rechacen el paquete sin abrirlo. No es una venta: es un recordatorio amable de máximo 60–90s con un guion propio (persona "Cristina"). Reduce paquetes rechazados/devueltos en contra reembolso. Deja de llamar cuando el pedido pasa a entregado/cancelado y respeta un mínimo de 3h entre llamadas al mismo pedido.

Cómo funciona

1. Carga .env y comprueba ventana horaria (isCallableNow()).

2. Abre/crea la tabla delivery_reminders en data/voice-calls.db (registro propio de recordatorios, separado de calls).

3. Pide a Shopify los pedidos fulfillment_status=shipped de los últimos 14 días (máx 100) con sus fulfillments.

4. Filtra: descarta entregados/cancelados/rechazados; se queda con COD; exige tracking_number; exige shipment_status === 'out_for_delivery' (o tag en_reparto/out_for_delivery).

5. Por candidato: salta si fue llamado hace menos de 3h (lastReminderAt); extrae teléfono; prepara variables en español.

6. Construye un system prompt y un firstMessage específicos del recordatorio (guion de la persona "Cristina") y lanza la llamada con createOutboundCall pasando systemPromptOverride, firstMessageOverride y extraMetadata (tracking, call_type=delivery_reminder, gls_status).

7. Guarda la llamada en delivery_reminders. Throttle 2s. Imprime 📊 N llamadas lanzadas · M saltadas.

> ⚠️ Nota de código: usa phone.ok / phone.number, pero extractPhoneFromOrder en lib/phone-normalizer.ts devuelve string | null, no un objeto {ok, number}. Tal cual está, la condición fallaría/lanzaría en tiempo de ejecución. Probablemente es la razón por la que aún no tiene plist (pendiente de arreglar antes de programarlo).

Datos/APIs

  • Shopify Admin REST (2024-10): pedidos enviados + fulfillments (tracking_number, shipment_status). Vars: SHOPIFY_STORE, SHOPIFY_ACCESS_TOKEN.
  • Vapi (lib/vapi-client.ts) con overrides de prompt. Vars: VAPI_API_KEY, VAPI_ASSISTANT_ID_COD_CONFIRM, VAPI_PHONE_NUMBER_ID.
  • GLS: indirecto — usa el shipment_status/tracking que Shopify guarda en el fulfillment (el estado real de GLS lo escriben otros crons de tracking en los tags/fulfillment).
  • SQLite data/voice-calls.db, tabla propia delivery_reminders (vía better-sqlite3 directo, no voice-db.ts).
  • Helpers: lib/phone-normalizer.ts, lib/spanish-converter.ts. No notifica Telegram.

Cómo probarlo

cd /Users/user/rifai-agents && npx tsx agentes/voice/voice-delivery-reminder.ts

Esperado: 📦 Voice Delivery Reminder ..., nº de pedidos enviados en 14d y nº de candidatos COD en reparto. Si no hay candidatos, termina en 📊 0 llamadas lanzadas. Fuera de horario sale con . OJO: con candidatos válidos lanza llamadas reales de pago. Antes de programarlo, validar el bug del teléfono descrito arriba.

Si se rompe / recuperar

No hay plist. Para programarlo (cada 1h) habría que crear com.rifai.voice-delivery-reminder.plist con StartInterval 3600, copiarlo a ~/Library/LaunchAgents/ y:

launchctl load ~/Library/LaunchAgents/com.rifai.voice-delivery-reminder.plist

Logs sugeridos: /Users/user/rifai-agents/logs/voice-delivery-reminder.log (definir StandardOutPath/StandardErrorPath en el plist). Mientras no exista plist, solo corre manualmente.

Cómo replicarlo

  • Carga .env estándar.
  • Lectura Shopify de pedidos enviados + fulfillments, filtro COD + out_for_delivery.
  • Cliente Vapi con soporte de systemPromptOverride/firstMessageOverride/extraMetadata (ya soportado en vapi-client.ts).
  • Guion de la persona "Cristina" (system prompt + firstMessage).
  • Normalizador de teléfono (corregir el contrato string|null vs {ok,number}) + conversor español + ventana horaria.
  • SQLite con tabla delivery_reminders para anti-spam (mín 3h entre llamadas).
  • Plist launchd StartInterval 3600 (a crear).