GustavoandClaude Sonnet 5 abc690ddb7 feat(v2): real Slack send pipeline (guard, idempotency, success/failure registration)
Implements the actual send branch: Selecionar Top N -> Montar Mensagem ->
Guard de Envio -> Slack real -> registrar resultado (only after
confirmed success/failure) -- previously simulated/absent.

logic/slack.js (new): shouldSendByConfig (SEND_ENABLED gate, defaults
false), computeMessageHash (djb2Hash of the exact message text, reused
from logic/hash.js), alreadySentSuccessfully (idempotency check: only a
prior status='success' record for the same report_date+run_type+
message_hash blocks a resend -- a prior 'failed' record does not, so
retries after a real failure aren't stuck), evaluateSendGuard (single
auditable decision combining both), buildEnvioDigestRecord.
logic/slack.test.js: 13 tests covering all of the above, explicitly
labeled against the mission's required tests #13-#16.

New node drivers:
- guard-envio-slack.node.js: reads the digest + recent envio records
  (fetched by report_date), computes the send decision.
- Slack node itself (n8n-nodes-base.slack, native, not a raw webhook):
  reuses the real "Slack account" credential (slackApi) and
  $vars.SLACK_CHANNEL_TECNICO channel variable already used by this
  org's own "Notificacao de Erros Globais" workflow on the same n8n
  instance -- V1's own Slack webhook URL was never actually deployed
  (its Config value is literally "SEU/WEBHOOK/AQUI", same class of
  placeholder as the old GLPI URL from the prior cycle), so this reuses
  the one REAL, credentialed Slack mechanism that exists in this
  environment rather than inventing a new destination. onError:
  continueErrorOutput splits success/failure into two branches.
- registrar-envio-sucesso.node.js / registrar-envio-falha.node.js: build
  the success/failure record; only the success path continues to the
  existing per-ticket send-counter logic (rewired below).
- lancar-erro-envio.node.js: after the failure record is written,
  explicitly throws so the n8n execution shows status=error (never
  silently swallow a send failure).
- pular-envio.node.js: terminal no-op for the "should not send" branch
  (SEND_ENABLED=false or already sent today), for observability only.

n8n/nodes/prepare-envio-record.node.js: rewired to read the Top10
selection by name ($('Code - Selecionar Top 10').all()) instead of
$input, since it now runs downstream of the Slack-success registration,
not directly off Selecionar Top10 -- registering per-ticket send counts
before Slack ever confirmed anything was the exact "don't register
before confirmation" bug the mission called out.

logic/message.test.js: added a full-Top10 message-length regression test
(mission requirement: message stays short, no leaked JSON/score/evidence).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 20:50:54 -03:00

Coordenador GLPI - Chamados Abertos

Projeto n8n para atuar como coordenador diario de Suporte de TI, analisando chamados abertos no GLPI e enviando no Slack os 10 chamados que precisam de acao imediata.

Objetivo

Todos os dias uteis, o workflow consulta o banco do GLPI, calcula um score operacional para cada chamado aberto e envia uma lista priorizada no Slack.

O foco nao e apenas listar chamados antigos. O ranking considera:

  • SLA vencido ou proximo de vencer
  • tempo sem interacao humana
  • prioridade, urgencia e impacto
  • idade do chamado
  • chamado sem tecnico atribuido
  • chamados em categorias e entidades reais do GLPI

Arquivos

  • Coordenador GLPI - Chamados Abertos Slack.n8n.json: workflow importavel no n8n
  • sql/top_10_chamados_abertos_glpi.sql: query base usada pelo workflow
  • .env.example: variaveis para subir n8n localmente
  • docker-compose.yml: n8n local via Docker

Como configurar

  1. Suba o n8n local, se necessario:
docker compose up -d
  1. Acesse:
http://localhost:5678
  1. Importe o workflow:
Coordenador GLPI - Chamados Abertos Slack.n8n.json
  1. Configure a credencial MySQL no node:
MySQL - Top 10 chamados abertos
  1. Abra o node Config - Coordenador GLPI e preencha:
  • slack_webhook_url: webhook do canal Slack
  • dias_sem_interacao_alerta: padrao 2
  • horas_sla_risco: padrao 8
  1. Execute pelo Manual Trigger para validar.

  2. Ative o workflow para rodar pelo Schedule Trigger - Dias uteis 08h.

Metodologia de priorizacao

Cada chamado aberto recebe um score_criticidade, mas a lista final nao e mais apenas o top 10 geral. O workflow monta a lista por blocos para evitar que chamados muito antigos monopolizem todos os dias.

Blocos do top 10:

  • 3 chamados com SLA vencido mais criticos
  • 3 chamados com maior tempo sem interacao
  • 2 chamados sem tecnico atribuido
  • 2 chamados de prioridade alta mais recentes

Se algum bloco nao tiver chamados suficientes, o complemento vem do ranking geral.

O mesmo chamado nao entra duas vezes. Se ele ja apareceu em um bloco anterior, e removido dos blocos seguintes.

Score

Pesos principais:

  • SLA vencido: +100
  • SLA vencendo nas proximas horas configuradas: +45
  • chamado sem interacao ha 7 dias ou mais: +35
  • chamado sem interacao ha 3 a 6 dias: +25
  • chamado sem interacao ha 1 a 2 dias: +10
  • prioridade GLPI: priority * 8
  • urgencia GLPI: urgency * 5
  • impacto GLPI: impact * 5
  • idade do chamado: ate +30
  • sem tecnico atribuido: +25

