git-subtree-dir: coordenador git-subtree-mainline:facbe2e340git-subtree-split:ce7af94d55
315 lines
20 KiB
JSON
315 lines
20 KiB
JSON
{
|
|
"name": "Coordenador GLPI - Chamados Abertos Slack",
|
|
"nodes": [
|
|
{
|
|
"parameters": {},
|
|
"id": "manual-trigger-coordenador-glpi",
|
|
"name": "Manual Trigger",
|
|
"type": "n8n-nodes-base.manualTrigger",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
180,
|
|
420
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"rule": {
|
|
"interval": [
|
|
{
|
|
"field": "cronExpression",
|
|
"expression": "0 8 * * 1-5"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"id": "schedule-trigger-dias-uteis-08h",
|
|
"name": "Schedule Trigger - Dias uteis 08h",
|
|
"type": "n8n-nodes-base.scheduleTrigger",
|
|
"typeVersion": 1.2,
|
|
"position": [
|
|
180,
|
|
180
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"assignments": {
|
|
"assignments": [
|
|
{
|
|
"id": "slack-webhook-url",
|
|
"name": "slack_webhook_url",
|
|
"type": "string",
|
|
"value": "https://hooks.slack.com/services/SEU/WEBHOOK/AQUI"
|
|
},
|
|
{
|
|
"id": "glpi-base-url",
|
|
"name": "glpi_base_url",
|
|
"type": "string",
|
|
"value": "https://glpi.suaempresa.com.br"
|
|
},
|
|
{
|
|
"id": "dias-sem-interacao-alerta",
|
|
"name": "dias_sem_interacao_alerta",
|
|
"type": "number",
|
|
"value": 2
|
|
},
|
|
{
|
|
"id": "horas-sla-risco",
|
|
"name": "horas_sla_risco",
|
|
"type": "number",
|
|
"value": 8
|
|
}
|
|
]
|
|
},
|
|
"options": {}
|
|
},
|
|
"id": "config-coordenador-glpi",
|
|
"name": "Config - Coordenador GLPI",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 3.4,
|
|
"position": [
|
|
440,
|
|
300
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const config = $('Config - Coordenador GLPI').first().json;\n\nconst diasSemInteracaoAlerta = Number(config.dias_sem_interacao_alerta || 2);\nconst horasSlaRisco = Number(config.horas_sla_risco || 8);\nconst glpiBaseUrl = String(config.glpi_base_url || '').replace(/\\/$/, '').replace(/'/g, \"''\");\n\nconst queryTemplate = `-- Top 10 chamados abertos por blocos operacionais.\n-- Blocos:\n-- - 3 chamados com SLA vencido mais criticos\n-- - 3 chamados com maior tempo sem interacao\n-- - 2 chamados sem tecnico atribuido\n-- - 2 chamados de prioridade alta mais recentes\n-- Se faltar item em algum bloco, o complemento vem do ranking geral.\n--\n-- Ajuste os parametros abaixo no workflow n8n:\n-- {DIAS_SEM_INTERACAO_ALERTA}\n-- {HORAS_SLA_RISCO}\n-- {GLPI_BASE_URL}\n\nWITH ultima_interacao AS (\n SELECT\n tickets_id,\n MAX(data_interacao) AS ultima_interacao_em\n FROM (\n SELECT tickets_id, MAX(data_interacao) AS data_interacao\n FROM (\n SELECT items_id AS tickets_id, date AS data_interacao\n FROM glpi_itilfollowups\n WHERE itemtype = 'Ticket'\n AND is_private = 0\n\n UNION ALL\n\n SELECT items_id AS tickets_id, date_mod AS data_interacao\n FROM glpi_itilfollowups\n WHERE itemtype = 'Ticket'\n AND is_private = 0\n\n UNION ALL\n\n SELECT items_id AS tickets_id, date_creation AS data_interacao\n FROM glpi_itilfollowups\n WHERE itemtype = 'Ticket'\n AND is_private = 0\n ) followup_datas\n WHERE data_interacao IS NOT NULL\n GROUP BY tickets_id\n\n UNION ALL\n\n SELECT tickets_id, MAX(data_interacao) AS data_interacao\n FROM (\n SELECT tickets_id, date AS data_interacao\n FROM glpi_tickettasks\n\n UNION ALL\n\n SELECT tickets_id, date_mod AS data_interacao\n FROM glpi_tickettasks\n\n UNION ALL\n\n SELECT tickets_id, date_creation AS data_interacao\n FROM glpi_tickettasks\n ) task_datas\n WHERE data_interacao IS NOT NULL\n GROUP BY tickets_id\n ) interacoes\n GROUP BY tickets_id\n), tecnicos AS (\n SELECT\n tu.tickets_id,\n GROUP_CONCAT(TRIM(CONCAT(COALESCE(u.firstname, ''), ' ', COALESCE(u.realname, u.name))) SEPARATOR ', ') AS tecnicos\n FROM glpi_tickets_users tu\n LEFT JOIN glpi_users u ON u.id = tu.users_id\n WHERE tu.type = 2\n GROUP BY tu.tickets_id\n), chamados_base AS (\n SELECT\n t.id,\n t.name AS titulo,\n t.status,\n CASE t.status\n WHEN 1 THEN 'Novo'\n WHEN 2 THEN 'Em atendimento'\n WHEN 3 THEN 'Planejado'\n WHEN 4 THEN 'Pendente'\n ELSE CONCAT('Status ', t.status)\n END AS status_nome,\n t.date AS aberto_em,\n t.date_mod AS modificado_em,\n t.time_to_resolve AS sla_resolver_ate,\n t.priority,\n t.urgency,\n t.impact,\n COALESCE(e.completename, e.name, 'Nao informado') AS entidade,\n COALESCE(c.completename, c.name, 'Sem categoria') AS categoria,\n COALESCE(tecnicos.tecnicos, 'Sem tecnico atribuido') AS tecnico_atribuido,\n GREATEST(\n COALESCE(ultima_interacao.ultima_interacao_em, '1970-01-01 00:00:00'),\n COALESCE(t.date_mod, '1970-01-01 00:00:00'),\n COALESCE(t.date, '1970-01-01 00:00:00')\n ) AS ultima_interacao_em,\n TIMESTAMPDIFF(DAY, t.date, NOW()) AS dias_aberto,\n GREATEST(TIMESTAMPDIFF(DAY, GREATEST(\n COALESCE(ultima_interacao.ultima_interacao_em, '1970-01-01 00:00:00'),\n COALESCE(t.date_mod, '1970-01-01 00:00:00'),\n COALESCE(t.date, '1970-01-01 00:00:00')\n ), NOW()), 0) AS dias_sem_interacao,\n TIMESTAMPDIFF(HOUR, NOW(), t.time_to_resolve) AS horas_ate_sla,\n CASE WHEN t.time_to_resolve IS NOT NULL AND t.time_to_resolve < NOW() THEN 1 ELSE 0 END AS sla_vencido,\n CASE\n WHEN t.time_to_resolve IS NOT NULL\n AND t.time_to_resolve >= NOW()\n AND TIMESTAMPDIFF(HOUR, NOW(), t.time_to_resolve) <= {HORAS_SLA_RISCO} THEN 1\n ELSE 0\n END AS sla_em_risco,\n CASE WHEN tecnicos.tecnicos IS NULL THEN 1 ELSE 0 END AS sem_tecnico,\n CONCAT('{GLPI_BASE_URL}', '/front/ticket.form.php?id=', t.id) AS link_glpi\n FROM glpi_tickets t\n LEFT JOIN glpi_entities e ON e.id = t.entities_id\n LEFT JOIN glpi_itilcategories c ON c.id = t.itilcategories_id\n LEFT JOIN ultima_interacao ON ultima_interacao.tickets_id = t.id\n LEFT JOIN tecnicos ON tecnicos.tickets_id = t.id\n WHERE t.is_deleted = false\n AND t.status NOT IN (5, 6)\n AND COALESCE(c.completename, c.name, '') NOT LIKE 'ADMINISTRATIVO%'\n AND COALESCE(c.completename, c.name, '') NOT LIKE 'DESENVOLVIMENTO%'\n AND COALESCE(c.completename, c.name, '') NOT LIKE 'INFRA%'\n), chamados_ranked AS (\n SELECT\n id,\n titulo,\n status_nome,\n aberto_em,\n modificado_em,\n ultima_interacao_em,\n dias_aberto,\n dias_sem_interacao,\n sla_resolver_ate,\n horas_ate_sla,\n sla_vencido,\n sla_em_risco,\n priority AS prioridade,\n urgency AS urgencia,\n impact AS impacto,\n entidade,\n categoria,\n tecnico_atribuido,\n sem_tecnico,\n link_glpi,\n (\n CASE WHEN sla_vencido = 1 THEN 100 ELSE 0 END\n + CASE WHEN sla_em_risco = 1 THEN 45 ELSE 0 END\n + CASE\n WHEN dias_sem_interacao >= 7 THEN 35\n WHEN dias_sem_interacao >= 3 THEN 25\n WHEN dias_sem_interacao >= {DIAS_SEM_INTERACAO_ALERTA} THEN 10\n ELSE 0\n END\n + LEAST(dias_aberto, 30)\n + (priority * 8)\n + (urgency * 5)\n + (impact * 5)\n + CASE WHEN sem_tecnico = 1 THEN 25 ELSE 0 END\n ) AS score_criticidade\n FROM chamados_base\n), sla_top AS (\n SELECT *, 'SLA vencido' AS bloco_origem, 1 AS bloco_ordem\n FROM chamados_ranked\n WHERE sla_vencido = 1\n ORDER BY score_criticidade DESC, dias_sem_interacao DESC, dias_aberto DESC\n LIMIT 3\n), sem_interacao_top AS (\n SELECT *, 'Sem interacao' AS bloco_origem, 2 AS bloco_ordem\n FROM chamados_ranked\n WHERE id NOT IN (SELECT id FROM sla_top)\n ORDER BY dias_sem_interacao DESC, score_criticidade DESC, dias_aberto DESC\n LIMIT 3\n), sem_tecnico_top AS (\n SELECT *, 'Sem tecnico' AS bloco_origem, 3 AS bloco_ordem\n FROM chamados_ranked\n WHERE sem_tecnico = 1\n AND id NOT IN (SELECT id FROM sla_top)\n AND id NOT IN (SELECT id FROM sem_interacao_top)\n ORDER BY score_criticidade DESC, dias_sem_interacao DESC, dias_aberto DESC\n LIMIT 2\n), prioridade_alta_recente_top AS (\n SELECT *, 'Prioridade alta recente' AS bloco_origem, 4 AS bloco_ordem\n FROM chamados_ranked\n WHERE prioridade >= 4\n AND id NOT IN (SELECT id FROM sla_top)\n AND id NOT IN (SELECT id FROM sem_interacao_top)\n AND id NOT IN (SELECT id FROM sem_tecnico_top)\n ORDER BY aberto_em DESC, score_criticidade DESC\n LIMIT 2\n), selecionados AS (\n SELECT * FROM sla_top\n UNION ALL\n SELECT * FROM sem_interacao_top\n UNION ALL\n SELECT * FROM sem_tecnico_top\n UNION ALL\n SELECT * FROM prioridade_alta_recente_top\n), complemento AS (\n SELECT *, 'Ranking geral' AS bloco_origem, 5 AS bloco_ordem\n FROM chamados_ranked\n WHERE id NOT IN (SELECT id FROM selecionados)\n ORDER BY score_criticidade DESC, sla_vencido DESC, dias_sem_interacao DESC, dias_aberto DESC\n LIMIT 10\n)\nSELECT *\nFROM (\n SELECT * FROM selecionados\n UNION ALL\n SELECT * FROM complemento\n) ranking_final\nORDER BY bloco_ordem ASC, score_criticidade DESC, dias_sem_interacao DESC, dias_aberto DESC\nLIMIT 10;\n`;\nconst query = queryTemplate\n .replaceAll('{DIAS_SEM_INTERACAO_ALERTA}', String(diasSemInteracaoAlerta))\n .replaceAll('{HORAS_SLA_RISCO}', String(horasSlaRisco))\n .replaceAll('{GLPI_BASE_URL}', glpiBaseUrl);\n\nreturn [{ json: { query } }];"
|
|
},
|
|
"id": "code-montar-sql-top-10",
|
|
"name": "Code - Montar SQL Top 10",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
700,
|
|
300
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"operation": "executeQuery",
|
|
"query": "={{ $json.query }}",
|
|
"options": {}
|
|
},
|
|
"id": "mysql-top-10-chamados-abertos",
|
|
"name": "MySQL - Top 10 chamados abertos",
|
|
"type": "n8n-nodes-base.mySql",
|
|
"typeVersion": 2.4,
|
|
"position": [
|
|
960,
|
|
300
|
|
],
|
|
"credentials": {
|
|
"mySql": {
|
|
"id": "",
|
|
"name": "MySQL GLPI"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const chamados = $input.all().map(item => item.json);\nconst hoje = new Date().toLocaleDateString('pt-BR', { timeZone: 'America/Sao_Paulo' });\nconst hojeIso = new Date().toLocaleDateString('sv-SE', { timeZone: 'America/Sao_Paulo' });\nconst staticData = $getWorkflowStaticData('global');\nconst historicoAnterior = staticData.reincidencia_chamados || {};\nconst idsUltimoDisparo = new Set(staticData.ultimos_chamados_enviados || []);\nconst ultimaDataDisparo = staticData.ultima_data_disparo;\nconst mesmaData = ultimaDataDisparo === hojeIso;\n\nconst chamadosComReincidencia = chamados.map(chamado => {\n const id = String(chamado.id);\n const anterior = historicoAnterior[id] || {};\n let diasSeguidos;\n\n if (mesmaData && anterior.ultima_data === hojeIso) {\n diasSeguidos = Number(anterior.dias_seguidos || 1);\n } else if (idsUltimoDisparo.has(id)) {\n diasSeguidos = Number(anterior.dias_seguidos || 1) + 1;\n } else {\n diasSeguidos = 1;\n }\n\n return { ...chamado, reincidencia_dias: diasSeguidos };\n});\n\nstaticData.reincidencia_chamados = Object.fromEntries(\n chamadosComReincidencia.map(chamado => [String(chamado.id), {\n dias_seguidos: chamado.reincidencia_dias,\n ultima_data: hojeIso\n }])\n);\nstaticData.ultimos_chamados_enviados = chamadosComReincidencia.map(chamado => String(chamado.id));\nstaticData.ultima_data_disparo = hojeIso;\n\nfunction slaTexto(chamado) {\n if (Number(chamado.sla_vencido) === 1) return 'Vencido';\n if (Number(chamado.sla_em_risco) === 1) return `Risco ${chamado.horas_ate_sla}h`;\n return chamado.sla_resolver_ate ? 'OK' : 'Sem SLA';\n}\n\nfunction reincidenciaTexto(dias) {\n if (dias >= 3) return `${dias} dias - ESCALAR`;\n if (dias === 2) return '2 dias - reincidente';\n return '1 dia';\n}\n\nfunction tituloCurto(texto) {\n const limpo = String(texto || 'Sem titulo').replace(/\\s+/g, ' ').trim();\n return limpo.length > 80 ? `${limpo.slice(0, 77)}...` : limpo;\n}\n\nconst resumo = {\n sla_vencido: chamadosComReincidencia.filter(c => Number(c.sla_vencido) === 1).length,\n sem_tecnico: chamadosComReincidencia.filter(c => Number(c.sem_tecnico) === 1).length,\n reincidentes_2_dias: chamadosComReincidencia.filter(c => Number(c.reincidencia_dias) === 2).length,\n escalar_3_dias_ou_mais: chamadosComReincidencia.filter(c => Number(c.reincidencia_dias) >= 3).length\n};\n\nconst linhas = chamadosComReincidencia.map((chamado, index) => [\n `${index + 1}. #${chamado.id} - ${tituloCurto(chamado.titulo)}`,\n `Tecnico: ${chamado.tecnico_atribuido} | Fila: ${chamado.bloco_origem || 'Ranking geral'}`,\n `SLA: ${slaTexto(chamado)} | Sem interacao: ${chamado.dias_sem_interacao}d | Aberto: ${chamado.dias_aberto}d | Reinc.: ${reincidenciaTexto(Number(chamado.reincidencia_dias || 1))}`,\n `${chamado.link_glpi}`\n].join('\\n'));\n\nconst escalados = chamadosComReincidencia\n .filter(chamado => Number(chamado.reincidencia_dias) >= 3)\n .map(chamado => `#${chamado.id}`);\n\nconst textoPronto = chamadosComReincidencia.length\n ? [\n `@time Top 10 chamados para atencao hoje - ${hoje}`,\n '',\n `Resumo: ${resumo.sla_vencido} SLA vencido(s) | ${resumo.sem_tecnico} sem tecnico | ${resumo.reincidentes_2_dias} reincidente(s) 2d | ${resumo.escalar_3_dias_ou_mais} escalar 3d+`,\n '',\n ...linhas,\n '',\n escalados.length ? `Escalar para coordenacao: ${escalados.join(', ')}` : 'Sem chamados com 3 dias seguidos na lista.',\n 'Atualizem o GLPI para o chamado sair da reincidencia.'\n ].join('\\n')\n : [`@time Coordenador GLPI - ${hoje}`, '', 'Nenhum chamado aberto encontrado pelos criterios da query.'].join('\\n');\n\nconst promptIa = [\n 'Revise a mensagem abaixo para Slack.',\n 'Regras obrigatorias:',\n '- Nao adicione fatos.',\n '- Nao crie motivo, acao ou prazo.',\n '- Nao altere IDs, tecnicos, datas, SLA, dias, reincidencia ou links.',\n '- Nao use tom agressivo.',\n '- Mantenha a mensagem curta e facil de escanear.',\n '- Retorne somente a mensagem final.',\n '',\n textoPronto\n].join('\\n');\n\nreturn [{ json: { chamados: chamadosComReincidencia, resumo, texto_pronto: textoPronto, prompt_ia: promptIa, total: chamadosComReincidencia.length, data_relatorio: hoje } }];"
|
|
},
|
|
"id": "code-reincidencia-mensagem",
|
|
"name": "Code - Reincidencia e mensagem curta",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1220,
|
|
300
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"model": "glm-4.5-flash",
|
|
"options": {
|
|
"temperature": 0.1
|
|
}
|
|
},
|
|
"id": "z-ia-chat-model-coordenador",
|
|
"name": "Z IA Chat Model",
|
|
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
|
|
"typeVersion": 1.2,
|
|
"position": [
|
|
1480,
|
|
520
|
|
],
|
|
"credentials": {
|
|
"openAiApi": {
|
|
"id": "",
|
|
"name": "Z IA"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"promptType": "define",
|
|
"text": "={{ $json.prompt_ia }}",
|
|
"options": {
|
|
"systemMessage": "Voce e um revisor de mensagem operacional para Slack. Sua funcao e apenas melhorar clareza e reduzir texto. Nao invente dados. Nao adicione motivo, acao, prazo, diagnostico ou cobranca agressiva. Preserve IDs, nomes, tecnicos, links e numeros exatamente como recebidos."
|
|
}
|
|
},
|
|
"id": "ai-agent-coordenador-glpi",
|
|
"name": "AI Agent - Revisar mensagem",
|
|
"type": "@n8n/n8n-nodes-langchain.agent",
|
|
"typeVersion": 1.7,
|
|
"position": [
|
|
1480,
|
|
300
|
|
],
|
|
"continueOnFail": true
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const resposta = $input.first().json;\nconst textoIa = String(resposta.output || resposta.text || resposta.response || resposta.result || '').trim();\nconst contexto = $('Code - Reincidencia e mensagem curta').first().json;\nconst fallback = contexto.texto_pronto;\nconst chamados = contexto.chamados || [];\n\nconst contemTodosIds = chamados.every(chamado => textoIa.includes(`#${chamado.id}`));\nconst contemTodosLinks = chamados.every(chamado => !chamado.link_glpi || textoIa.includes(chamado.link_glpi));\nconst contemCampoProibido = /(^|\\n)\\s*\\*{0,2}(motivo|acao|ação|prazo)\\*{0,2}\\s*:/i.test(textoIa);\nconst textoSeguro = textoIa && contemTodosIds && contemTodosLinks && !contemCampoProibido;\n\nreturn [{ json: { text: textoSeguro ? textoIa : fallback } }];"
|
|
},
|
|
"id": "code-preparar-slack",
|
|
"name": "Code - Preparar mensagem Slack",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1740,
|
|
300
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "={{ $('Config - Coordenador GLPI').first().json.slack_webhook_url }}",
|
|
"sendBody": true,
|
|
"contentType": "json",
|
|
"specifyBody": "keypair",
|
|
"bodyParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "text",
|
|
"value": "={{ $json.text }}"
|
|
}
|
|
]
|
|
},
|
|
"options": {}
|
|
},
|
|
"id": "http-slack-enviar",
|
|
"name": "HTTP - Slack enviar mensagem",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.2,
|
|
"position": [
|
|
2000,
|
|
300
|
|
]
|
|
}
|
|
],
|
|
"pinData": {},
|
|
"connections": {
|
|
"Manual Trigger": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Config - Coordenador GLPI",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Schedule Trigger - Dias uteis 08h": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Config - Coordenador GLPI",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Config - Coordenador GLPI": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code - Montar SQL Top 10",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code - Montar SQL Top 10": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "MySQL - Top 10 chamados abertos",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"MySQL - Top 10 chamados abertos": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code - Reincidencia e mensagem curta",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code - Reincidencia e mensagem curta": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "AI Agent - Revisar mensagem",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Z IA Chat Model": {
|
|
"ai_languageModel": [
|
|
[
|
|
{
|
|
"node": "AI Agent - Revisar mensagem",
|
|
"type": "ai_languageModel",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"AI Agent - Revisar mensagem": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code - Preparar mensagem Slack",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code - Preparar mensagem Slack": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "HTTP - Slack enviar mensagem",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"active": false,
|
|
"settings": {
|
|
"executionOrder": "v1"
|
|
},
|
|
"versionId": "",
|
|
"meta": {
|
|
"templateCredsSetupCompleted": false
|
|
},
|
|
"tags": []
|
|
}
|