feat(api): webhooks Monday en tiempo real + alertas de inventario cableadas
- Webhook Oportunidades: cambio de etapa dispara escaneo (Aparto→Apartado, Ganado→Venta) además del round-robin de leads por create_item - Acepta los nombres reales de los eventos de Monday: create_pulse/pulseId y update_column_value (verificados en vivo) - Token interno (X-Internal-Token) para que los syncs locales llamen POST /cotizaciones/alertas-inventario sin JWT de usuario - sync-estatus-maestro.py notifica los cambios aplicados al endpoint de alertas (actividad al vendedor con cotizaciones recientes) - Fix P1008 SQLite: escaneos del poll cron secuenciales + connection_limit=1 en DATABASE_URL - Webhooks registrados en Monday sobre https://frasa.consultoria-as.com (Leads create_item, Oportunidades change_column_value); crons quedan como red de seguridad - Docs: sección 0 en AUTOMATIZACIONES-MONDAY.md con la matriz de eventos y los quirks de Monday
This commit is contained in:
Binary file not shown.
@@ -115,6 +115,42 @@ def main():
|
||||
print(f'{aplicados} items actualizados en Monday')
|
||||
for code, motivo in omitidos:
|
||||
print(f' omitido {code}: {motivo}')
|
||||
if not DRY and aplicados:
|
||||
notificar_alertas(cambios)
|
||||
|
||||
|
||||
def notificar_alertas(cambios):
|
||||
"""Avisa al API local de los cambios aplicados (alertas de inventario al
|
||||
vendedor con cotizaciones recientes de la unidad). Best-effort: un fallo
|
||||
aquí no revierte lo ya escrito en Monday."""
|
||||
token = os.environ.get('INTERNAL_SYNC_TOKEN') or lee_env('INTERNAL_SYNC_TOKEN')
|
||||
if not token:
|
||||
print(' (sin INTERNAL_SYNC_TOKEN: se omiten las alertas de inventario)')
|
||||
return
|
||||
payload = json.dumps({'cambios': [
|
||||
{'unidadCodigo': c['codigo'], 'statusNuevo': c['a']} for c in cambios
|
||||
]}).encode()
|
||||
req = urllib.request.Request(
|
||||
'http://localhost:3000/api/cotizaciones/alertas-inventario',
|
||||
data=payload,
|
||||
headers={'Content-Type': 'application/json', 'X-Internal-Token': token})
|
||||
try:
|
||||
res = json.load(urllib.request.urlopen(req, timeout=15))
|
||||
print(f" alertas-inventario: {res.get('alertasCreadas', 0)} actividad(es) creada(s), "
|
||||
f"{res.get('omitidas', 0)} omitida(s), {res.get('fallidas', 0)} fallida(s)")
|
||||
except Exception as e:
|
||||
print(f' AVISO: no se pudieron enviar las alertas de inventario: {e}')
|
||||
|
||||
|
||||
def lee_env(nombre):
|
||||
env = os.path.join(ROOT, '../../.env')
|
||||
try:
|
||||
for line in open(env):
|
||||
if line.startswith(nombre + '='):
|
||||
return line.strip().split('=', 1)[1].strip().strip('"').strip("'")
|
||||
except OSError:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user