🚨 Vigilante de Envíos 17h
Archivo: /Users/user/rifai-agents/agentes/sec/vigilante-envios.ts · Plist: com.rifai.vigilante-envios · Horario: cada día a las 17:00 Madrid (StartCalendarInterval Hour 17, Minute 0). El script vuelve a comprobar que la hora de Madrid sea 17 salvo FORCE=1.
Qué hace
Cada día a las 17:00 lee en Shopify los pedidos creados desde la fecha de arranque (pizarra limpia desde 2026-06-04) y los clasifica por estado de envío: incidencias, sin enviar (+5d / 3-5d / 1-2d / hoy), en tránsito (estancados +7d / normales) y entregados hoy. Con eso compone un informe HTML y lo manda por Telegram. Pese a ser un agente del depto Secretario, el informe se envía al bot de Oscar (ops) porque los envíos son logística, no al bot de Sec.
Cómo funciona
1. Parsea .env y calcula la hora de Madrid. Gate: si no es FORCE=1 y la hora no es 17, sale.
2. Pide a Shopify orders.json?status=any&created_at_min=<CONTAR_DESDE>&limit=250 con los campos de fulfillment/tracking/cliente.
3. Para cada pedido (descartando cancelados, refunded y voided) calcula la antigüedad en días y extrae el tracking del primer fulfillment.
4. Clasifica con la lógica del nodo original:
deliveredToday→ entregadosHoy;delivered(no hoy) → se ignora.attempted_delivery/failure→ incidencias.unfulfilled/partial/sin estado → sinEnviar según edad (≥5 / ≥3 / ≥1 / hoy).fulfilledcon tracking → enTránsito; estancado si los días desde la última actualización del tracking ≥7, si no normal.
5. Ordena cada cubo por antigüedad/días en tránsito descendente.
6. Construye el mensaje HTML con secciones (solo las no vacías), formateando cada pedido (nombre, total, cliente, ciudad, edad y, donde aplica, número/empresa/estado de tracking) y añade el resumen "Total activos / entregados hoy". Si no hay nada: "Todo al día".
7. sendTelegram trocea el mensaje en partes ≤3900 caracteres (cortando por salto de línea) y las envía con parse_mode: HTML al bot de ops.
Datos/APIs
- Shopify Admin API (
2024-10):orders.jsonconstatus=anyycreated_at_min. Vars:SHOPIFY_STORE,SHOPIFY_ACCESS_TOKEN. - Telegram Bot API (bot de Oscar / ops):
sendMessageconparse_mode: HTML, multi-parte. Vars:TELEGRAM_OPS_TOKEN,TELEGRAM_CHAT_ID. - Nota: envía con
fetchdirecto a Telegram (no usanotify-router.ts).
Cómo probarlo
cd /Users/user/rifai-agents && FORCE=1 npx tsx agentes/sec/vigilante-envios.ts
FORCE=1 salta el gate de las 17:00. Esperado: log con la hora de Madrid, y "Informe enviado a Oscar. Activos: N, entregados hoy: M", más el informe en el bot de ops. Si no hay pedidos activos, el mensaje será "Todo al día." Para revisar el texto sin enviar a producción, ejecutar fuera de la franja sin FORCE saldrá antes ("Fuera de ventana 17:00").
Si se rompe / recuperar
Recargar el plist:
launchctl unload ~/Library/LaunchAgents/com.rifai.vigilante-envios.plist
launchctl load ~/Library/LaunchAgents/com.rifai.vigilante-envios.plist
Logs: /Users/user/rifai-agents/logs/vigilante-envios.log. Causas típicas: SHOPIFY_ACCESS_TOKEN caducado o sin scope de orders, TELEGRAM_OPS_TOKEN incorrecto, o cambio en la estructura de fulfillments/shipment_status de Shopify.
Cómo replicarlo
.envconSHOPIFY_STORE,SHOPIFY_ACCESS_TOKEN,TELEGRAM_OPS_TOKEN,TELEGRAM_CHAT_ID.- App Shopify con permiso de lectura de pedidos.
- Gate horario (17:00 Madrid, override
FORCE=1). - Consulta
orders.jsonconcreated_at_miny la lógica de clasificación porfulfillment_status+shipment_status+ antigüedad/días en tránsito. - Formateo HTML por secciones + envío multi-parte (≤3900) al bot de ops.
- Plist launchd con
StartCalendarIntervala las 17:00 que ejecutenpx tsxdel script.