- Script sync-obra-estatus.py (idempotente, --dry-run, retry/backoff): parsea ESTATUS OBRA, SENDA-ACT-AGO2026, SENDA/SOLE DG, Diagonal 38 y las hojas de ventas; mapea a Unidades vía maestro-unidades.json - Board Unidades: +12 columnas (% avance obra, meses atraso, contratista, clave catastral, no. oficial, vendedor, broker, venc. autorización, fecha entrega obra, 4 checkboxes de hitos documentales) — 147 items actualizados (DIAGONAL 38/38, SENDA 109/142) - Board nuevo 'Flujo Escrituras' (18429252054): 32 items mayo–ago/2026 por proyecto/semana con escrituras e ingreso - Board nuevo 'Saldos a Favor' (18429252069): 7 pendientes (Estanza/Sole) - Receta nativa documentada: recordatorio 7 días antes de Venc. autorización al coordinador - SOLE y MUTUO no existen como inventario en Monday: sus datos de obra se reportan como saltados (no se crean unidades)
143 lines
6.7 KiB
Markdown
143 lines
6.7 KiB
Markdown
# Automatizaciones nativas de Monday — checklist del admin
|
|
|
|
Recetas que se activan **desde la UI de Monday** (botón "Automatizar" en cada
|
|
tablero). Tiempo estimado total: ~10 minutos. Ninguna requiere código.
|
|
|
|
> **No duplicar**: el servidor (API Gateway) ya cubre la asignación round-robin
|
|
> de vendedores, el recordatorio de leads inactivos (10 días), el escalado de
|
|
> leads sin contactar (48 h), y la creación de items en Apartado / Ventas
|
|
> cuando una oportunidad entra a **Aparto** o **Ganado**. Las recetas de abajo
|
|
> son solo *avisos y orden visual*; no repitas esas reglas como recetas
|
|
> nativas.
|
|
|
|
## 0. Cómo llegan los eventos al servidor (webhooks + crons)
|
|
|
|
Desde que el stack tiene dominio público (Cloudflare Tunnel), Monday avisa al
|
|
servidor **en tiempo real** vía webhooks registrados en
|
|
`https://frasa.consultoria-as.com/api/webhooks/monday`:
|
|
|
|
| Board | Evento registrado | Reacción del servidor |
|
|
|---|---|---|
|
|
| Leads | `create_item` | Round-robin: asigna Vendedor al lead nuevo |
|
|
| Oportunidades | `change_column_value` | Si la etapa es **Aparto** → crea item en Apartado; si es **Ganado** → crea item en Ventas |
|
|
|
|
Los **crons cada 5 min** (`POLL_CRON`) siguen activos como red de seguridad:
|
|
repiten los mismos escaneos (idempotentes, con dedup en la base) por si un
|
|
evento se pierde. El escaneo de **inactividad** (9:00) y los **recordatorios
|
|
de cobranza** (9:30) solo corren por cron.
|
|
|
|
Notas técnicas (quirks de Monday, ya contemplados en el código):
|
|
|
|
- El webhook se registra como `create_item` pero el payload real llega como
|
|
`create_pulse`, y el id viene en `pulseId` (no `itemId`).
|
|
- Los cambios de columna llegan como `update_column_value`.
|
|
- El evento `change_status_column_value` **no dispara** en estos boards; por
|
|
eso se registró `change_column_value`.
|
|
- Monday no firma sus webhooks: el servidor usa el evento solo como disparador
|
|
y re-consulta el tablero por API antes de escribir nada.
|
|
|
|
### 0.1 La cadena del funnel: Leads → Oportunidades
|
|
|
|
Los leads **no** se cargan como clientes directo: cada lead capturado entra al
|
|
tablero **Oportunidades** en etapa **Afluencia** y la oportunidad avanza sola
|
|
conforme avanza el proceso. La vinculación lead ↔ oportunidad vive en la tabla
|
|
`LeadOportunidad` de la base local (una oportunidad por lead; idempotente).
|
|
|
|
| Transición | Evento que la dispara |
|
|
|---|---|
|
|
| → **Afluencia** | `POST /api/leads` (captura) o webhook `create_pulse` en Leads (alta directa en la UI de Monday): crea la oportunidad con nombre, teléfono, email y Desarrollo del lead |
|
|
| → **Agendo Cita** | `POST /api/leads/:id/estado` con estado `AGENDA CITA` |
|
|
| → **Cotizador** | `POST /api/cotizaciones` con un teléfono que ya tiene lead mapeado: **actualiza** la misma oportunidad (Unidad, Tipo propuesta, precios, Fecha cotización) en vez de crear una segunda |
|
|
| → **Aparto** | `POST /api/clientes` con `leadMondayId` en el payload (app alta-clientes). Se escribe el dedup `apartado-creado:<opId>` **antes** del cambio de etapa para que el webhook/cron no duplique el Apartado |
|
|
| → **Ganado** | Manual en Monday (o flujo Enkontrol): el escaneo crea el item en Ventas |
|
|
| → **Perdido** | `POST /api/leads/:id/descartar`: mueve la oportunidad y, si el motivo es label del dropdown **Motivo No Compra**, lo setea también |
|
|
|
|
Reglas de resiliencia: un fallo de Monday en cualquiera de estas transiciones
|
|
solo se loguea — la acción principal (crear el lead, la cotización o el alta)
|
|
nunca se rompe por el funnel.
|
|
|
|
Para re-registrar un webhook (p. ej. si cambia el dominio):
|
|
|
|
```graphql
|
|
mutation {
|
|
create_webhook(board_id: <BOARD_ID>,
|
|
url: "https://frasa.consultoria-as.com/api/webhooks/monday",
|
|
event: create_item) { id }
|
|
}
|
|
```
|
|
|
|
## 1. Tablero Leads — avisar al vendedor cuando se le asigna un lead
|
|
|
|
El round-robin del servidor asigna la columna **Vendedor**; esta receta solo
|
|
envía la notificación.
|
|
|
|
- Board: **Leads**
|
|
- Receta: *"When a person is assigned to someone, notify someone"* (categoría
|
|
**People**; en español: "Cuando se asigne una persona, notificar a alguien")
|
|
- Parámetros:
|
|
- person column: **Vendedor**
|
|
- notify: **the person assigned** (el vendedor asignado)
|
|
- mensaje: `Tienes un lead nuevo: {item.name}`
|
|
|
|
## 2. Tablero Oportunidades — avisar cuando algo se gana
|
|
|
|
El servidor ya crea el item en Ventas; esto solo avisa al equipo.
|
|
|
|
- Board: **Oportunidades**
|
|
- Receta: *"When status changes to something, notify someone"* (categoría
|
|
**Status**)
|
|
- Parámetros:
|
|
- status column: **Estado** → valor: **Ganado**
|
|
- notify: una persona o equipo de coordinación (elegir en la receta)
|
|
- mensaje: `Venta ganada: {item.name} — {item.text_mm6ezd0d}` (unidad)
|
|
|
|
## 3. Tablero Apartado — recordatorio de fecha límite
|
|
|
|
- Board: **Apartado**
|
|
- Receta: *"When a date arrives, notify someone"* (categoría **Date
|
|
reminders**)
|
|
- Parámetros:
|
|
- date column: **Fecha límite**
|
|
- when: **1 día antes**, a las **9:00**
|
|
- notify: **el responsable del expediente** (o coordinación)
|
|
- mensaje: `El apartado de {item.name} vence mañana`
|
|
|
|
## 4. Mover items entre grupos por estado (orden visual)
|
|
|
|
Si los tableros tienen grupos (p. ej. "Activos" / "Cerrados"), una receta por
|
|
tablero mantiene el orden sin trabajo manual:
|
|
|
|
- Board: **Oportunidades** (repetir en **Leads** si usa grupos)
|
|
- Receta: *"When status changes to something, move item to group"* (categoría
|
|
**Status**)
|
|
- Parámetros sugeridos:
|
|
- **Estado** = Ganado → mover al grupo **Cerrados**
|
|
- **Estado** = Perdido → mover al grupo **Cerrados**
|
|
- **Estado** = Abandono → mover al grupo **Cerrados**
|
|
|
|
> Si el tablero no tiene grupos, omite esta receta: no afecta nada del servidor.
|
|
|
|
## 5. Tablero Unidades — recordatorio de vencimiento de autorización de crédito
|
|
|
|
La columna **Venc. autorización** (date) del board Unidades la llena
|
|
`sync-obra-estatus.py` cuando el desarrollo exista en el board (hoy solo la
|
|
fuente MUTUO la trae, y MUTUO aún no está en Unidades). La receta queda lista
|
|
para cuando la columna tenga datos.
|
|
|
|
- Board: **Unidades**
|
|
- Receta: *"When a date arrives, notify someone"* (categoría **Date
|
|
reminders**; en español: "Cuando llegue una fecha, notificar a alguien")
|
|
- Parámetros:
|
|
- date column: **Venc. autorización**
|
|
- when: **7 días antes**, a las **9:00**
|
|
- notify: **el coordinador de ventas** (elegir la persona en la receta)
|
|
- mensaje: `La autorización de crédito de {item.name} vence en 7 días`
|
|
|
|
## Verificación rápida (2 min)
|
|
|
|
1. Crea un item de prueba en **Leads**, asígnate como Vendedor → debe llegarte
|
|
la notificación de la receta 1. Bórralo después.
|
|
2. En **Oportunidades**, cambia un item de prueba a **Ganado** → notificación
|
|
de la receta 2 **y** (en segundos, vía webhook; ≤ 5 min por el cron de
|
|
respaldo) un item nuevo en **Ventas**. Borra ambos después.
|