{"updatedAt":"2026-08-09T18:35:05.746Z","createdAt":"2026-08-09T18:35:05.746Z","id":"U94mUWQ6EVwkpvhV","name":"Sino Contábil - Acompanhar resposta","description":null,"active":true,"isArchived":false,"nodes":[{"parameters":{"rule":{"interval":[{"field":"hours","hoursInterval":4}]}},"id":"cron","name":"A cada 4h","type":"n8n-nodes-base.scheduleTrigger","typeVersion":1.2,"position":[0,0]},{"parameters":{"jsCode":"\nconst fs = require('fs');\nconst LOG = '/home/ultimo/nf-pmo/enviados.json';\nif (!fs.existsSync(LOG)) return [{ json: { checar: 'nao' } }];\n\nconst log = JSON.parse(fs.readFileSync(LOG, 'utf8'));\n// pega o envio mais recente que ainda nao foi resolvido\nconst aberto = [...log].reverse().find(e => !e.acompanhamento_fechado && e.gmail_id);\nif (!aberto) return [{ json: { checar: 'nao' } }];\n\nconst horas = (Date.now() - new Date(aberto.em).getTime()) / 3600000;\nreturn [{ json: {\n  checar: 'sim',\n  thread_id: aberto.gmail_id,\n  referencia: aberto.referencia,\n  horas: Math.floor(horas),\n  passou48h: horas >= 48,\n}}];\n"},"id":"ver","name":"Ver pendência","type":"n8n-nodes-base.code","typeVersion":2,"position":[200,0]},{"parameters":{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"loose","version":2},"conditions":[{"id":"c","leftValue":"={{ $json.checar }}","rightValue":"sim","operator":{"type":"string","operation":"equals"}}],"combinator":"and"},"options":{}},"id":"Tem envio aberto","name":"Tem envio aberto","type":"n8n-nodes-base.if","typeVersion":2,"position":[400,0]},{"parameters":{"url":"=https://gmail.googleapis.com/gmail/v1/users/me/threads/{{ $json.thread_id }}?format=metadata","authentication":"predefinedCredentialType","nodeCredentialType":"gmailOAuth2","options":{}},"id":"thr","name":"Ler a conversa","type":"n8n-nodes-base.httpRequest","typeVersion":4.2,"position":[600,-60],"credentials":{"gmailOAuth2":{"id":"JrDIhubWWqvyxQA7","name":"Gmail account"}}},{"parameters":{"jsCode":"\nconst fs = require('fs');\nconst LOG = '/home/ultimo/nf-pmo/enviados.json';\nconst CONFIG = '/home/ultimo/nf-pmo/config.json';\nconst ctx = $('Ver pendência').first().json;\nconst thread = $input.first().json || {};\n\nlet chat = null;\ntry { chat = JSON.parse(fs.readFileSync(CONFIG, 'utf8')).chat_id; } catch (e) {}\nif (!chat) return [{ json: { avisar: 'nao' } }];\n\n// A thread comeca com a nossa mensagem. Mais de uma = alguem respondeu.\nconst mensagens = (thread.messages || []).length;\nconst responderam = mensagens > 1;\n\nif (!responderam && !ctx.passou48h) {\n  return [{ json: { avisar: 'nao', motivo: 'so ' + ctx.horas + 'h, ainda no prazo' } }];\n}\n\n// Quem respondeu, e o que disse\nlet quem = '', trecho = '';\nif (responderam) {\n  const ultima = thread.messages[thread.messages.length - 1];\n  const cab = ((ultima.payload || {}).headers || []);\n  quem = (cab.find(h => h.name === 'From') || {}).value || '';\n  quem = quem.split('<').pop().split('>')[0] || quem;\n  trecho = (ultima.snippet || '').slice(0, 120);\n}\n\nconst esc = (t) => String(t == null ? '' : t)\n  .split('&').join('&amp;').split('<').join('&lt;').split('>').join('&gt;');\n\nconst L = [];\nif (responderam) {\n  L.push('✅ <b>A prefeitura respondeu</b>');\n  L.push('');\n  L.push('NF ' + esc(ctx.referencia) + ' confirmada por ' + esc(quem) + '.');\n  if (trecho) L.push('');\n  if (trecho) L.push('<i>' + esc(trecho) + '</i>');\n} else {\n  L.push('⏰ <b>Ninguém respondeu ainda</b>');\n  L.push('');\n  L.push('A NF ' + esc(ctx.referencia) + ' foi enviada há ' + ctx.horas + ' horas e ' +\n         'nem protocolo, nem controladoria, nem a prefeitura acusaram recebimento.');\n  L.push('');\n  L.push('Em julho isso custou 5 dias. Vale cobrar.');\n}\n\n// marca como resolvido para nao repetir o aviso todo dia\nconst log = JSON.parse(fs.readFileSync(LOG, 'utf8'));\nfor (let i = log.length - 1; i >= 0; i--) {\n  if (log[i].gmail_id === ctx.thread_id) {\n    log[i].acompanhamento_fechado = true;\n    log[i].respondido = responderam;\n    if (responderam) log[i].respondido_por = quem;\n    break;\n  }\n}\nfs.writeFileSync(LOG, JSON.stringify(log, null, 2));\n\nconst body = JSON.stringify({ chat_id: chat, text: L.join('\\n'), parse_mode: 'HTML' });\nreturn [{ json: { avisar: 'sim', body } }];\n"},"id":"av","name":"Avaliar resposta","type":"n8n-nodes-base.code","typeVersion":2,"position":[800,-60]},{"parameters":{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"loose","version":2},"conditions":[{"id":"c","leftValue":"={{ $json.avisar }}","rightValue":"sim","operator":{"type":"string","operation":"equals"}}],"combinator":"and"},"options":{}},"id":"Precisa avisar","name":"Precisa avisar","type":"n8n-nodes-base.if","typeVersion":2,"position":[1000,-60]},{"parameters":{"method":"POST","url":"https://api.telegram.org/bot8722984812:AAHOvrtnsBokyTcaJi1ZNmIz8_mBq-ocd-0/sendMessage","sendBody":true,"specifyBody":"json","jsonBody":"={{ $json.body }}","options":{}},"id":"msg","name":"Avisar","type":"n8n-nodes-base.httpRequest","typeVersion":4.2,"position":[1200,-120]}],"connections":{"A cada 4h":{"main":[[{"node":"Ver pendência","type":"main","index":0}]]},"Ver pendência":{"main":[[{"node":"Tem envio aberto","type":"main","index":0}]]},"Tem envio aberto":{"main":[[{"node":"Ler a conversa","type":"main","index":0}],[]]},"Ler a conversa":{"main":[[{"node":"Avaliar resposta","type":"main","index":0}]]},"Avaliar resposta":{"main":[[{"node":"Precisa avisar","type":"main","index":0}]]},"Precisa avisar":{"main":[[{"node":"Avisar","type":"main","index":0}],[]]}},"settings":{"executionOrder":"v1","timezone":"America/Fortaleza","errorWorkflow":"rq9KzWVq6da7YiNQ","callerPolicy":"workflowsFromSameOwner","availableInMCP":false},"staticData":{"node:A cada 4h":{"recurrenceRules":[]}},"meta":null,"pinData":null,"versionId":"2b211dd1-c3c0-4e5a-ac88-0d2857b41b07","activeVersionId":"2b211dd1-c3c0-4e5a-ac88-0d2857b41b07","versionCounter":4,"triggerCount":1,"shared":[{"updatedAt":"2026-08-09T18:35:05.749Z","createdAt":"2026-08-09T18:35:05.749Z","role":"workflow:owner","workflowId":"U94mUWQ6EVwkpvhV","projectId":"lcNbFUrydUsxxeGp","project":{"updatedAt":"2026-05-06T16:07:04.097Z","createdAt":"2026-04-10T15:23:11.499Z","id":"lcNbFUrydUsxxeGp","name":"Ultimo Campos <ultimocampos@gmail.com>","type":"personal","icon":null,"description":null,"creatorId":"7fdfc85d-b5cb-411b-92ad-50cd2ccbad11"}}],"tags":[],"activeVersion":{"updatedAt":"2026-08-09T18:35:05.752Z","createdAt":"2026-08-09T18:35:05.752Z","versionId":"2b211dd1-c3c0-4e5a-ac88-0d2857b41b07","workflowId":"U94mUWQ6EVwkpvhV","nodes":[{"parameters":{"rule":{"interval":[{"field":"hours","hoursInterval":4}]}},"id":"cron","name":"A cada 4h","type":"n8n-nodes-base.scheduleTrigger","typeVersion":1.2,"position":[0,0]},{"parameters":{"jsCode":"\nconst fs = require('fs');\nconst LOG = '/home/ultimo/nf-pmo/enviados.json';\nif (!fs.existsSync(LOG)) return [{ json: { checar: 'nao' } }];\n\nconst log = JSON.parse(fs.readFileSync(LOG, 'utf8'));\n// pega o envio mais recente que ainda nao foi resolvido\nconst aberto = [...log].reverse().find(e => !e.acompanhamento_fechado && e.gmail_id);\nif (!aberto) return [{ json: { checar: 'nao' } }];\n\nconst horas = (Date.now() - new Date(aberto.em).getTime()) / 3600000;\nreturn [{ json: {\n  checar: 'sim',\n  thread_id: aberto.gmail_id,\n  referencia: aberto.referencia,\n  horas: Math.floor(horas),\n  passou48h: horas >= 48,\n}}];\n"},"id":"ver","name":"Ver pendência","type":"n8n-nodes-base.code","typeVersion":2,"position":[200,0]},{"parameters":{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"loose","version":2},"conditions":[{"id":"c","leftValue":"={{ $json.checar }}","rightValue":"sim","operator":{"type":"string","operation":"equals"}}],"combinator":"and"},"options":{}},"id":"Tem envio aberto","name":"Tem envio aberto","type":"n8n-nodes-base.if","typeVersion":2,"position":[400,0]},{"parameters":{"url":"=https://gmail.googleapis.com/gmail/v1/users/me/threads/{{ $json.thread_id }}?format=metadata","authentication":"predefinedCredentialType","nodeCredentialType":"gmailOAuth2","options":{}},"id":"thr","name":"Ler a conversa","type":"n8n-nodes-base.httpRequest","typeVersion":4.2,"position":[600,-60],"credentials":{"gmailOAuth2":{"id":"JrDIhubWWqvyxQA7","name":"Gmail account"}}},{"parameters":{"jsCode":"\nconst fs = require('fs');\nconst LOG = '/home/ultimo/nf-pmo/enviados.json';\nconst CONFIG = '/home/ultimo/nf-pmo/config.json';\nconst ctx = $('Ver pendência').first().json;\nconst thread = $input.first().json || {};\n\nlet chat = null;\ntry { chat = JSON.parse(fs.readFileSync(CONFIG, 'utf8')).chat_id; } catch (e) {}\nif (!chat) return [{ json: { avisar: 'nao' } }];\n\n// A thread comeca com a nossa mensagem. Mais de uma = alguem respondeu.\nconst mensagens = (thread.messages || []).length;\nconst responderam = mensagens > 1;\n\nif (!responderam && !ctx.passou48h) {\n  return [{ json: { avisar: 'nao', motivo: 'so ' + ctx.horas + 'h, ainda no prazo' } }];\n}\n\n// Quem respondeu, e o que disse\nlet quem = '', trecho = '';\nif (responderam) {\n  const ultima = thread.messages[thread.messages.length - 1];\n  const cab = ((ultima.payload || {}).headers || []);\n  quem = (cab.find(h => h.name === 'From') || {}).value || '';\n  quem = quem.split('<').pop().split('>')[0] || quem;\n  trecho = (ultima.snippet || '').slice(0, 120);\n}\n\nconst esc = (t) => String(t == null ? '' : t)\n  .split('&').join('&amp;').split('<').join('&lt;').split('>').join('&gt;');\n\nconst L = [];\nif (responderam) {\n  L.push('✅ <b>A prefeitura respondeu</b>');\n  L.push('');\n  L.push('NF ' + esc(ctx.referencia) + ' confirmada por ' + esc(quem) + '.');\n  if (trecho) L.push('');\n  if (trecho) L.push('<i>' + esc(trecho) + '</i>');\n} else {\n  L.push('⏰ <b>Ninguém respondeu ainda</b>');\n  L.push('');\n  L.push('A NF ' + esc(ctx.referencia) + ' foi enviada há ' + ctx.horas + ' horas e ' +\n         'nem protocolo, nem controladoria, nem a prefeitura acusaram recebimento.');\n  L.push('');\n  L.push('Em julho isso custou 5 dias. Vale cobrar.');\n}\n\n// marca como resolvido para nao repetir o aviso todo dia\nconst log = JSON.parse(fs.readFileSync(LOG, 'utf8'));\nfor (let i = log.length - 1; i >= 0; i--) {\n  if (log[i].gmail_id === ctx.thread_id) {\n    log[i].acompanhamento_fechado = true;\n    log[i].respondido = responderam;\n    if (responderam) log[i].respondido_por = quem;\n    break;\n  }\n}\nfs.writeFileSync(LOG, JSON.stringify(log, null, 2));\n\nconst body = JSON.stringify({ chat_id: chat, text: L.join('\\n'), parse_mode: 'HTML' });\nreturn [{ json: { avisar: 'sim', body } }];\n"},"id":"av","name":"Avaliar resposta","type":"n8n-nodes-base.code","typeVersion":2,"position":[800,-60]},{"parameters":{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"loose","version":2},"conditions":[{"id":"c","leftValue":"={{ $json.avisar }}","rightValue":"sim","operator":{"type":"string","operation":"equals"}}],"combinator":"and"},"options":{}},"id":"Precisa avisar","name":"Precisa avisar","type":"n8n-nodes-base.if","typeVersion":2,"position":[1000,-60]},{"parameters":{"method":"POST","url":"https://api.telegram.org/bot8722984812:AAHOvrtnsBokyTcaJi1ZNmIz8_mBq-ocd-0/sendMessage","sendBody":true,"specifyBody":"json","jsonBody":"={{ $json.body }}","options":{}},"id":"msg","name":"Avisar","type":"n8n-nodes-base.httpRequest","typeVersion":4.2,"position":[1200,-120]}],"connections":{"A cada 4h":{"main":[[{"node":"Ver pendência","type":"main","index":0}]]},"Ver pendência":{"main":[[{"node":"Tem envio aberto","type":"main","index":0}]]},"Tem envio aberto":{"main":[[{"node":"Ler a conversa","type":"main","index":0}],[]]},"Ler a conversa":{"main":[[{"node":"Avaliar resposta","type":"main","index":0}]]},"Avaliar resposta":{"main":[[{"node":"Precisa avisar","type":"main","index":0}]]},"Precisa avisar":{"main":[[{"node":"Avisar","type":"main","index":0}],[]]}},"authors":"Ultimo Campos","name":null,"description":null,"autosaved":false,"workflowPublishHistory":[{"createdAt":"2026-08-09T18:35:05.785Z","id":593,"workflowId":"U94mUWQ6EVwkpvhV","versionId":"2b211dd1-c3c0-4e5a-ac88-0d2857b41b07","event":"activated","userId":"7fdfc85d-b5cb-411b-92ad-50cd2ccbad11"}]}}