O resultado e ordenado por:

  1. score_criticidade desc
  2. chamados com SLA vencido primeiro
  3. maior tempo sem interacao
  4. chamados mais antigos

Reincidencia

O workflow controla reincidencia usando staticData global do n8n, sem gravar nada no banco do GLPI.

Regra:

  • apareceu 1 vez: normal
  • apareceu 2 dias seguidos: marcado como reincidente
  • apareceu 3 dias seguidos ou mais: escalar para coordenacao

Campos salvos no staticData:

  • ultima_data_disparo
  • ultimos_chamados_enviados
  • reincidencia_chamados

Se o workflow for duplicado, recriado ou importado como novo workflow, esse historico pode ser perdido porque pertence ao workflow no n8n.

Tempo sem interacao

O campo dias_sem_interacao considera a maior data encontrada entre:

  • followups publicos do chamado: date, date_mod, date_creation
  • tarefas do chamado: date, date_mod, date_creation
  • modificacao do chamado: glpi_tickets.date_mod
  • abertura do chamado: glpi_tickets.date

Isso evita marcar um chamado como parado quando alguem acabou de adicionar ou alterar uma tarefa no GLPI, mesmo que a tarefa esteja planejada para outro dia.

Se a maior data encontrada estiver no futuro por causa de uma tarefa planejada, o contador fica em 0 dias sem interacao, evitando valores negativos no relatorio.

Regra de chamados abertos

O SQL considera abertos todos os chamados com:

is_deleted = false
AND status NOT IN (5, 6)

Este gatilho principal ignora chamados das categorias:

  • ADMINISTRATIVO
  • DESENVOLVIMENTO
  • INFRA

O filtro usa o nome completo da categoria (completename) ou o nome simples (name) iniciando com esses termos, entao tambem remove subcategorias dessas filas.

No GLPI, normalmente:

  • 5: solucionado
  • 6: fechado

Campos usados

A query usa tabelas comuns do GLPI:

  • glpi_tickets
  • glpi_itilcategories
  • glpi_entities
  • glpi_itilfollowups
  • glpi_tickettasks
  • glpi_tickets_users
  • glpi_users

Se sua versao do GLPI tiver customizacoes, valide primeiro a query sql/top_10_chamados_abertos_glpi.sql diretamente no banco.

Saida no Slack

O Slack recebe uma mensagem curta com:

  • top 10 chamados para atacar hoje
  • tecnico atribuido, quando existir
  • SLA
  • dias sem interacao
  • dias aberto
  • reincidencia
  • link do chamado, se glpi_base_url estiver configurado no workflow

Campos removidos da mensagem para reduzir ruido:

  • motivo
  • acao
  • prazo

Se o agente de IA falhar, o workflow envia a mensagem curta gerada por codigo, sem depender da IA.

Agente de IA do n8n com Z IA

O workflow usa o node:

AI Agent - Revisar mensagem

Por padrao, ele esta conectado ao node:

Z IA Chat Model

Esse node usa o chat model compativel com OpenAI do n8n, mas a credencial deve ser configurada para a Z IA.

A IA nao monta mais a mensagem do zero. O node Code - Reincidencia e mensagem curta monta a mensagem final de forma deterministica, e a IA apenas revisa clareza e reduz texto.

Regras do prompt:

  • nao adicionar fatos
  • nao criar motivo
  • nao criar acao
  • nao criar prazo
  • nao alterar IDs, tecnicos, datas, SLA, dias, reincidencia ou links
  • nao usar tom agressivo

No n8n, abra o node:

Z IA Chat Model

Configure:

  • credencial Z IA
  • endpoint/base URL da Z IA, se a credencial permitir
  • modelo correto disponibilizado pela Z IA, por exemplo glm-4.5-flash

No arquivo importavel deixei o modelo como glm-4.5-flash. Se sua conta Z IA usar outro nome de modelo, troque pelo nome exato exibido na plataforma.

Se aparecer The resource you are requesting could not be found, revise principalmente:

  • Base URL da credencial: normalmente https://api.z.ai/api/paas/v4
  • Modelo: precisa existir na sua conta, por exemplo glm-4.5-flash
  • Chave API: precisa ser da Z IA, nao da OpenAI
  • Node usado: mantenha Z IA Chat Model conectado ao AI Agent - Revisar mensagem

Se a Z IA aparecer no seu n8n como node proprio, mantenha o AI Agent - Revisar mensagem e substitua somente o subnode Z IA Chat Model pelo modelo oficial da Z IA.

Recomendacao direta

Nao trate isso como relatorio bonito. Trate como fila diaria de comando.

Minha sugestao operacional:

  • rodar as 08h no canal da lideranca de suporte
  • exigir responsavel e prazo para cada um dos 10 chamados ate 10h
  • repetir apenas os chamados que continuarem parados no dia seguinte
  • se um chamado aparecer 3 dias seguidos, escalar para coordenacao/gestao
  • separar um segundo workflow para chamados sem tecnico atribuido, porque isso e falha de triagem, nao backlog comum
  • criar outro alerta intradiario para SLA vencendo nas proximas 2 horas

Se quiser resultado real, nao basta notificar. Tem que transformar a mensagem do Slack em ritual diario de cobranca.

S
Description
No description provided
Readme
353 KiB
Languages
JavaScript 99.3%
Python 0.7%