From 16bd98a7164dbc12b27dd243c6398cf796dd5651 Mon Sep 17 00:00:00 2001 From: Isaac_Aracena Date: Sun, 30 Aug 2026 04:00:57 +0000 Subject: [PATCH] Create backup: Cotizador WMC - Gmail Agent --- cotizador-wmc-gmail-agent.json | 8051 ++++++++++++++++++++++++++++++++ 1 file changed, 8051 insertions(+) create mode 100644 cotizador-wmc-gmail-agent.json diff --git a/cotizador-wmc-gmail-agent.json b/cotizador-wmc-gmail-agent.json new file mode 100644 index 0000000..a384b94 --- /dev/null +++ b/cotizador-wmc-gmail-agent.json @@ -0,0 +1,8051 @@ +{ + "updatedAt": "2026-08-30T00:43:39.289Z", + "createdAt": "2026-08-29T23:40:22.957Z", + "id": "p4rDtVLIWyPuK0LI", + "name": "Cotizador WMC - Gmail Agent", + "description": null, + "active": true, + "isArchived": false, + "nodes": [ + { + "parameters": { + "pollTimes": { + "item": [ + { + "mode": "everyMinute" + } + ] + }, + "simple": false, + "filters": { + "q": "from:iaracena@gomezleemarketing.com to:wmc@gomezlee.marketing" + }, + "options": { + "dataPropertyAttachmentsPrefixName": "attachment_", + "downloadAttachments": true + } + }, + "type": "n8n-nodes-base.gmailTrigger", + "typeVersion": 1.3, + "position": [ + -608, + 752 + ], + "id": "ab207f82-b390-4f05-bee8-8275c085aa13", + "name": "Gmail Trigger - WMC Inbox", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "jsCode": "const raw = $json || {};\nconst binary = $binary || {};\nconst hdr = {};\nfor (const h of (raw.payload?.headers || [])) {\n const k = String(h?.name || '').trim().toLowerCase();\n if (k) hdr[k] = String(h?.value || '');\n}\nfunction hv(name, fallback='') {\n const k = String(name).toLowerCase();\n return String(hdr[k] ?? raw[name] ?? raw.headers?.[k] ?? raw.headers?.[name] ?? fallback ?? '');\n}\nfunction decode64url(v) {\n if (!v) return '';\n try {\n let s = String(v).replace(/-/g,'+').replace(/_/g,'/');\n while (s.length % 4) s += '=';\n return Buffer.from(s,'base64').toString('utf8');\n } catch { return ''; }\n}\nfunction collect(part, texts, htmls) {\n if (!part || typeof part !== 'object') return;\n const mime = String(part.mimeType || '').toLowerCase();\n const decoded = decode64url(part.body?.data);\n if (decoded) {\n if (mime === 'text/plain') texts.push(decoded);\n else if (mime === 'text/html') htmls.push(decoded);\n }\n for (const p of (part.parts || [])) collect(p,texts,htmls);\n}\nconst texts=[], htmls=[]; collect(raw.payload || {}, texts, htmls);\nlet bodyText = String(raw.textPlain || raw.text || texts.join('\\n\\n') || raw.snippet || '').trim();\nlet bodyHtml = String(raw.textHtml || htmls.join('\\n\\n') || '').trim();\nif (!bodyText && bodyHtml) bodyText = bodyHtml.replace(//gi,' ').replace(//gi,' ').replace(//gi,'\\n').replace(/<\\/p>/gi,'\\n').replace(/<[^>]+>/g,' ').replace(/ /gi,' ').replace(/&/gi,'&').replace(/\\s+\\n/g,'\\n').replace(/\\n{3,}/g,'\\n\\n').trim();\nconst bodyTextFull = bodyText;\nfunction stripQuotedReply_(value) {\n let s=String(value||'').replace(/\\r\\n/g,'\\n').trim();\n // Gmail suele añadir el mensaje anterior tras “On ... wrote:” o “El ... escribió:”.\n // Cortamos solo esas respuestas citadas; NO eliminamos mensajes reenviados porque\n // pueden ser una solicitud operativa válida que el usuario haya reenviado.\n const replyMarkers=[\n /\\nOn [^\\n]{1,500} wrote:\\s*(?:\\n|$)/i,\n /\\nEl [^\\n]{1,500} escribi[oó]:\\s*(?:\\n|$)/i,\n /\\nLe [^\\n]{1,500} a écrit\\s*:\\s*(?:\\n|$)/i\n ];\n let cut=-1;\n for (const re of replyMarkers) { const m=re.exec(s); if(m && (cut<0 || m.index=0) s=s.slice(0,cut).trim();\n // Si solo quedan líneas quoteadas al final, no las enviamos al clasificador.\n const lines=s.split('\\n');\n const firstQuoted=lines.findIndex((line,i)=>i>0 && /^\\s*>/.test(line));\n if(firstQuoted>0) s=lines.slice(0,firstQuoted).join('\\n').trim();\n return s;\n}\nbodyText = stripQuotedReply_(bodyText) || bodyTextFull;\nfunction parseAddress(v) {\n const s=String(v||'').trim();\n const m=s.match(/<([^<>\\s]+@[^<>\\s]+)>/);\n const email=String(m?.[1] || (s.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}/i)||[])[0] || '').toLowerCase();\n let name=s.replace(/<[^>]+>/g,'').replace(/^\\s*[\"']|[\"']\\s*$/g,'').trim();\n if (!name || name===email) name='';\n return {email,name};\n}\nconst from=parseAddress(hv('From',raw.from));\nconst to=hv('To',raw.to); const cc=hv('Cc',raw.cc); const subject=hv('Subject',raw.Subject || '(Sin asunto)');\nconst gmailMessageId=String(raw.id || raw.messageId || '').trim();\nconst gmailThreadId=String(raw.threadId || '').trim();\nconst approvers=['jgomez@gomezleemarketing.com','wlopez@gomezleemarketing.com'];\nconst testSender='iaracena@gomezleemarketing.com';\nconst senderDomain=(from.email.split('@')[1]||'').toLowerCase();\nconst isApprover=approvers.includes(from.email);\nconst isAllowedRequester=(senderDomain==='walmart.com' || from.email===testSender);\nconst isSelf=(from.email==='wmc@gomezlee.marketing');\nconst attachmentMeta=[];\nfor (const [key,b] of Object.entries(binary)) {\n const fileName=String(b?.fileName || b?.fileName || key);\n const mediaType=String(b?.mimeType || b?.fileType || 'application/octet-stream');\n const size=Number(b?.fileSize || 0) || null;\n attachmentMeta.push({binaryKey:key,filename:fileName,mediaType,size});\n}\nconst textForCountry=(subject+'\\n'+bodyText).toLowerCase();\nconst countries=[['GT','guatemala'],['CR','costa rica'],['SV','el salvador'],['SV','salvador'],['HN','honduras'],['NI','nicaragua']];\nlet countryCode=null; for (const [c,t] of countries) if (textForCountry.includes(t)) {countryCode=c;break;}\nreturn [{json:{\n gmailMessageId,gmailThreadId,senderEmail:from.email,senderName:from.name,subject,to,cc,\n sentAt:hv('Date',new Date().toISOString()),bodyText,bodyTextFull,bodyHtml,attachmentMeta,countryCode,\n isApprover,isAllowedRequester,isSelf,approvers,testSender,\n source:'gmail',receivedAt:new Date().toISOString()\n},binary}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + -368, + 752 + ], + "id": "b3c728b0-d9d4-427d-baa0-10a2a80afa49", + "name": "Normalizar correo entrante" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "aaf3ccba-78a9-454f-9f14-b55bc667172c", + "leftValue": "={{ $json.isApprover === true && /\\[APROBACIÓN WMC\\]/i.test(String($json.subject || '')) }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 480, + 768 + ], + "id": "95c42b09-c38b-4d85-ad06-91025bafbc0c", + "name": "¿Respuesta de aprobador?" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "2599c6eb-9d4f-4442-a05a-baf138f2c35b", + "leftValue": "={{ $json.isAllowedRequester && !$json.isSelf }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 800, + 1376 + ], + "id": "e739c023-0e45-42f2-9ca4-3459b5722e63", + "name": "¿Remitente permitido?" + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 1040, + 1616 + ], + "id": "3fb50aa6-8dea-428f-8b12-b3b3ed54c22f", + "name": "Fin - Remitente ignorado" + }, + { + "parameters": { + "jsCode": "const bin=$binary||{}; const names=[];\nfor(const [k,b] of Object.entries(bin)){ const m=String(b?.mimeType||'').toLowerCase(), f=String(b?.fileName||''); if(m.startsWith('image/')||/\\.(png|jpe?g|webp|gif|bmp|heic|heif)$/i.test(f)) names.push(k); }\nreturn [{json:{...$json,hasImages:names.length>0,imageBinaryNames:names.join(',')},binary:bin}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1040, + 1376 + ], + "id": "e7808d43-d28b-4864-ada3-0a70d096a9c8", + "name": "Preparar imágenes email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "e5e507fd-a65e-4f07-ba4f-47ce85f79973", + "leftValue": "={{ $json.hasImages }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 1280, + 1376 + ], + "id": "fda52bfd-ce24-4c74-aff0-2b72d57690d7", + "name": "¿Tiene imágenes email?" + }, + { + "parameters": { + "resource": "image", + "operation": "analyze", + "modelId": { + "__rl": true, + "mode": "list", + "value": "models/gemini-2.5-pro" + }, + "text": "Analiza fielmente las imágenes adjuntas para una solicitud de cotización Walmart Connect. Extrae solo información visible o escrita relevante: marcas, producto, país, formato/tienda, cantidades, personal, uniformes, mobiliario, medidas, logística y observaciones. No inventes precios ni datos.", + "inputType": "binary", + "binaryPropertyName": "={{ $node[\"Preparar imágenes email\"].json.imageBinaryNames }}", + "options": { + "maxOutputTokens": 2200 + } + }, + "type": "@n8n/n8n-nodes-langchain.googleGemini", + "typeVersion": 1.1, + "position": [ + 1520, + 1216 + ], + "id": "a5566162-bb0b-4827-b9cc-f6c1ced415bf", + "name": "Gemini - Analizar imágenes email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googlePalmApi": { + "id": "jvsXYwL6IOoY2DBU", + "name": "Isaac - Gemini Api Pago" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "function txt(r){ if(!r||typeof r!=='object') return ''; for(const k of ['text','output','response','result','mergedResponse']) if(typeof r[k]==='string'&&r[k].trim()) return r[k].trim(); const p=r.content?.parts||r.candidates?.[0]?.content?.parts; if(Array.isArray(p)) return p.map(x=>x?.text||'').join('\\n').trim(); return ''; }\nconst base=$node[\"Preparar imágenes email\"].json; const t=txt($json); let trg={}; try{trg=$items(\"Gmail Trigger - WMC Inbox\")[0]||{};}catch{}\nreturn [{json:{...base,imageAnalysis:t||null,imageAnalysisError:base.hasImages&&!t},binary:trg.binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1760, + 1216 + ], + "id": "d700f366-212a-4637-8d45-aee19bb3e1bb", + "name": "Integrar análisis imágenes" + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,imageAnalysis:null,imageAnalysisError:false},binary:$binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1520, + 1536 + ], + "id": "3df9c929-8766-4cb8-919e-2f79e76e500c", + "name": "Sin imágenes email" + }, + { + "parameters": { + "jsCode": "const bin=$binary||{}; const names=[];\nfor(const [k,b] of Object.entries(bin)){ const m=String(b?.mimeType||'').toLowerCase(), f=String(b?.fileName||''); if(m==='application/pdf'||/\\.pdf$/i.test(f)) names.push(k); }\nreturn [{json:{...$json,hasPdfs:names.length>0,pdfBinaryNames:names.join(',')},binary:bin}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2000, + 1376 + ], + "id": "1af5b2f6-2f46-4c76-8206-b9066966e8dd", + "name": "Preparar PDFs email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "692b7118-2bee-4b0e-961b-e783688e914e", + "leftValue": "={{ $json.hasPdfs }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 2240, + 1376 + ], + "id": "648a0d41-45df-4e8a-9dec-01ca563b3cfb", + "name": "¿Tiene PDFs email?" + }, + { + "parameters": { + "resource": "document", + "modelId": { + "__rl": true, + "mode": "list", + "value": "models/gemini-2.5-pro" + }, + "text": "Analiza fielmente los PDF adjuntos para el Cotizador Walmart Connect. Extrae únicamente datos explícitos relevantes: país, anunciante, proyecto, fechas, formatos, tiendas, ubicación/cobertura, personal, cantidades, días, mobiliario, insumos, logística, medidas, condiciones y observaciones. No inventes información ni precios.", + "inputType": "binary", + "binaryPropertyName": "={{ $node[\"Preparar PDFs email\"].json.pdfBinaryNames }}", + "options": { + "maxOutputTokens": 2600 + } + }, + "type": "@n8n/n8n-nodes-langchain.googleGemini", + "typeVersion": 1.1, + "position": [ + 2480, + 1216 + ], + "id": "bd831472-87a5-4836-9e70-dba6c73d78f4", + "name": "Gemini - Analizar PDFs email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googlePalmApi": { + "id": "jvsXYwL6IOoY2DBU", + "name": "Isaac - Gemini Api Pago" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "function txt(r){ if(!r||typeof r!=='object') return ''; for(const k of ['text','output','response','result','mergedResponse']) if(typeof r[k]==='string'&&r[k].trim()) return r[k].trim(); const p=r.content?.parts||r.candidates?.[0]?.content?.parts; if(Array.isArray(p)) return p.map(x=>x?.text||'').join('\\n').trim(); return ''; }\nconst base=$node[\"Preparar PDFs email\"].json; const t=txt($json); let trg={}; try{trg=$items(\"Gmail Trigger - WMC Inbox\")[0]||{};}catch{}\nreturn [{json:{...base,documentAnalysis:t||null,documentAnalysisError:base.hasPdfs&&!t},binary:trg.binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2720, + 1216 + ], + "id": "bf272474-9aae-43fc-b879-0d94a65c31ef", + "name": "Integrar análisis PDFs" + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,documentAnalysis:null,documentAnalysisError:false},binary:$binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2480, + 1536 + ], + "id": "92a5a7dd-7cc2-4548-bf3b-ec0d91306277", + "name": "Sin PDFs email" + }, + { + "parameters": { + "jsCode": "const bin=$binary||{}; const names=[];\nfor(const [k,b] of Object.entries(bin)){ const m=String(b?.mimeType||'').toLowerCase(), f=String(b?.fileName||''); if(m.startsWith('audio/')||/\\.(webm|mp3|wav|m4a|ogg|oga|aac|flac|mpeg|mpga)$/i.test(f)) names.push(k); }\nreturn [{json:{...$json,hasAudio:names.length>0,audioBinaryNames:names.join(',')},binary:bin}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2960, + 1376 + ], + "id": "a1dd4f45-724b-4846-84a7-5427087de6cd", + "name": "Preparar audio email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "f0e66802-b149-4681-8953-4deaf95f1a07", + "leftValue": "={{ $json.hasAudio }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 3200, + 1216 + ], + "id": "7e36fa54-ba65-4439-bd2a-6a4b5fa36a80", + "name": "¿Tiene audio email?" + }, + { + "parameters": { + "resource": "audio", + "modelId": { + "__rl": true, + "value": "models/gemini-2.5-pro", + "mode": "list", + "cachedResultName": "models/gemini-2.5-pro" + }, + "inputType": "binary", + "binaryPropertyName": "={{ $node[\"Preparar audio email\"].json.audioBinaryNames }}", + "options": {} + }, + "type": "@n8n/n8n-nodes-langchain.googleGemini", + "typeVersion": 1.1, + "position": [ + 3440, + 1056 + ], + "id": "1eb02117-3fa7-4a60-81fe-4d2e7b13d296", + "name": "Gemini - Transcribir audio email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googlePalmApi": { + "id": "jvsXYwL6IOoY2DBU", + "name": "Isaac - Gemini Api Pago" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "function txt(r){ if(!r||typeof r!=='object') return ''; for(const k of ['text','output','response','result','mergedResponse']) if(typeof r[k]==='string'&&r[k].trim()) return r[k].trim(); const p=r.content?.parts||r.candidates?.[0]?.content?.parts; if(Array.isArray(p)) return p.map(x=>x?.text||'').join('\\n').trim(); return ''; }\nconst base=$node[\"Preparar audio email\"].json; const t=txt($json); let trg={}; try{trg=$items(\"Gmail Trigger - WMC Inbox\")[0]||{};}catch{}\nreturn [{json:{...base,audioTranscription:t||null,audioTranscriptionError:base.hasAudio&&!t},binary:trg.binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3680, + 1056 + ], + "id": "187cb874-b625-4376-8ec1-323d7fd676ca", + "name": "Integrar transcripción audio" + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,audioTranscription:null,audioTranscriptionError:false},binary:$binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3440, + 1376 + ], + "id": "07bf21a9-1f3b-4e4f-8777-080b1f43533b", + "name": "Sin audio email" + }, + { + "parameters": { + "jsCode": "const bin=$binary||{}; const keys=[];\nfor(const [k,b] of Object.entries(bin)){ const m=String(b?.mimeType||'').toLowerCase(), f=String(b?.fileName||''); if(m==='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'||/\\.xlsx$/i.test(f)) keys.push(k); }\nconst supported=new Set(keys); const unsupported=($json.attachmentMeta||[]).filter(a=>{const m=String(a.mediaType||'').toLowerCase(),f=String(a.filename||''); return !(m.startsWith('image/')||m.startsWith('audio/')||m==='application/pdf'||/\\.(png|jpe?g|webp|gif|bmp|heic|heif|webm|mp3|wav|m4a|ogg|oga|aac|flac|mpeg|mpga|pdf|xlsx)$/i.test(f));});\nreturn [{json:{...$json,hasXlsx:keys.length>0,xlsxBinaryKeys:keys,unsupportedAttachments:unsupported},binary:bin}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3920, + 1216 + ], + "id": "26a4ac9d-2a64-4b24-a2af-2e4caab7c197", + "name": "Preparar XLSX email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "eaadc66d-c3f5-417d-b945-5397809d08b9", + "leftValue": "={{ $json.hasXlsx }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 4848, + 1088 + ], + "id": "6c433395-f347-45a6-bd7e-5d0c37b4bd9f", + "name": "¿Tiene XLSX email?" + }, + { + "parameters": { + "jsCode": "const base=$json, bin=$binary||{}, keys=Array.isArray(base.xlsxBinaryKeys)?base.xlsxBinaryKeys:[]; const out=[]; let i=0;\nfor(const k of keys){const b=bin[k]; if(!b) continue; i++; const fn=String(b.fileName||`archivo-${i}.xlsx`); out.push({json:{...base,xlsxIndex:i-1,xlsxFilename:fn,tempUploadName:`_TEMP_WMC_EMAIL_XLSX_${Date.now()}_${i}_${fn.replace(/[^a-zA-Z0-9._-]+/g,'_').slice(0,90)}`},binary:{data:b}})}\nreturn out.length?out:[{json:{...base,hasXlsx:false}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 5088, + 928 + ], + "id": "76c6166e-02e0-4119-89c6-babb7682c06a", + "name": "Expandir XLSX email" + }, + { + "parameters": { + "name": "={{ $json.tempUploadName }}", + "driveId": { + "__rl": true, + "value": "My Drive", + "mode": "list" + }, + "folderId": { + "__rl": true, + "value": "root", + "mode": "list", + "cachedResultName": "/ (Root folder)" + }, + "options": { + "simplifyOutput": true + } + }, + "type": "n8n-nodes-base.googleDrive", + "typeVersion": 3, + "position": [ + 5328, + 928 + ], + "id": "262b6267-8259-407d-a105-831750270537", + "name": "Subir XLSX email temporal a Drive", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const ups=$input.all(); let src=[]; try{src=$items(\"Expandir XLSX email\");}catch{} return ups.map((it,i)=>({json:{...(src[i]?.json||{}),tempXlsxDriveId:String(it.json?.id||'')||null,tempXlsxUploadError:it.json?.error||null},pairedItem:{item:i}}));" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 5568, + 928 + ], + "id": "53d5ef62-ba53-4a13-abf0-02223658ac6d", + "name": "Mapear XLSX email temporal" + }, + { + "parameters": { + "method": "POST", + "url": "={{ 'https://www.googleapis.com/drive/v2/files/' + encodeURIComponent($json.tempXlsxDriveId || 'invalid') + '/copy?convert=true' }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "options": { + "timeout": 60000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 5808, + 928 + ], + "id": "212fa06d-0a76-4e04-a540-7a101a26d283", + "name": "Convertir XLSX email a Google Sheets", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const xs=$input.all(); let src=[]; try{src=$items(\"Mapear XLSX email temporal\");}catch{} return xs.map((it,i)=>({json:{...(src[i]?.json||{}),tempGoogleSheetId:String(it.json?.id||'')||null,tempGoogleSheetMimeType:String(it.json?.mimeType||''),tempConversionError:it.json?.error||null},pairedItem:{item:i}}));" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 6048, + 928 + ], + "id": "c30d3b4a-58f2-45fd-ad7e-b9f3773c930f", + "name": "Mapear XLSX convertido email" + }, + { + "parameters": { + "url": "={{ 'https://sheets.googleapis.com/v4/spreadsheets/' + encodeURIComponent($json.tempGoogleSheetId || 'invalid') }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "sendQuery": true, + "queryParameters": { + "parameters": [ + { + "name": "includeGridData", + "value": "true" + }, + { + "name": "fields", + "value": "spreadsheetId,properties(title),sheets(properties(sheetId,title,index,hidden,gridProperties(rowCount,columnCount)),data(startRow,startColumn,rowData(values(formattedValue,effectiveValue))))" + } + ] + }, + "options": { + "timeout": 90000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 6288, + 928 + ], + "id": "555ba82c-e8ca-488a-b817-db114a0b9954", + "name": "Leer todas las hojas XLSX email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Preparar XLSX email\"].json; const incoming=$input.all(); let metas=[]; try{metas=$items(\"Mapear XLSX convertido email\");}catch{}\nconst MAX=70000, ROWS=1500, COLS=100, SHEETS=40; let chars=0,trunc=false; const blocks=[],inventory=[],warn=[];\nconst clean=v=>String(v??'').replace(/[\\u0000-\\u001F]+/g,' ').replace(/\\s+/g,' ').trim();\nfunction col(i){let n=i+1,s='';while(n){const r=(n-1)%26;s=String.fromCharCode(65+r)+s;n=Math.floor((n-1)/26);}return s;}\nfunction val(c){if(!c||typeof c!=='object')return'';if(c.formattedValue!=null)return clean(c.formattedValue);const e=c.effectiveValue||{};for(const k of ['stringValue','numberValue','boolValue','formulaValue'])if(e[k]!=null)return clean(e[k]);return'';}\nfor(let fi=0;fi=MAX){trunc=true;break;}const p=sh?.properties||{}, sn=clean(p.title||`Hoja ${names.length+1}`);names.push(sn);const rm=new Map();for(const g of (sh.data||[])){const sr=Number(g?.startRow||0),sc=Number(g?.startColumn||0);for(let r=0;r<(g.rowData||[]).length;r++){const ar=sr+r;if(ar>=ROWS){trunc=true;break;}for(let c=0;c<(g.rowData[r]?.values||[]).length;c++){const ac=sc+c;if(ac>=COLS){trunc=true;break;}const v=val(g.rowData[r].values[c]);if(v){if(!rm.has(ar))rm.set(ar,new Map());rm.get(ar).set(ac,v);}}}}const lines=[];for(const r of [...rm.keys()].sort((a,b)=>a-b)){const cells=[...rm.get(r).entries()].sort((a,b)=>a[0]-b[0]);const line=`Fila ${r+1}: `+cells.map(([c,v])=>`[${col(c)}] ${v}`).join(' | ');if(chars+line.length>MAX){trunc=true;break;}lines.push(line);chars+=line.length+1;}blocks.push(`Archivo: ${fn}\\nHoja analizada: ${sn}${p.hidden?' (oculta)':''}\\n${lines.length?lines.join('\\n'):'(Sin contenido legible)'}`);}inventory.push({file:fn,sheets:names});}\nif(trunc)warn.push('Extracción XLSX truncada por límite de seguridad.');\nreturn [{json:{...base,spreadsheetAnalysis:blocks.join('\\n\\n').trim()||null,spreadsheetAnalysisError:blocks.length===0,spreadsheetSheetNames:inventory,spreadsheetExtractionWarnings:warn}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 6528, + 928 + ], + "id": "e25959cf-4a9d-440d-89e6-e77732472f69", + "name": "Agregar análisis XLSX email" + }, + { + "parameters": { + "jsCode": "let metas=[];try{metas=$items(\"Mapear XLSX convertido email\");}catch{}const out=[],seen=new Set();for(const m0 of metas){const m=m0.json||{};for(const id0 of [m.tempGoogleSheetId,m.tempXlsxDriveId]){const id=String(id0||'').trim();if(id&&!seen.has(id)){seen.add(id);out.push({json:{deleteFileId:id}});}}}return out.length?out:[{json:{deleteFileId:null}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 6768, + 928 + ], + "id": "959e39a9-fd46-4ae5-b9f5-2ee81f418988", + "name": "Preparar limpieza XLSX email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "873da85e-f479-4fe3-85b3-95c6f9c105e8", + "leftValue": "={{ !!$json.deleteFileId }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 7008, + 928 + ], + "id": "c992c380-1830-4340-9adf-a54fc401df24", + "name": "¿Hay temporal XLSX?" + }, + { + "parameters": { + "operation": "deleteFile", + "fileId": { + "__rl": true, + "value": "={{ $json.deleteFileId }}", + "mode": "id" + }, + "options": { + "deletePermanently": true + } + }, + "type": "n8n-nodes-base.googleDrive", + "typeVersion": 3, + "position": [ + 7248, + 800 + ], + "id": "d924d82b-5ff6-4ab6-b84c-369cce1a95eb", + "name": "Eliminar temporal XLSX email", + "retryOnFail": true, + "maxTries": 2, + "waitBetweenTries": 1500, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Agregar análisis XLSX email\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 7488, + 800 + ], + "id": "0d5af946-c85f-47f4-a11f-a947696196af", + "name": "Restaurar base tras limpieza XLSX" + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Agregar análisis XLSX email\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 7248, + 1040 + ], + "id": "8d0f1365-ea58-4f3f-9fcd-edcc09773181", + "name": "Restaurar base sin limpieza XLSX" + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,spreadsheetAnalysis:null,spreadsheetAnalysisError:false,spreadsheetSheetNames:[],spreadsheetExtractionWarnings:[]}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 5088, + 1248 + ], + "id": "3dfe6356-38d4-4be1-b08a-18ff31309002", + "name": "Sin XLSX email" + }, + { + "parameters": { + "jsCode": "return [{json:$json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 7728, + 1088 + ], + "id": "b447a80b-ee83-4c9d-850e-a2dfe62f1a9a", + "name": "Base email lista para agente" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_ingest", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.gmailThreadId,p_gmail_message_id:$json.gmailMessageId,p_sender_email:$json.senderEmail,p_sender_name:$json.senderName,p_subject:$json.subject,p_body_text:$json.bodyText,p_body_html:$json.bodyHtml||null,p_attachments:$json.attachmentMeta||[],p_country_code:$json.countryCode||null}) }", + "options": { + "timeout": 40000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 7968, + 1088 + ], + "id": "26cb64c2-0b25-4d30-b054-d2a991ba468f", + "name": "Supabase - Ingestar email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500 + }, + { + "parameters": { + "jsCode": "const base=$node[\"Base email lista para agente\"].json; const raw=$json||{}; const ing=raw.body&&typeof raw.body==='object'?raw.body:(raw.data&&typeof raw.data==='object'?raw.data:raw);\nconst parts=[String(base.bodyText||'').trim()];\nif(base.imageAnalysis)parts.push('[ANÁLISIS REAL DE IMÁGENES ADJUNTAS]\\n'+base.imageAnalysis);\nif(base.documentAnalysis)parts.push('[ANÁLISIS REAL DE PDF ADJUNTOS]\\n'+base.documentAnalysis);\nif(base.audioTranscription)parts.push('[TRANSCRIPCIÓN REAL DE AUDIO ADJUNTO]\\n'+base.audioTranscription);\nif(base.spreadsheetAnalysis)parts.push('[CONTENIDO REAL EXTRAÍDO DE XLSX ADJUNTO]\\n'+base.spreadsheetAnalysis);\nif((base.unsupportedAttachments||[]).length)parts.push('[ADJUNTOS NO ANALIZADOS AUTOMÁTICAMENTE]\\n'+base.unsupportedAttachments.map(a=>`${a.filename} (${a.mediaType})`).join('\\n'));\nreturn [{json:{...base,ingest:ing,agentRequest:{gmailThreadId:base.gmailThreadId,gmailMessageId:base.gmailMessageId,senderEmail:base.senderEmail,senderName:base.senderName,text:parts.filter(Boolean).join('\\n\\n'),attachments:[],countryCode:base.countryCode,history:Array.isArray(ing.history)?ing.history:[],context:ing.context&&typeof ing.context==='object'?ing.context:{},emailMeta:{subject:base.subject,to:base.to,cc:base.cc,sentAt:base.sentAt,attachmentMeta:base.attachmentMeta||[],spreadsheetSheetNames:base.spreadsheetSheetNames||[]}}}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 8208, + 1088 + ], + "id": "02146f13-9a85-4727-8d27-a81a1c3d07fa", + "name": "Construir solicitud agente email" + }, + { + "parameters": { + "method": "POST", + "url": "https://agenteit.digitalcompass.agency/webhook/cotizador-wmc-email-agent", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "Content-Type", + "value": "application/json" + }, + { + "name": "X-WMC-Internal-Secret", + "value": "fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={{ JSON.stringify($json.agentRequest) }}", + "options": { + "timeout": 240000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 8448, + 1088 + ], + "id": "d13eba8c-3cc5-4c21-a8f8-a60b048d15ee", + "name": "Agente WMC - Procesar email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 4000, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Construir solicitud agente email\"].json; const raw=$json||{}; const a=(raw.body&&typeof raw.body==='object')?raw.body:raw; const cfg=base.ingest?.config||{};\nconst disposition=String(a.emailDisposition||'process').toLowerCase(); const action=String(a.action||'chat'); const quote=a.quote&&typeof a.quote==='object'?a.quote:null; const total=Number(quote?.totalUsd||0)||0; const threshold=Number(cfg.approval_threshold_usd??cfg.approvalThresholdUsd??10000)||10000;\nconst nonTariff=[]; if(quote&&Array.isArray(quote.items)){for(const it of quote.items){const amount=Math.abs(Number(it?.totalUsd||0));if(!(amount>0))continue;const code=String(it?.metadata?.priceSourceCode||it?.priceSourceCode||'').toUpperCase();if(code!=='T')nonTariff.push({description:String(it?.description||''),code:code||'E',amount});}}\nconst reasons=[];if(total>threshold)reasons.push({code:'OVER_10000',text:`Total USD ${total.toFixed(2)} supera el umbral de USD ${threshold.toFixed(2)}.`});if(nonTariff.length)reasons.push({code:'NON_TARIFF',text:`${nonTariff.length} partida(s) usan referencia fuera del tarifario oficial.`,items:nonTariff});\nconst approvalRequired=!!quote && ['generate_quote','generate_proposal','generate_monthly_glm'].includes(action) && reasons.length>0;\nconst generatedActions=['generate_quote','generate_proposal','generate_monthly_glm','generate_image'];\nconst artifactFailure=generatedActions.includes(action) && !a.artifactUrl;\nif(artifactFailure){\n a.reply='No pude generar el archivo solicitado en este momento. Por favor responde a este mismo correo para reintentarlo.';\n a.warnings=[...(Array.isArray(a.warnings)?a.warnings:[]),'El artefacto no fue generado; no se envió ningún archivo.'];\n}\nlet customerMode='final'; if(disposition==='ignore')customerMode='ignore'; else if(action==='chat'||artifactFailure)customerMode='clarification'; else if(approvalRequired)customerMode='approval';\nconst artifactType=String(a.artifactType||''); const artifactId=String(a.artifactId||''); const shouldExport=!!artifactId&&['quote','proposal','monthly_glm'].includes(artifactType);\nreturn [{json:{...base,agent:a,config:cfg,customerMode,approvalRequired,approvalReasons:reasons,nonTariffItems:nonTariff,totalUsd:total,thresholdUsd:threshold,artifactType,artifactId,artifactUrl:a.artifactUrl||null,artifactTitle:a.title||quote?.project||'WMC',quote,shouldExport,artifactFailure}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 8688, + 1088 + ], + "id": "339b335b-e1ad-4696-92a3-43c4bcb7d437", + "name": "Evaluar respuesta agente email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "93182a6b-e065-4c35-93a8-e5c81bcddd2b", + "leftValue": "={{ $json.customerMode }}", + "rightValue": "ignore", + "operator": { + "type": "string", + "operation": "equals", + "name": "filter.operator.equals" + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 8928, + 1088 + ], + "id": "81685b4e-e097-456a-8a99-511234820fc6", + "name": "¿Ignorar correo?" + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 9168, + 928 + ], + "id": "f80493b2-681c-491c-a844-605f26421534", + "name": "Fin - Correo fuera de alcance" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "257b6ccb-e648-4422-bd6d-025089fed298", + "leftValue": "={{ $json.approvalRequired }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 9168, + 1248 + ], + "id": "e8fc2f77-6ee2-4c75-916c-975c282e8fde", + "name": "¿Requiere aprobación interna?" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_create_approval", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.gmailThreadId,p_quote:$json.quote,p_document_url:$json.artifactUrl,p_artifact_id:$json.artifactId,p_artifact_type:$json.artifactType,p_artifact_title:$json.artifactTitle,p_customer_gmail_message_id:$json.gmailMessageId,p_reason:$json.approvalReasons}) }", + "options": { + "timeout": 40000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 9408, + 1488 + ], + "id": "d14f3a22-591f-495a-9f49-63f218e8dbe0", + "name": "Supabase - Crear aprobación email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500 + }, + { + "parameters": { + "jsCode": "const base=$node[\"Evaluar respuesta agente email\"].json;const raw=$json||{};const r=raw.body&&typeof raw.body==='object'?raw.body:raw;const approvalId=String(r.approvalId||'');\nconst esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nconst q=base.quote||{};const items=(base.nonTariffItems||[]).map(x=>`
  • ${esc(x.code)} · ${esc(x.description)} · USD ${Number(x.amount||0).toFixed(2)}
  • `).join('');\nconst reasons=(base.approvalReasons||[]).map(x=>`
    ${esc(x.text)}
    `).join('');\nconst html=`
    \"GomezLee
    COTIZADOR WALMART CONNECT · APROBACIÓN INTERNA

    Cotización pendiente de aprobación

    El agente preparó una cotización recibida por correo que no puede enviarse automáticamente.

    ${reasons}
    Proyecto${esc(q.project||'—')}
    Anunciante${esc(q.advertiser||'—')}
    País${esc(q.country||q.countryCode||'—')}
    Solicitante${esc(base.senderEmail)}
    TotalUSD ${Number(base.totalUsd||0).toFixed(2)}
    ${items?`
    Partidas fuera de tarifario
      ${items}
    `:''}
    Para decidir, responde a este mismo correo:
    APROBAR · envía la cotización al cliente.
    RECHAZAR · no la envía.
    CAMBIAR: seguido de la modificación solicitada · el agente regenera el borrador y vuelve a pedir aprobación.
    ${base.artifactUrl?`

    Abrir borrador en Google Workspace

    `:''}
    Referencia interna: ${esc(approvalId)}
    `;\nconst approverEmails=(Array.isArray(base.config?.approver_emails)?base.config.approver_emails:(Array.isArray(base.emailConfig?.approver_emails)?base.emailConfig.approver_emails:['jgomez@gomezleemarketing.com','wlopez@gomezleemarketing.com'])).map(x=>String(x||'').trim()).filter(Boolean);return [{json:{...base,approvalId,requiredApprovals:Number(r.requiredApprovals||1),approvalSubject:`[APROBACIÓN WMC] ${q.project||q.advertiser||'Cotización'} · USD ${Number(base.totalUsd||0).toFixed(2)}`,approvalHtml:html,approverList:approverEmails.join(', '),approverEmails}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 9648, + 1488 + ], + "id": "f15c6913-b9ee-47f9-9eb8-03529ff1b481", + "name": "Preparar correo aprobación GLM" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "dccfd9d3-857b-4b82-a269-6eef3029549d", + "leftValue": "={{ $json.shouldExport }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 9888, + 1488 + ], + "id": "5a76b54f-0585-438c-ad80-be0c812e27ad", + "name": "¿Adjuntar borrador a aprobación?" + }, + { + "parameters": { + "url": "={{ 'https://www.googleapis.com/drive/v3/files/' + encodeURIComponent($json.artifactId) + '/export?mimeType=' + encodeURIComponent($json.artifactType === 'proposal' ? 'application/pdf' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "options": { + "response": { + "response": { + "responseFormat": "file" + } + }, + "timeout": 90000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 10320, + 1408 + ], + "id": "975d8649-99b7-41d0-993a-ce032b6fd94a", + "name": "Descargar borrador para aprobación", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Preparar correo aprobación GLM\"].json;const b=$binary?.data||null;if(b){b.fileName=(String(base.artifactTitle||'Cotizacion_WMC').replace(/[^a-zA-Z0-9._-]+/g,'_').slice(0,100))+(base.artifactType==='proposal'?'.pdf':'.xlsx');b.mimeType=base.artifactType==='proposal'?'application/pdf':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';}\nreturn [{json:{...base,exportOk:!!b},binary:b?{data:b}:{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 10560, + 1408 + ], + "id": "79448614-99a4-4125-a885-baf0f2da5d9f", + "name": "Preparar adjunto aprobación" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "7eb6cac5-d384-4161-9ac3-7b4ade92b248", + "leftValue": "={{ $json.exportOk }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 11008, + 1376 + ], + "id": "24d47913-b611-4203-ae4b-04be6e8311b9", + "name": "¿Borrador descargado?" + }, + { + "parameters": { + "sendTo": "=iaracena@gomezleemarketing.com", + "subject": "={{ $json.approvalSubject }}", + "message": "={{ $json.approvalHtml }}", + "options": { + "appendAttribution": false, + "attachmentsUi": { + "attachmentsBinary": [ + {} + ] + }, + "senderName": "Walmart Connect | GomezLee Marketing" + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11552, + 1264 + ], + "id": "bf6b11ec-3341-42ad-b433-316684ad660c", + "name": "Gmail - Enviar aprobación con adjunto", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "64450f47-d0b4-424f-a091-341c4a34c2cd", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "sendTo": "=iaracena@gomezleemarketing.com", + "subject": "={{ $json.approvalSubject }}", + "message": "={{ $json.approvalHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect | GomezLee Marketing" + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11776, + 1472 + ], + "id": "cc24abfe-a768-4cb8-a227-575a8695bcd6", + "name": "Gmail - Enviar aprobación sin adjunto", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "b538ae39-7ec0-496a-a263-ce5263a9499f", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,exportOk:false}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 10992, + 1856 + ], + "id": "5c3cec29-debb-4d98-8a51-6fcba1561663", + "name": "Preparar aprobación sin exportar" + }, + { + "parameters": { + "sendTo": "=iaracena@gomezleemarketing.com", + "subject": "={{ $json.approvalSubject }}", + "message": "={{ $json.approvalHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect | GomezLee Marketing" + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11232, + 1856 + ], + "id": "78b06108-0570-4e13-939b-0c722ff2fdcb", + "name": "Gmail - Enviar aprobación solo enlace", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "f13b8337-eee5-4a66-846d-908c2ea31ad9", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_set_approval_gmail_thread", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_id:$node['Preparar correo aprobación GLM'].json.approvalId,p_approval_gmail_thread_id:$json.threadId,p_approval_gmail_message_id:$json.id}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 13376, + 1680 + ], + "id": "5a9dafcd-c828-433b-aa0b-1d7d56fc5316", + "name": "Supabase - Vincular hilo de aprobación", + "continueOnFail": true + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_record_message", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$node['Evaluar respuesta agente email'].json.gmailThreadId,p_gmail_message_id:'approval-out-'+$node['Preparar correo aprobación GLM'].json.approvalId,p_direction:'internal_out',p_from_email:'wmc@gomezlee.marketing',p_to_emails:$node['Preparar correo aprobación GLM'].json.approverEmails,p_subject:$node['Preparar correo aprobación GLM'].json.approvalSubject,p_body_text:'Solicitud de aprobación interna de cotización WMC.',p_body_html:$node['Preparar correo aprobación GLM'].json.approvalHtml,p_attachments:[],p_metadata:{approvalId:$node['Preparar correo aprobación GLM'].json.approvalId},p_status:'pending_approval'}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 13616, + 1680 + ], + "id": "e7d604e0-1355-4350-8869-3c363498d708", + "name": "Supabase - Registrar solicitud aprobación", + "continueOnFail": true + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 13856, + 1680 + ], + "id": "c599c6f8-093e-459e-8390-b14279ccebe8", + "name": "Fin - Esperando aprobación" + }, + { + "parameters": { + "jsCode": "const b=$json;const a=b.agent||{};const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const name=String(b.senderName||'').trim();const greeting=name?`Hola ${esc(name.split(/\\s+/)[0])},`:'Hola,';const reply=esc(a.reply||'').replace(/\\n/g,'
    ');const isClar=b.customerMode==='clarification';const title=isClar?'Necesitamos una confirmación para continuar':'Cotización Walmart Connect';const intro=isClar?'Gracias por tu solicitud. Para continuar correctamente necesitamos confirmar lo siguiente:':'La solicitud fue procesada. Encontrarás el archivo correspondiente adjunto o disponible en el enlace incluido.';\nconst html=`
    \"Walmart

    ${esc(title)}

    ${greeting}

    ${esc(intro)}

    ${reply||'Listo.'}
    ${!isClar&&b.artifactUrl?`

    Abrir archivo en Google Workspace

    `:''}${isClar?'

    Por favor responde a este mismo correo con la información solicitada y continuaremos desde aquí.

    ':'

    Quedamos atentos a cualquier comentario o ajuste.

    '}
    Walmart Connect · Gestión automatizada de cotizaciones
    `;return [{json:{...b,customerHtml:html,customerSubject:b.subject}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 9408, + 1168 + ], + "id": "ee0eab64-c0ec-4e4b-800b-e1942931944c", + "name": "Construir HTML cliente Walmart" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "e94406c9-0285-4541-ab19-a06c44a85b99", + "leftValue": "={{ $json.customerMode }}", + "rightValue": "clarification", + "operator": { + "type": "string", + "operation": "equals", + "name": "filter.operator.equals" + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 9648, + 1168 + ], + "id": "b5f91adb-ca7d-4f7c-8680-a6697855b7d1", + "name": "¿Es aclaración?" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 10192, + 752 + ], + "id": "92fd8304-6172-4aa1-8067-cf2edc56905f", + "name": "Gmail - Responder aclaración cliente", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "160a5c37-d2e5-4ae9-8c18-327091bf22e5", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "1aebba2a-7e1b-47b2-b464-7835a163efe1", + "leftValue": "={{ $json.shouldExport }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 9888, + 1280 + ], + "id": "f58741f6-91f1-4843-b35c-619046a2839e", + "name": "¿Adjuntar archivo al cliente?" + }, + { + "parameters": { + "url": "={{ 'https://www.googleapis.com/drive/v3/files/' + encodeURIComponent($json.artifactId) + '/export?mimeType=' + encodeURIComponent($json.artifactType === 'proposal' ? 'application/pdf' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "options": { + "response": { + "response": { + "responseFormat": "file" + } + }, + "timeout": 90000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 10208, + 1008 + ], + "id": "f43c7d77-f75f-4e9c-b067-92d62b151074", + "name": "Descargar artefacto para cliente", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Construir HTML cliente Walmart\"].json;const b=$binary?.data||null;if(b){b.fileName=(String(base.artifactTitle||'Cotizacion_WMC').replace(/[^a-zA-Z0-9._-]+/g,'_').slice(0,100))+(base.artifactType==='proposal'?'.pdf':'.xlsx');b.mimeType=base.artifactType==='proposal'?'application/pdf':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';}return [{json:{...base,exportOk:!!b},binary:b?{data:b}:{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 10448, + 1008 + ], + "id": "3d6acf36-9b2a-46b2-8253-3bba8b2e09bc", + "name": "Preparar adjunto cliente" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "f45ceb76-0896-4be4-bd24-03175f38373c", + "leftValue": "={{ $json.exportOk }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 10736, + 976 + ], + "id": "f9f98ee7-51c2-4c8d-948d-bfc26f480705", + "name": "¿Archivo cliente descargado?" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "attachmentsUi": { + "attachmentsBinary": [ + {} + ] + }, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11248, + 656 + ], + "id": "c7b347ba-e3a0-47b7-87ec-5f60858a0162", + "name": "Gmail - Responder cliente con archivo", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "ced5a909-e80a-4a90-8da6-cdd9b9f2d13d", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11088, + 1088 + ], + "id": "d1706a6c-4fb8-46c7-aba1-2e0b63ccc99a", + "name": "Gmail - Responder cliente sin archivo", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "541a4fe0-64c3-4eb0-acbe-65f3082d2845", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 10320, + 1184 + ], + "id": "01ba8fb0-98c7-4f97-a5d6-1b0d754ddee8", + "name": "Gmail - Responder cliente solo enlace", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "7520e58c-aa85-4301-be4d-b74d633610b4", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "jsCode": "const base=$node[\"Construir HTML cliente Walmart\"].json;const g=$json||{};return [{json:{...base,sentGmailMessageId:String(g.id||''),sentGmailThreadId:String(g.threadId||base.gmailThreadId),sentOk:!!g.id}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 11632, + 928 + ], + "id": "7ba23678-b7c4-4681-b8c5-75eadefb8977", + "name": "Postprocesar envío cliente" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "d974d8c2-6e06-41e0-880c-a2ab2f81f641", + "leftValue": "={{ !!$json.quote && $json.customerMode === \"final\" }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 11872, + 928 + ], + "id": "793b94a2-a6d0-4c0b-8ca8-a611dc5c975f", + "name": "¿Guardar quote enviado?" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_save_sent_quote", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.gmailThreadId,p_quote:$json.quote,p_document_url:$json.artifactUrl,p_artifact_id:$json.artifactId,p_artifact_type:$json.artifactType,p_artifact_title:$json.artifactTitle,p_sent_gmail_message_id:$json.sentGmailMessageId}) }", + "options": { + "timeout": 40000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 12368, + 800 + ], + "id": "d691d86e-23bc-4834-8651-3e35072b0c25", + "name": "Supabase - Guardar cotización enviada", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Postprocesar envío cliente\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 12608, + 800 + ], + "id": "7698dbfb-1fac-4906-bf24-5a0a6316a48c", + "name": "Restaurar post envío tras guardar" + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Postprocesar envío cliente\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 12464, + 1232 + ], + "id": "35274e8e-3527-4bb2-9b96-a23c40c6ab22", + "name": "Continuar sin guardar quote" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_record_message", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.gmailThreadId,p_gmail_message_id:$json.sentGmailMessageId,p_direction:'outbound',p_from_email:'wmc@gomezlee.marketing',p_to_emails:[$json.senderEmail],p_subject:$json.subject,p_body_text:$json.agent.reply||'',p_body_html:$json.customerHtml,p_attachments:$json.customerMode==='final'&&$json.artifactUrl?[{filename:$json.artifactTitle||'WMC',mediaType:$json.artifactType||'artifact',url:$json.artifactUrl}]:[],p_metadata:{action:$json.agent.action||'chat',artifactUrl:$json.artifactUrl||null},p_status:$json.customerMode==='clarification'?'awaiting_clarification':'sent'}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 13408, + 1248 + ], + "id": "5463d643-ff69-4a0e-bdcc-02a71bc746ec", + "name": "Supabase - Registrar respuesta al cliente", + "continueOnFail": true + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 13648, + 1248 + ], + "id": "87ab6e4b-9587-4a2d-abe9-011ba22e31b7", + "name": "Fin - Email cliente procesado" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_get_pending_approval", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_gmail_thread_id:$json.gmailThreadId,p_approver_email:$json.senderEmail}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 720, + 448 + ], + "id": "2885f662-e411-420a-bb10-e12588d7c594", + "name": "Supabase - Buscar aprobación pendiente", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const mail=$node[\"Normalizar correo entrante\"].json;\nconst raw=$json||{};\nconst r=raw.body&&typeof raw.body==='object'?raw.body:raw;\nconst found=!!r.found;\nconst normalize=v=>String(v||'').toLowerCase().normalize('NFD').replace(/[\\u0300-\\u036f]/g,'').replace(/\\s+/g,' ').trim();\nconst text=normalize(mail.bodyText||'');\nlet decision='change';\n// Se evalúa únicamente la respuesta nueva (el texto citado de Gmail ya fue retirado).\nif (/^(rechazar|rechazo|no aprobar|no apruebo|cancelar)\\b/.test(text)) decision='reject';\nelse if (/^(aprobar|apruebo|aprobado|confirmo|confirmado|adelante)\\b/.test(text)) decision='approve';\nelse if (/^(cambiar|cambio|modificar|ajustar|corregir)\\b/.test(text)) decision='change';\nreturn [{json:{...mail,pending:r,found,approval:r.approval||null,customerThread:r.customerThread||null,history:r.history||[],context:r.context||{},approvalDecision:decision,approvalInstructions:mail.bodyText}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 960, + 448 + ], + "id": "87090417-f5f4-492a-a9f3-ee99a77f92d2", + "name": "Preparar respuesta de aprobación" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "2391c203-8c51-436b-a7c4-62e86f2963d1", + "leftValue": "={{ $json.found }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 1200, + 448 + ], + "id": "80a80c46-df48-4e3c-b658-db1f72f8bb8b", + "name": "¿Aprobación pendiente encontrada?" + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 1440, + 208 + ], + "id": "2c48258c-8563-4f1b-9ca4-37d5ac6d93cc", + "name": "Fin - Sin aprobación pendiente" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_record_message", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.customerThread.gmailThreadId,p_gmail_message_id:$json.gmailMessageId,p_direction:'internal_in',p_from_email:$json.senderEmail,p_to_emails:['wmc@gomezlee.marketing'],p_subject:$json.subject,p_body_text:$json.bodyText,p_body_html:$json.bodyHtml||null,p_attachments:$json.attachmentMeta||[],p_metadata:{approvalId:$json.approval.id},p_status:'pending_approval'}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 1440, + 528 + ], + "id": "a0fcc6ee-8aa6-4f58-8506-626bfbe42ba0", + "name": "Supabase - Registrar respuesta aprobador", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Preparar respuesta de aprobación\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1680, + 528 + ], + "id": "a362cd2f-e5ac-4bd5-a6e0-6279fef142b1", + "name": "Restaurar aprobación tras registro" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "70b77420-e9f5-45c2-a5ce-ba7c06d88ef9", + "leftValue": "={{ $json.approvalDecision }}", + "rightValue": "change", + "operator": { + "type": "string", + "operation": "equals", + "name": "filter.operator.equals" + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 1920, + 528 + ], + "id": "5be3f8fa-7c0b-4e38-b9fe-a4ce636fd7d2", + "name": "¿Solicita cambios internos?" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_decide_approval", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_id:$json.approval.id,p_approver_email:$json.senderEmail,p_decision:$json.approvalDecision,p_note:$json.bodyText}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 2160, + 688 + ], + "id": "1d1234b9-dc97-480e-803f-8661b31645cb", + "name": "Supabase - Decidir aprobación", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Restaurar aprobación tras registro\"].json;const raw=$json||{};const r=raw.body&&typeof raw.body==='object'?raw.body:raw;return [{json:{...base,decisionResult:r,finalDecision:String(r.finalDecision||''),approvalFinalOk:r.ok!==false}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2400, + 688 + ], + "id": "6230ea05-3cc2-4de8-a6f6-5cbd64936aa7", + "name": "Evaluar decisión interna" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "75942c37-1cb3-4221-a5ee-01dca0898f55", + "leftValue": "={{ $json.finalDecision }}", + "rightValue": "approved", + "operator": { + "type": "string", + "operation": "equals", + "name": "filter.operator.equals" + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 2640, + 688 + ], + "id": "cc0e5278-4017-477d-944b-8531f812179d", + "name": "¿Aprobado final?" + }, + { + "parameters": { + "jsCode": "const b=$json;const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const rejected=b.finalDecision==='rejected';const msg=rejected?'La cotización fue rechazada y no se enviará al cliente.':'La aprobación quedó registrada y continúa pendiente de las aprobaciones requeridas.';const html=`

    ${rejected?'Cotización rechazada':'Aprobación registrada'}

    ${esc(msg)}

    `;return [{json:{...b,internalAckHtml:html}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2880, + 848 + ], + "id": "13d60b72-4de5-413f-8091-ac9a615d2b60", + "name": "Preparar confirmación decisión interna" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.internalAckHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 3120, + 848 + ], + "id": "c827ea05-0996-430d-818d-99c01e3decf6", + "name": "Gmail - Confirmar decisión al aprobador", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "23dccd92-8d02-43bd-bca5-c96ce84abd6c", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 3360, + 848 + ], + "id": "63689e52-aad6-468f-8e61-9a851ae73c07", + "name": "Fin - Decisión interna registrada" + }, + { + "parameters": { + "jsCode": "const b=$json;const a=b.approval||{};const q=a.candidateQuote||b.decisionResult?.candidateQuote||{};const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const html=`

    Cotización Walmart Connect

    Hola,

    Adjunto encontrarás la cotización solicitada para ${esc(q.project||'el proyecto indicado')}.

    ${a.artifactUrl?`

    Abrir cotización en Google Workspace

    `:''}

    Quedamos atentos a cualquier comentario o ajuste.

    `;const type=String(a.artifactType||'');return [{json:{...b,quote:q,artifactId:a.artifactId,artifactUrl:a.artifactUrl,artifactType:type,artifactTitle:a.artifactTitle||q.project||'Cotizacion WMC',customerHtml:html,customerMessageId:a.customerGmailMessageId,shouldExport:!!a.artifactId&&['quote','proposal','monthly_glm'].includes(type)}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2880, + 528 + ], + "id": "6325982d-9758-4b41-9b54-abb442790169", + "name": "Preparar envío aprobado al cliente" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "d25c7755-c533-472c-b27e-62b8a46da16e", + "leftValue": "={{ $json.shouldExport }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 3120, + 528 + ], + "id": "9fc5b7cf-f07f-48a3-96fe-dc48e432030d", + "name": "¿Adjuntar archivo aprobado?" + }, + { + "parameters": { + "url": "={{ 'https://www.googleapis.com/drive/v3/files/' + encodeURIComponent($json.artifactId) + '/export?mimeType=' + encodeURIComponent($json.artifactType === 'proposal' ? 'application/pdf' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "options": { + "response": { + "response": { + "responseFormat": "file" + } + }, + "timeout": 90000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 3504, + 272 + ], + "id": "3d9f2351-adea-48f2-a349-54d2fd3556ec", + "name": "Descargar artefacto aprobado", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Preparar envío aprobado al cliente\"].json;const b=$binary?.data||null;if(b){b.fileName=(String(base.artifactTitle||'Cotizacion_WMC').replace(/[^a-zA-Z0-9._-]+/g,'_').slice(0,100))+(base.artifactType==='proposal'?'.pdf':'.xlsx');b.mimeType=base.artifactType==='proposal'?'application/pdf':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';}return [{json:{...base,exportOk:!!b},binary:b?{data:b}:{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3744, + 272 + ], + "id": "074c1f03-b7bc-4d8d-a25c-76fa616db4d1", + "name": "Preparar adjunto aprobado" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "6d87afdd-9702-4c7a-809a-38f5b7331a0f", + "leftValue": "={{ $json.exportOk }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 4240, + 224 + ], + "id": "14065d5b-400d-432f-b30e-83f3e408c1ff", + "name": "¿Archivo aprobado descargado?" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.customerMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "attachmentsUi": { + "attachmentsBinary": [ + {} + ] + }, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 4480, + 144 + ], + "id": "9b7f449f-2574-432c-b318-32c475f10ea7", + "name": "Gmail - Enviar aprobado con archivo", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "ab9cd32a-ae42-48f1-87ba-26e33714c900", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.customerMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 4480, + 352 + ], + "id": "a326b49f-39cd-41c1-aa43-670e4f348933", + "name": "Gmail - Enviar aprobado sin archivo", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "ff99c43e-af13-44ec-8ed5-63b891dbb5a5", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.customerMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 3360, + 640 + ], + "id": "7448f893-a0da-49d4-a0c8-6ac38f4a5459", + "name": "Gmail - Enviar aprobado solo enlace", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "0a92c11b-b768-4729-ac5a-d6547891db37", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "jsCode": "const base=$node[\"Preparar envío aprobado al cliente\"].json;const g=$json||{};return [{json:{...base,sentGmailMessageId:String(g.id||''),sentGmailThreadId:String(g.threadId||base.customerThread?.gmailThreadId||'')}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 5360, + 384 + ], + "id": "506a308d-aaec-4d24-8634-9fdbe8aeeddc", + "name": "Postprocesar envío aprobado" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_mark_approval_sent", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_id:$json.approval.id,p_sent_gmail_message_id:$json.sentGmailMessageId}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 5600, + 384 + ], + "id": "a1f193f6-61e8-42d9-a5dc-9dfa58b5da87", + "name": "Supabase - Marcar aprobación enviada", + "continueOnFail": true + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_record_message", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$node['Postprocesar envío aprobado'].json.customerThread.gmailThreadId,p_gmail_message_id:$node['Postprocesar envío aprobado'].json.sentGmailMessageId,p_direction:'outbound',p_from_email:'wmc@gomezlee.marketing',p_to_emails:[$node['Postprocesar envío aprobado'].json.customerThread.requesterEmail],p_subject:$node['Postprocesar envío aprobado'].json.customerThread.subject,p_body_text:'Cotización aprobada y enviada.',p_body_html:$node['Postprocesar envío aprobado'].json.customerHtml,p_attachments:[{filename:$node['Postprocesar envío aprobado'].json.artifactTitle,mediaType:$node['Postprocesar envío aprobado'].json.artifactType,url:$node['Postprocesar envío aprobado'].json.artifactUrl}],p_metadata:{approvalId:$node['Postprocesar envío aprobado'].json.approval.id},p_status:'sent'}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 5840, + 384 + ], + "id": "9299ffeb-f273-4512-8c6a-029931e7139f", + "name": "Supabase - Registrar envío aprobado cliente", + "continueOnFail": true + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 6080, + 384 + ], + "id": "ad781ca1-ba7b-4850-ae31-2ed33cb7cf05", + "name": "Fin - Aprobación enviada al cliente" + }, + { + "parameters": { + "jsCode": "const b=$node[\"Restaurar aprobación tras registro\"].json;const a=b.approval||{};return [{json:{...b,revisionRequest:{gmailThreadId:b.customerThread.gmailThreadId,gmailMessageId:b.gmailMessageId,senderEmail:b.senderEmail,senderName:b.senderName,text:`Revisión interna autorizada por ${b.senderEmail}:\\n${b.approvalInstructions}`,attachments:[],countryCode:b.customerThread.countryCode||null,history:b.history||[],context:b.context||{},emailMeta:{subject:b.customerThread.subject,internalApproval:true,approverEmail:b.senderEmail,requesterEmail:b.customerThread.requesterEmail},approvalRevision:{approvalId:a.id,approverEmail:b.senderEmail,instructions:b.approvalInstructions,candidateQuote:a.candidateQuote,artifactUrl:a.artifactUrl}}}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2160, + 368 + ], + "id": "3e523ab8-90fb-431e-ad5b-384ee83e03a7", + "name": "Preparar revisión interna para agente" + }, + { + "parameters": { + "method": "POST", + "url": "https://agenteit.digitalcompass.agency/webhook/cotizador-wmc-email-agent", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "Content-Type", + "value": "application/json" + }, + { + "name": "X-WMC-Internal-Secret", + "value": "fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={{ JSON.stringify($json.revisionRequest) }}", + "options": { + "timeout": 240000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 2400, + 368 + ], + "id": "b9b37eb4-bedb-4bf4-b29e-983835b05c59", + "name": "Agente WMC - Aplicar cambios aprobador", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 4000, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const b=$node[\"Preparar revisión interna para agente\"].json;const raw=$json||{};const a=raw.body&&typeof raw.body==='object'?raw.body:raw;const ready=!!(a.quote&&a.artifactUrl&&a.artifactId)&&a.action!=='chat';const q=a.quote||{};const nonT=[];for(const it of (q.items||[])){if(Number(it.totalUsd||0)>0){const c=String(it?.metadata?.priceSourceCode||'').toUpperCase()||'E';if(c!=='T')nonT.push({description:it.description,code:c,amount:Number(it.totalUsd||0)});}}const reasons=[];if(Number(q.totalUsd||0)>10000)reasons.push({code:'OVER_10000',text:`Total USD ${Number(q.totalUsd).toFixed(2)} supera USD 10,000.`});if(nonT.length)reasons.push({code:'NON_TARIFF',text:`${nonT.length} partida(s) fuera de tarifario.`,items:nonT});return [{json:{...b,revisionAgent:a,revisionReady:ready,revisionQuote:a.quote||null,revisionArtifactId:a.artifactId||null,revisionArtifactUrl:a.artifactUrl||null,revisionArtifactType:a.artifactType||null,revisionArtifactTitle:a.title||q.project||'WMC',revisionReasons:reasons}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2640, + 368 + ], + "id": "6e2488a6-0781-45da-8fd5-e2ec64fab9ff", + "name": "Evaluar revisión interna" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "21c1085b-3260-4823-8161-2d59fba12d14", + "leftValue": "={{ $json.revisionReady }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 2880, + 368 + ], + "id": "fe12a681-17e1-4863-aebe-eb77df9fec26", + "name": "¿Revisión regenerada?" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_replace_approval_candidate", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_id:$json.approval.id,p_approver_email:$json.senderEmail,p_quote:$json.revisionQuote,p_document_url:$json.revisionArtifactUrl,p_artifact_id:$json.revisionArtifactId,p_artifact_type:$json.revisionArtifactType,p_artifact_title:$json.revisionArtifactTitle,p_reason:$json.revisionReasons}) }", + "options": { + "timeout": 40000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 3264, + -16 + ], + "id": "d2205239-e261-4540-89f3-8ec3b95bcae8", + "name": "Supabase - Reemplazar candidato aprobación", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const b=$node[\"Evaluar revisión interna\"].json;const q=b.revisionQuote||{};const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const html=`

    Borrador actualizado

    Se aplicaron los cambios solicitados. El nuevo total es USD ${Number(q.totalUsd||0).toFixed(2)}.

    ${b.revisionArtifactUrl?`

    Abrir borrador actualizado

    `:''}
    Responde a este hilo con APROBAR, RECHAZAR o CAMBIAR: ...
    `;return [{json:{...b,internalRevisionHtml:html}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3504, + -16 + ], + "id": "4b0e8f7e-8f97-4c15-b1dc-ad0cb3e6a3d0", + "name": "Preparar confirmación revisión GLM" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.internalRevisionHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 3744, + -16 + ], + "id": "bd39629e-7f00-4024-8e06-b97b76da06ea", + "name": "Gmail - Enviar borrador actualizado al aprobador", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "b5b19d95-d7d7-456e-ba99-2c60e80498a9", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 3984, + -16 + ], + "id": "31181c4a-f6fe-43b0-96a2-784e0d809824", + "name": "Fin - Revisión pendiente nueva decisión" + }, + { + "parameters": { + "jsCode": "const b=$json;const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const msg=esc(b.revisionAgent?.reply||'Necesito una precisión adicional para aplicar el cambio.').replace(/\\n/g,'
    ');const html=`

    Necesito confirmar un detalle del cambio

    ${msg}

    Responde a este mismo correo con la aclaración.

    `;return [{json:{...b,internalRevisionHtml:html}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3152, + 320 + ], + "id": "175d6f84-a294-41e3-bedd-9ebd7f3215d2", + "name": "Preparar aclaración cambio al aprobador" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.internalRevisionHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 3616, + 464 + ], + "id": "5ecffd80-3047-438f-9855-30ee11bc5704", + "name": "Gmail - Pedir aclaración al aprobador", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "e282116c-ad2a-4509-8f12-be7e95b06c14", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 3856, + 464 + ], + "id": "f85e6ffd-e7f0-4732-b161-ceed68521561", + "name": "Fin - Esperando aclaración aprobador" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_get_config", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={{ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08'}) }}", + "options": { + "timeout": 20000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + -32, + 528 + ], + "id": "74d66de7-d63a-4400-ba2b-498c01800035", + "name": "Supabase - Config canal email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 1500 + }, + { + "parameters": { + "jsCode": "const mail=$node[\"Normalizar correo entrante\"].json;\nconst raw=$json||{};\nconst cfg=(raw.body&&typeof raw.body==='object')?raw.body:(raw.data&&typeof raw.data==='object'?raw.data:raw);\nconst enabled=cfg.enabled===true || String(cfg.enabled||'').toLowerCase()==='true';\nconst allowTest=cfg.allow_test_sender===true || cfg.allowTestSender===true || String(cfg.allow_test_sender??cfg.allowTestSender??'').toLowerCase()==='true';\nconst testSender=String(cfg.test_sender_email??cfg.testSenderEmail??'iaracena@gomezleemarketing.com').trim().toLowerCase();\nconst walmartDomain=String(cfg.walmart_sender_domain??cfg.walmartSenderDomain??'walmart.com').trim().toLowerCase();\nconst approversRaw=cfg.approver_emails??cfg.approverEmails??['jgomez@gomezleemarketing.com','wlopez@gomezleemarketing.com'];\nconst approvers=(Array.isArray(approversRaw)?approversRaw:String(approversRaw||'').split(',')).map(x=>String(x||'').trim().toLowerCase()).filter(Boolean);\nconst sender=String(mail.senderEmail||'').trim().toLowerCase();\nconst domain=(sender.split('@')[1]||'').toLowerCase();\nconst isApprover=approvers.includes(sender);\nconst isSelf=sender==='wmc@gomezlee.marketing';\nconst isAllowedRequester=enabled && !isSelf && (domain===walmartDomain || (allowTest && sender===testSender));\nreturn [{json:{...mail,emailConfig:cfg,emailEnabled:enabled,allowTestSender:allowTest,testSender,walmartSenderDomain:walmartDomain,approvers,isApprover,isSelf,isAllowedRequester}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 208, + 528 + ], + "id": "f0a4115a-e0c8-44ec-bf85-47cff0143b0a", + "name": "Aplicar configuración canal email" + } + ], + "connections": { + "Gmail Trigger - WMC Inbox": { + "main": [ + [ + { + "node": "Normalizar correo entrante", + "type": "main", + "index": 0 + } + ] + ] + }, + "Normalizar correo entrante": { + "main": [ + [ + { + "node": "Supabase - Config canal email", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Respuesta de aprobador?": { + "main": [ + [ + { + "node": "Supabase - Buscar aprobación pendiente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "¿Remitente permitido?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Remitente permitido?": { + "main": [ + [ + { + "node": "Preparar imágenes email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Fin - Remitente ignorado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar imágenes email": { + "main": [ + [ + { + "node": "¿Tiene imágenes email?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Tiene imágenes email?": { + "main": [ + [ + { + "node": "Gemini - Analizar imágenes email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Sin imágenes email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gemini - Analizar imágenes email": { + "main": [ + [ + { + "node": "Integrar análisis imágenes", + "type": "main", + "index": 0 + } + ] + ] + }, + "Integrar análisis imágenes": { + "main": [ + [ + { + "node": "Preparar PDFs email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sin imágenes email": { + "main": [ + [ + { + "node": "Preparar PDFs email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar PDFs email": { + "main": [ + [ + { + "node": "¿Tiene PDFs email?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Tiene PDFs email?": { + "main": [ + [ + { + "node": "Gemini - Analizar PDFs email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Sin PDFs email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gemini - Analizar PDFs email": { + "main": [ + [ + { + "node": "Integrar análisis PDFs", + "type": "main", + "index": 0 + } + ] + ] + }, + "Integrar análisis PDFs": { + "main": [ + [ + { + "node": "Preparar audio email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sin PDFs email": { + "main": [ + [ + { + "node": "Preparar audio email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar audio email": { + "main": [ + [ + { + "node": "¿Tiene audio email?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Tiene audio email?": { + "main": [ + [ + { + "node": "Gemini - Transcribir audio email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Sin audio email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gemini - Transcribir audio email": { + "main": [ + [ + { + "node": "Integrar transcripción audio", + "type": "main", + "index": 0 + } + ] + ] + }, + "Integrar transcripción audio": { + "main": [ + [ + { + "node": "Preparar XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sin audio email": { + "main": [ + [ + { + "node": "Preparar XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar XLSX email": { + "main": [ + [ + { + "node": "¿Tiene XLSX email?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Tiene XLSX email?": { + "main": [ + [ + { + "node": "Expandir XLSX email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Sin XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Expandir XLSX email": { + "main": [ + [ + { + "node": "Subir XLSX email temporal a Drive", + "type": "main", + "index": 0 + } + ] + ] + }, + "Subir XLSX email temporal a Drive": { + "main": [ + [ + { + "node": "Mapear XLSX email temporal", + "type": "main", + "index": 0 + } + ] + ] + }, + "Mapear XLSX email temporal": { + "main": [ + [ + { + "node": "Convertir XLSX email a Google Sheets", + "type": "main", + "index": 0 + } + ] + ] + }, + "Convertir XLSX email a Google Sheets": { + "main": [ + [ + { + "node": "Mapear XLSX convertido email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Mapear XLSX convertido email": { + "main": [ + [ + { + "node": "Leer todas las hojas XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Leer todas las hojas XLSX email": { + "main": [ + [ + { + "node": "Agregar análisis XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Agregar análisis XLSX email": { + "main": [ + [ + { + "node": "Preparar limpieza XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar limpieza XLSX email": { + "main": [ + [ + { + "node": "¿Hay temporal XLSX?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Hay temporal XLSX?": { + "main": [ + [ + { + "node": "Eliminar temporal XLSX email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Restaurar base sin limpieza XLSX", + "type": "main", + "index": 0 + } + ] + ] + }, + "Eliminar temporal XLSX email": { + "main": [ + [ + { + "node": "Restaurar base tras limpieza XLSX", + "type": "main", + "index": 0 + } + ] + ] + }, + "Restaurar base tras limpieza XLSX": { + "main": [ + [ + { + "node": "Base email lista para agente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Restaurar base sin limpieza XLSX": { + "main": [ + [ + { + "node": "Base email lista para agente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sin XLSX email": { + "main": [ + [ + { + "node": "Base email lista para agente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Base email lista para agente": { + "main": [ + [ + { + "node": "Supabase - Ingestar email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Ingestar email": { + "main": [ + [ + { + "node": "Construir solicitud agente email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Construir solicitud agente email": { + "main": [ + [ + { + "node": "Agente WMC - Procesar email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Agente WMC - Procesar email": { + "main": [ + [ + { + "node": "Evaluar respuesta agente email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Evaluar respuesta agente email": { + "main": [ + [ + { + "node": "¿Ignorar correo?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Ignorar correo?": { + "main": [ + [ + { + "node": "Fin - Correo fuera de alcance", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "¿Requiere aprobación interna?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Requiere aprobación interna?": { + "main": [ + [ + { + "node": "Supabase - Crear aprobación email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Construir HTML cliente Walmart", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Crear aprobación email": { + "main": [ + [ + { + "node": "Preparar correo aprobación GLM", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar correo aprobación GLM": { + "main": [ + [ + { + "node": "¿Adjuntar borrador a aprobación?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Adjuntar borrador a aprobación?": { + "main": [ + [ + { + "node": "Descargar borrador para aprobación", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Preparar aprobación sin exportar", + "type": "main", + "index": 0 + } + ] + ] + }, + "Descargar borrador para aprobación": { + "main": [ + [ + { + "node": "Preparar adjunto aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar adjunto aprobación": { + "main": [ + [ + { + "node": "¿Borrador descargado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Borrador descargado?": { + "main": [ + [ + { + "node": "Gmail - Enviar aprobación con adjunto", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Enviar aprobación sin adjunto", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar aprobación sin exportar": { + "main": [ + [ + { + "node": "Gmail - Enviar aprobación solo enlace", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobación con adjunto": { + "main": [ + [ + { + "node": "Supabase - Vincular hilo de aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobación sin adjunto": { + "main": [ + [ + { + "node": "Supabase - Vincular hilo de aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobación solo enlace": { + "main": [ + [ + { + "node": "Supabase - Vincular hilo de aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Vincular hilo de aprobación": { + "main": [ + [ + { + "node": "Supabase - Registrar solicitud aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Registrar solicitud aprobación": { + "main": [ + [ + { + "node": "Fin - Esperando aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Construir HTML cliente Walmart": { + "main": [ + [ + { + "node": "¿Es aclaración?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Es aclaración?": { + "main": [ + [ + { + "node": "Gmail - Responder aclaración cliente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "¿Adjuntar archivo al cliente?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Adjuntar archivo al cliente?": { + "main": [ + [ + { + "node": "Descargar artefacto para cliente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Responder cliente solo enlace", + "type": "main", + "index": 0 + } + ] + ] + }, + "Descargar artefacto para cliente": { + "main": [ + [ + { + "node": "Preparar adjunto cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar adjunto cliente": { + "main": [ + [ + { + "node": "¿Archivo cliente descargado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Archivo cliente descargado?": { + "main": [ + [ + { + "node": "Gmail - Responder cliente con archivo", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Responder cliente sin archivo", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Responder aclaración cliente": { + "main": [ + [ + { + "node": "Postprocesar envío cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Responder cliente con archivo": { + "main": [ + [ + { + "node": "Postprocesar envío cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Responder cliente sin archivo": { + "main": [ + [ + { + "node": "Postprocesar envío cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Responder cliente solo enlace": { + "main": [ + [ + { + "node": "Postprocesar envío cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Postprocesar envío cliente": { + "main": [ + [ + { + "node": "¿Guardar quote enviado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Guardar quote enviado?": { + "main": [ + [ + { + "node": "Supabase - Guardar cotización enviada", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Continuar sin guardar quote", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Guardar cotización enviada": { + "main": [ + [ + { + "node": "Restaurar post envío tras guardar", + "type": "main", + "index": 0 + } + ] + ] + }, + "Restaurar post envío tras guardar": { + "main": [ + [ + { + "node": "Supabase - Registrar respuesta al cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Continuar sin guardar quote": { + "main": [ + [ + { + "node": "Supabase - Registrar respuesta al cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Registrar respuesta al cliente": { + "main": [ + [ + { + "node": "Fin - Email cliente procesado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Buscar aprobación pendiente": { + "main": [ + [ + { + "node": "Preparar respuesta de aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar respuesta de aprobación": { + "main": [ + [ + { + "node": "¿Aprobación pendiente encontrada?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Aprobación pendiente encontrada?": { + "main": [ + [ + { + "node": "Supabase - Registrar respuesta aprobador", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Fin - Sin aprobación pendiente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Registrar respuesta aprobador": { + "main": [ + [ + { + "node": "Restaurar aprobación tras registro", + "type": "main", + "index": 0 + } + ] + ] + }, + "Restaurar aprobación tras registro": { + "main": [ + [ + { + "node": "¿Solicita cambios internos?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Solicita cambios internos?": { + "main": [ + [ + { + "node": "Preparar revisión interna para agente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Supabase - Decidir aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Decidir aprobación": { + "main": [ + [ + { + "node": "Evaluar decisión interna", + "type": "main", + "index": 0 + } + ] + ] + }, + "Evaluar decisión interna": { + "main": [ + [ + { + "node": "¿Aprobado final?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Aprobado final?": { + "main": [ + [ + { + "node": "Preparar envío aprobado al cliente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Preparar confirmación decisión interna", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar confirmación decisión interna": { + "main": [ + [ + { + "node": "Gmail - Confirmar decisión al aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Confirmar decisión al aprobador": { + "main": [ + [ + { + "node": "Fin - Decisión interna registrada", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar envío aprobado al cliente": { + "main": [ + [ + { + "node": "¿Adjuntar archivo aprobado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Adjuntar archivo aprobado?": { + "main": [ + [ + { + "node": "Descargar artefacto aprobado", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Enviar aprobado solo enlace", + "type": "main", + "index": 0 + } + ] + ] + }, + "Descargar artefacto aprobado": { + "main": [ + [ + { + "node": "Preparar adjunto aprobado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar adjunto aprobado": { + "main": [ + [ + { + "node": "¿Archivo aprobado descargado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Archivo aprobado descargado?": { + "main": [ + [ + { + "node": "Gmail - Enviar aprobado con archivo", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Enviar aprobado sin archivo", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobado con archivo": { + "main": [ + [ + { + "node": "Postprocesar envío aprobado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobado sin archivo": { + "main": [ + [ + { + "node": "Postprocesar envío aprobado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobado solo enlace": { + "main": [ + [ + { + "node": "Postprocesar envío aprobado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Postprocesar envío aprobado": { + "main": [ + [ + { + "node": "Supabase - Marcar aprobación enviada", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Marcar aprobación enviada": { + "main": [ + [ + { + "node": "Supabase - Registrar envío aprobado cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Registrar envío aprobado cliente": { + "main": [ + [ + { + "node": "Fin - Aprobación enviada al cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar revisión interna para agente": { + "main": [ + [ + { + "node": "Agente WMC - Aplicar cambios aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Agente WMC - Aplicar cambios aprobador": { + "main": [ + [ + { + "node": "Evaluar revisión interna", + "type": "main", + "index": 0 + } + ] + ] + }, + "Evaluar revisión interna": { + "main": [ + [ + { + "node": "¿Revisión regenerada?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Revisión regenerada?": { + "main": [ + [ + { + "node": "Supabase - Reemplazar candidato aprobación", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Preparar aclaración cambio al aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Reemplazar candidato aprobación": { + "main": [ + [ + { + "node": "Preparar confirmación revisión GLM", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar confirmación revisión GLM": { + "main": [ + [ + { + "node": "Gmail - Enviar borrador actualizado al aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar borrador actualizado al aprobador": { + "main": [ + [ + { + "node": "Fin - Revisión pendiente nueva decisión", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar aclaración cambio al aprobador": { + "main": [ + [ + { + "node": "Gmail - Pedir aclaración al aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Pedir aclaración al aprobador": { + "main": [ + [ + { + "node": "Fin - Esperando aclaración aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Config canal email": { + "main": [ + [ + { + "node": "Aplicar configuración canal email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Aplicar configuración canal email": { + "main": [ + [ + { + "node": "¿Respuesta de aprobador?", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "settings": { + "executionOrder": "v1", + "binaryMode": "separate" + }, + "staticData": { + "node:Gmail Trigger - WMC Inbox": { + "Gmail Trigger - WMC Inbox": { + "lastTimeChecked": 1788050507, + "possibleDuplicates": [ + "1a0501db03001970", + "1a0501c3d985fa2b" + ] + } + } + }, + "meta": { + "templateCredsSetupCompleted": true + }, + "versionId": "5c4f87b4-f17a-4b66-9600-388931fcd2b9", + "activeVersionId": "5c4f87b4-f17a-4b66-9600-388931fcd2b9", + "versionCounter": 75, + "triggerCount": 1, + "shared": [ + { + "updatedAt": "2026-08-29T23:40:22.961Z", + "createdAt": "2026-08-29T23:40:22.961Z", + "role": "workflow:owner", + "workflowId": "p4rDtVLIWyPuK0LI", + "projectId": "PJpTANzTXIFibWsW", + "project": { + "updatedAt": "2026-04-22T14:25:09.686Z", + "createdAt": "2026-04-22T14:22:54.790Z", + "id": "PJpTANzTXIFibWsW", + "name": "Isaac Aracena ", + "type": "personal", + "icon": null, + "description": null, + "creatorId": "0a88c0b1-928e-4412-896e-c5d1c99b2029" + } + } + ], + "tags": [], + "activeVersion": { + "updatedAt": "2026-08-30T00:40:38.000Z", + "createdAt": "2026-08-30T00:35:48.576Z", + "versionId": "5c4f87b4-f17a-4b66-9600-388931fcd2b9", + "workflowId": "p4rDtVLIWyPuK0LI", + "nodes": [ + { + "parameters": { + "pollTimes": { + "item": [ + { + "mode": "everyMinute" + } + ] + }, + "simple": false, + "filters": { + "q": "from:iaracena@gomezleemarketing.com to:wmc@gomezlee.marketing" + }, + "options": { + "dataPropertyAttachmentsPrefixName": "attachment_", + "downloadAttachments": true + } + }, + "type": "n8n-nodes-base.gmailTrigger", + "typeVersion": 1.3, + "position": [ + -608, + 752 + ], + "id": "ab207f82-b390-4f05-bee8-8275c085aa13", + "name": "Gmail Trigger - WMC Inbox", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "jsCode": "const raw = $json || {};\nconst binary = $binary || {};\nconst hdr = {};\nfor (const h of (raw.payload?.headers || [])) {\n const k = String(h?.name || '').trim().toLowerCase();\n if (k) hdr[k] = String(h?.value || '');\n}\nfunction hv(name, fallback='') {\n const k = String(name).toLowerCase();\n return String(hdr[k] ?? raw[name] ?? raw.headers?.[k] ?? raw.headers?.[name] ?? fallback ?? '');\n}\nfunction decode64url(v) {\n if (!v) return '';\n try {\n let s = String(v).replace(/-/g,'+').replace(/_/g,'/');\n while (s.length % 4) s += '=';\n return Buffer.from(s,'base64').toString('utf8');\n } catch { return ''; }\n}\nfunction collect(part, texts, htmls) {\n if (!part || typeof part !== 'object') return;\n const mime = String(part.mimeType || '').toLowerCase();\n const decoded = decode64url(part.body?.data);\n if (decoded) {\n if (mime === 'text/plain') texts.push(decoded);\n else if (mime === 'text/html') htmls.push(decoded);\n }\n for (const p of (part.parts || [])) collect(p,texts,htmls);\n}\nconst texts=[], htmls=[]; collect(raw.payload || {}, texts, htmls);\nlet bodyText = String(raw.textPlain || raw.text || texts.join('\\n\\n') || raw.snippet || '').trim();\nlet bodyHtml = String(raw.textHtml || htmls.join('\\n\\n') || '').trim();\nif (!bodyText && bodyHtml) bodyText = bodyHtml.replace(//gi,' ').replace(//gi,' ').replace(//gi,'\\n').replace(/<\\/p>/gi,'\\n').replace(/<[^>]+>/g,' ').replace(/ /gi,' ').replace(/&/gi,'&').replace(/\\s+\\n/g,'\\n').replace(/\\n{3,}/g,'\\n\\n').trim();\nconst bodyTextFull = bodyText;\nfunction stripQuotedReply_(value) {\n let s=String(value||'').replace(/\\r\\n/g,'\\n').trim();\n // Gmail suele añadir el mensaje anterior tras “On ... wrote:” o “El ... escribió:”.\n // Cortamos solo esas respuestas citadas; NO eliminamos mensajes reenviados porque\n // pueden ser una solicitud operativa válida que el usuario haya reenviado.\n const replyMarkers=[\n /\\nOn [^\\n]{1,500} wrote:\\s*(?:\\n|$)/i,\n /\\nEl [^\\n]{1,500} escribi[oó]:\\s*(?:\\n|$)/i,\n /\\nLe [^\\n]{1,500} a écrit\\s*:\\s*(?:\\n|$)/i\n ];\n let cut=-1;\n for (const re of replyMarkers) { const m=re.exec(s); if(m && (cut<0 || m.index=0) s=s.slice(0,cut).trim();\n // Si solo quedan líneas quoteadas al final, no las enviamos al clasificador.\n const lines=s.split('\\n');\n const firstQuoted=lines.findIndex((line,i)=>i>0 && /^\\s*>/.test(line));\n if(firstQuoted>0) s=lines.slice(0,firstQuoted).join('\\n').trim();\n return s;\n}\nbodyText = stripQuotedReply_(bodyText) || bodyTextFull;\nfunction parseAddress(v) {\n const s=String(v||'').trim();\n const m=s.match(/<([^<>\\s]+@[^<>\\s]+)>/);\n const email=String(m?.[1] || (s.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}/i)||[])[0] || '').toLowerCase();\n let name=s.replace(/<[^>]+>/g,'').replace(/^\\s*[\"']|[\"']\\s*$/g,'').trim();\n if (!name || name===email) name='';\n return {email,name};\n}\nconst from=parseAddress(hv('From',raw.from));\nconst to=hv('To',raw.to); const cc=hv('Cc',raw.cc); const subject=hv('Subject',raw.Subject || '(Sin asunto)');\nconst gmailMessageId=String(raw.id || raw.messageId || '').trim();\nconst gmailThreadId=String(raw.threadId || '').trim();\nconst approvers=['jgomez@gomezleemarketing.com','wlopez@gomezleemarketing.com'];\nconst testSender='iaracena@gomezleemarketing.com';\nconst senderDomain=(from.email.split('@')[1]||'').toLowerCase();\nconst isApprover=approvers.includes(from.email);\nconst isAllowedRequester=(senderDomain==='walmart.com' || from.email===testSender);\nconst isSelf=(from.email==='wmc@gomezlee.marketing');\nconst attachmentMeta=[];\nfor (const [key,b] of Object.entries(binary)) {\n const fileName=String(b?.fileName || b?.fileName || key);\n const mediaType=String(b?.mimeType || b?.fileType || 'application/octet-stream');\n const size=Number(b?.fileSize || 0) || null;\n attachmentMeta.push({binaryKey:key,filename:fileName,mediaType,size});\n}\nconst textForCountry=(subject+'\\n'+bodyText).toLowerCase();\nconst countries=[['GT','guatemala'],['CR','costa rica'],['SV','el salvador'],['SV','salvador'],['HN','honduras'],['NI','nicaragua']];\nlet countryCode=null; for (const [c,t] of countries) if (textForCountry.includes(t)) {countryCode=c;break;}\nreturn [{json:{\n gmailMessageId,gmailThreadId,senderEmail:from.email,senderName:from.name,subject,to,cc,\n sentAt:hv('Date',new Date().toISOString()),bodyText,bodyTextFull,bodyHtml,attachmentMeta,countryCode,\n isApprover,isAllowedRequester,isSelf,approvers,testSender,\n source:'gmail',receivedAt:new Date().toISOString()\n},binary}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + -368, + 752 + ], + "id": "b3c728b0-d9d4-427d-baa0-10a2a80afa49", + "name": "Normalizar correo entrante" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "aaf3ccba-78a9-454f-9f14-b55bc667172c", + "leftValue": "={{ $json.isApprover === true && /\\[APROBACIÓN WMC\\]/i.test(String($json.subject || '')) }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 480, + 768 + ], + "id": "95c42b09-c38b-4d85-ad06-91025bafbc0c", + "name": "¿Respuesta de aprobador?" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "2599c6eb-9d4f-4442-a05a-baf138f2c35b", + "leftValue": "={{ $json.isAllowedRequester && !$json.isSelf }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 800, + 1376 + ], + "id": "e739c023-0e45-42f2-9ca4-3459b5722e63", + "name": "¿Remitente permitido?" + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 1040, + 1616 + ], + "id": "3fb50aa6-8dea-428f-8b12-b3b3ed54c22f", + "name": "Fin - Remitente ignorado" + }, + { + "parameters": { + "jsCode": "const bin=$binary||{}; const names=[];\nfor(const [k,b] of Object.entries(bin)){ const m=String(b?.mimeType||'').toLowerCase(), f=String(b?.fileName||''); if(m.startsWith('image/')||/\\.(png|jpe?g|webp|gif|bmp|heic|heif)$/i.test(f)) names.push(k); }\nreturn [{json:{...$json,hasImages:names.length>0,imageBinaryNames:names.join(',')},binary:bin}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1040, + 1376 + ], + "id": "e7808d43-d28b-4864-ada3-0a70d096a9c8", + "name": "Preparar imágenes email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "e5e507fd-a65e-4f07-ba4f-47ce85f79973", + "leftValue": "={{ $json.hasImages }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 1280, + 1376 + ], + "id": "fda52bfd-ce24-4c74-aff0-2b72d57690d7", + "name": "¿Tiene imágenes email?" + }, + { + "parameters": { + "resource": "image", + "operation": "analyze", + "modelId": { + "__rl": true, + "mode": "list", + "value": "models/gemini-2.5-pro" + }, + "text": "Analiza fielmente las imágenes adjuntas para una solicitud de cotización Walmart Connect. Extrae solo información visible o escrita relevante: marcas, producto, país, formato/tienda, cantidades, personal, uniformes, mobiliario, medidas, logística y observaciones. No inventes precios ni datos.", + "inputType": "binary", + "binaryPropertyName": "={{ $node[\"Preparar imágenes email\"].json.imageBinaryNames }}", + "options": { + "maxOutputTokens": 2200 + } + }, + "type": "@n8n/n8n-nodes-langchain.googleGemini", + "typeVersion": 1.1, + "position": [ + 1520, + 1216 + ], + "id": "a5566162-bb0b-4827-b9cc-f6c1ced415bf", + "name": "Gemini - Analizar imágenes email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googlePalmApi": { + "id": "jvsXYwL6IOoY2DBU", + "name": "Isaac - Gemini Api Pago" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "function txt(r){ if(!r||typeof r!=='object') return ''; for(const k of ['text','output','response','result','mergedResponse']) if(typeof r[k]==='string'&&r[k].trim()) return r[k].trim(); const p=r.content?.parts||r.candidates?.[0]?.content?.parts; if(Array.isArray(p)) return p.map(x=>x?.text||'').join('\\n').trim(); return ''; }\nconst base=$node[\"Preparar imágenes email\"].json; const t=txt($json); let trg={}; try{trg=$items(\"Gmail Trigger - WMC Inbox\")[0]||{};}catch{}\nreturn [{json:{...base,imageAnalysis:t||null,imageAnalysisError:base.hasImages&&!t},binary:trg.binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1760, + 1216 + ], + "id": "d700f366-212a-4637-8d45-aee19bb3e1bb", + "name": "Integrar análisis imágenes" + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,imageAnalysis:null,imageAnalysisError:false},binary:$binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1520, + 1536 + ], + "id": "3df9c929-8766-4cb8-919e-2f79e76e500c", + "name": "Sin imágenes email" + }, + { + "parameters": { + "jsCode": "const bin=$binary||{}; const names=[];\nfor(const [k,b] of Object.entries(bin)){ const m=String(b?.mimeType||'').toLowerCase(), f=String(b?.fileName||''); if(m==='application/pdf'||/\\.pdf$/i.test(f)) names.push(k); }\nreturn [{json:{...$json,hasPdfs:names.length>0,pdfBinaryNames:names.join(',')},binary:bin}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2000, + 1376 + ], + "id": "1af5b2f6-2f46-4c76-8206-b9066966e8dd", + "name": "Preparar PDFs email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "692b7118-2bee-4b0e-961b-e783688e914e", + "leftValue": "={{ $json.hasPdfs }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 2240, + 1376 + ], + "id": "648a0d41-45df-4e8a-9dec-01ca563b3cfb", + "name": "¿Tiene PDFs email?" + }, + { + "parameters": { + "resource": "document", + "modelId": { + "__rl": true, + "mode": "list", + "value": "models/gemini-2.5-pro" + }, + "text": "Analiza fielmente los PDF adjuntos para el Cotizador Walmart Connect. Extrae únicamente datos explícitos relevantes: país, anunciante, proyecto, fechas, formatos, tiendas, ubicación/cobertura, personal, cantidades, días, mobiliario, insumos, logística, medidas, condiciones y observaciones. No inventes información ni precios.", + "inputType": "binary", + "binaryPropertyName": "={{ $node[\"Preparar PDFs email\"].json.pdfBinaryNames }}", + "options": { + "maxOutputTokens": 2600 + } + }, + "type": "@n8n/n8n-nodes-langchain.googleGemini", + "typeVersion": 1.1, + "position": [ + 2480, + 1216 + ], + "id": "bd831472-87a5-4836-9e70-dba6c73d78f4", + "name": "Gemini - Analizar PDFs email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googlePalmApi": { + "id": "jvsXYwL6IOoY2DBU", + "name": "Isaac - Gemini Api Pago" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "function txt(r){ if(!r||typeof r!=='object') return ''; for(const k of ['text','output','response','result','mergedResponse']) if(typeof r[k]==='string'&&r[k].trim()) return r[k].trim(); const p=r.content?.parts||r.candidates?.[0]?.content?.parts; if(Array.isArray(p)) return p.map(x=>x?.text||'').join('\\n').trim(); return ''; }\nconst base=$node[\"Preparar PDFs email\"].json; const t=txt($json); let trg={}; try{trg=$items(\"Gmail Trigger - WMC Inbox\")[0]||{};}catch{}\nreturn [{json:{...base,documentAnalysis:t||null,documentAnalysisError:base.hasPdfs&&!t},binary:trg.binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2720, + 1216 + ], + "id": "bf272474-9aae-43fc-b879-0d94a65c31ef", + "name": "Integrar análisis PDFs" + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,documentAnalysis:null,documentAnalysisError:false},binary:$binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2480, + 1536 + ], + "id": "92a5a7dd-7cc2-4548-bf3b-ec0d91306277", + "name": "Sin PDFs email" + }, + { + "parameters": { + "jsCode": "const bin=$binary||{}; const names=[];\nfor(const [k,b] of Object.entries(bin)){ const m=String(b?.mimeType||'').toLowerCase(), f=String(b?.fileName||''); if(m.startsWith('audio/')||/\\.(webm|mp3|wav|m4a|ogg|oga|aac|flac|mpeg|mpga)$/i.test(f)) names.push(k); }\nreturn [{json:{...$json,hasAudio:names.length>0,audioBinaryNames:names.join(',')},binary:bin}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2960, + 1376 + ], + "id": "a1dd4f45-724b-4846-84a7-5427087de6cd", + "name": "Preparar audio email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "f0e66802-b149-4681-8953-4deaf95f1a07", + "leftValue": "={{ $json.hasAudio }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 3200, + 1216 + ], + "id": "7e36fa54-ba65-4439-bd2a-6a4b5fa36a80", + "name": "¿Tiene audio email?" + }, + { + "parameters": { + "resource": "audio", + "modelId": { + "__rl": true, + "value": "models/gemini-2.5-pro", + "mode": "list", + "cachedResultName": "models/gemini-2.5-pro" + }, + "inputType": "binary", + "binaryPropertyName": "={{ $node[\"Preparar audio email\"].json.audioBinaryNames }}", + "options": {} + }, + "type": "@n8n/n8n-nodes-langchain.googleGemini", + "typeVersion": 1.1, + "position": [ + 3440, + 1056 + ], + "id": "1eb02117-3fa7-4a60-81fe-4d2e7b13d296", + "name": "Gemini - Transcribir audio email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googlePalmApi": { + "id": "jvsXYwL6IOoY2DBU", + "name": "Isaac - Gemini Api Pago" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "function txt(r){ if(!r||typeof r!=='object') return ''; for(const k of ['text','output','response','result','mergedResponse']) if(typeof r[k]==='string'&&r[k].trim()) return r[k].trim(); const p=r.content?.parts||r.candidates?.[0]?.content?.parts; if(Array.isArray(p)) return p.map(x=>x?.text||'').join('\\n').trim(); return ''; }\nconst base=$node[\"Preparar audio email\"].json; const t=txt($json); let trg={}; try{trg=$items(\"Gmail Trigger - WMC Inbox\")[0]||{};}catch{}\nreturn [{json:{...base,audioTranscription:t||null,audioTranscriptionError:base.hasAudio&&!t},binary:trg.binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3680, + 1056 + ], + "id": "187cb874-b625-4376-8ec1-323d7fd676ca", + "name": "Integrar transcripción audio" + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,audioTranscription:null,audioTranscriptionError:false},binary:$binary||{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3440, + 1376 + ], + "id": "07bf21a9-1f3b-4e4f-8777-080b1f43533b", + "name": "Sin audio email" + }, + { + "parameters": { + "jsCode": "const bin=$binary||{}; const keys=[];\nfor(const [k,b] of Object.entries(bin)){ const m=String(b?.mimeType||'').toLowerCase(), f=String(b?.fileName||''); if(m==='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'||/\\.xlsx$/i.test(f)) keys.push(k); }\nconst supported=new Set(keys); const unsupported=($json.attachmentMeta||[]).filter(a=>{const m=String(a.mediaType||'').toLowerCase(),f=String(a.filename||''); return !(m.startsWith('image/')||m.startsWith('audio/')||m==='application/pdf'||/\\.(png|jpe?g|webp|gif|bmp|heic|heif|webm|mp3|wav|m4a|ogg|oga|aac|flac|mpeg|mpga|pdf|xlsx)$/i.test(f));});\nreturn [{json:{...$json,hasXlsx:keys.length>0,xlsxBinaryKeys:keys,unsupportedAttachments:unsupported},binary:bin}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3920, + 1216 + ], + "id": "26a4ac9d-2a64-4b24-a2af-2e4caab7c197", + "name": "Preparar XLSX email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "eaadc66d-c3f5-417d-b945-5397809d08b9", + "leftValue": "={{ $json.hasXlsx }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 4848, + 1088 + ], + "id": "6c433395-f347-45a6-bd7e-5d0c37b4bd9f", + "name": "¿Tiene XLSX email?" + }, + { + "parameters": { + "jsCode": "const base=$json, bin=$binary||{}, keys=Array.isArray(base.xlsxBinaryKeys)?base.xlsxBinaryKeys:[]; const out=[]; let i=0;\nfor(const k of keys){const b=bin[k]; if(!b) continue; i++; const fn=String(b.fileName||`archivo-${i}.xlsx`); out.push({json:{...base,xlsxIndex:i-1,xlsxFilename:fn,tempUploadName:`_TEMP_WMC_EMAIL_XLSX_${Date.now()}_${i}_${fn.replace(/[^a-zA-Z0-9._-]+/g,'_').slice(0,90)}`},binary:{data:b}})}\nreturn out.length?out:[{json:{...base,hasXlsx:false}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 5088, + 928 + ], + "id": "76c6166e-02e0-4119-89c6-babb7682c06a", + "name": "Expandir XLSX email" + }, + { + "parameters": { + "name": "={{ $json.tempUploadName }}", + "driveId": { + "__rl": true, + "value": "My Drive", + "mode": "list" + }, + "folderId": { + "__rl": true, + "value": "root", + "mode": "list", + "cachedResultName": "/ (Root folder)" + }, + "options": { + "simplifyOutput": true + } + }, + "type": "n8n-nodes-base.googleDrive", + "typeVersion": 3, + "position": [ + 5328, + 928 + ], + "id": "262b6267-8259-407d-a105-831750270537", + "name": "Subir XLSX email temporal a Drive", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const ups=$input.all(); let src=[]; try{src=$items(\"Expandir XLSX email\");}catch{} return ups.map((it,i)=>({json:{...(src[i]?.json||{}),tempXlsxDriveId:String(it.json?.id||'')||null,tempXlsxUploadError:it.json?.error||null},pairedItem:{item:i}}));" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 5568, + 928 + ], + "id": "53d5ef62-ba53-4a13-abf0-02223658ac6d", + "name": "Mapear XLSX email temporal" + }, + { + "parameters": { + "method": "POST", + "url": "={{ 'https://www.googleapis.com/drive/v2/files/' + encodeURIComponent($json.tempXlsxDriveId || 'invalid') + '/copy?convert=true' }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "options": { + "timeout": 60000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 5808, + 928 + ], + "id": "212fa06d-0a76-4e04-a540-7a101a26d283", + "name": "Convertir XLSX email a Google Sheets", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const xs=$input.all(); let src=[]; try{src=$items(\"Mapear XLSX email temporal\");}catch{} return xs.map((it,i)=>({json:{...(src[i]?.json||{}),tempGoogleSheetId:String(it.json?.id||'')||null,tempGoogleSheetMimeType:String(it.json?.mimeType||''),tempConversionError:it.json?.error||null},pairedItem:{item:i}}));" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 6048, + 928 + ], + "id": "c30d3b4a-58f2-45fd-ad7e-b9f3773c930f", + "name": "Mapear XLSX convertido email" + }, + { + "parameters": { + "url": "={{ 'https://sheets.googleapis.com/v4/spreadsheets/' + encodeURIComponent($json.tempGoogleSheetId || 'invalid') }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "sendQuery": true, + "queryParameters": { + "parameters": [ + { + "name": "includeGridData", + "value": "true" + }, + { + "name": "fields", + "value": "spreadsheetId,properties(title),sheets(properties(sheetId,title,index,hidden,gridProperties(rowCount,columnCount)),data(startRow,startColumn,rowData(values(formattedValue,effectiveValue))))" + } + ] + }, + "options": { + "timeout": 90000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 6288, + 928 + ], + "id": "555ba82c-e8ca-488a-b817-db114a0b9954", + "name": "Leer todas las hojas XLSX email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Preparar XLSX email\"].json; const incoming=$input.all(); let metas=[]; try{metas=$items(\"Mapear XLSX convertido email\");}catch{}\nconst MAX=70000, ROWS=1500, COLS=100, SHEETS=40; let chars=0,trunc=false; const blocks=[],inventory=[],warn=[];\nconst clean=v=>String(v??'').replace(/[\\u0000-\\u001F]+/g,' ').replace(/\\s+/g,' ').trim();\nfunction col(i){let n=i+1,s='';while(n){const r=(n-1)%26;s=String.fromCharCode(65+r)+s;n=Math.floor((n-1)/26);}return s;}\nfunction val(c){if(!c||typeof c!=='object')return'';if(c.formattedValue!=null)return clean(c.formattedValue);const e=c.effectiveValue||{};for(const k of ['stringValue','numberValue','boolValue','formulaValue'])if(e[k]!=null)return clean(e[k]);return'';}\nfor(let fi=0;fi=MAX){trunc=true;break;}const p=sh?.properties||{}, sn=clean(p.title||`Hoja ${names.length+1}`);names.push(sn);const rm=new Map();for(const g of (sh.data||[])){const sr=Number(g?.startRow||0),sc=Number(g?.startColumn||0);for(let r=0;r<(g.rowData||[]).length;r++){const ar=sr+r;if(ar>=ROWS){trunc=true;break;}for(let c=0;c<(g.rowData[r]?.values||[]).length;c++){const ac=sc+c;if(ac>=COLS){trunc=true;break;}const v=val(g.rowData[r].values[c]);if(v){if(!rm.has(ar))rm.set(ar,new Map());rm.get(ar).set(ac,v);}}}}const lines=[];for(const r of [...rm.keys()].sort((a,b)=>a-b)){const cells=[...rm.get(r).entries()].sort((a,b)=>a[0]-b[0]);const line=`Fila ${r+1}: `+cells.map(([c,v])=>`[${col(c)}] ${v}`).join(' | ');if(chars+line.length>MAX){trunc=true;break;}lines.push(line);chars+=line.length+1;}blocks.push(`Archivo: ${fn}\\nHoja analizada: ${sn}${p.hidden?' (oculta)':''}\\n${lines.length?lines.join('\\n'):'(Sin contenido legible)'}`);}inventory.push({file:fn,sheets:names});}\nif(trunc)warn.push('Extracción XLSX truncada por límite de seguridad.');\nreturn [{json:{...base,spreadsheetAnalysis:blocks.join('\\n\\n').trim()||null,spreadsheetAnalysisError:blocks.length===0,spreadsheetSheetNames:inventory,spreadsheetExtractionWarnings:warn}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 6528, + 928 + ], + "id": "e25959cf-4a9d-440d-89e6-e77732472f69", + "name": "Agregar análisis XLSX email" + }, + { + "parameters": { + "jsCode": "let metas=[];try{metas=$items(\"Mapear XLSX convertido email\");}catch{}const out=[],seen=new Set();for(const m0 of metas){const m=m0.json||{};for(const id0 of [m.tempGoogleSheetId,m.tempXlsxDriveId]){const id=String(id0||'').trim();if(id&&!seen.has(id)){seen.add(id);out.push({json:{deleteFileId:id}});}}}return out.length?out:[{json:{deleteFileId:null}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 6768, + 928 + ], + "id": "959e39a9-fd46-4ae5-b9f5-2ee81f418988", + "name": "Preparar limpieza XLSX email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "873da85e-f479-4fe3-85b3-95c6f9c105e8", + "leftValue": "={{ !!$json.deleteFileId }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 7008, + 928 + ], + "id": "c992c380-1830-4340-9adf-a54fc401df24", + "name": "¿Hay temporal XLSX?" + }, + { + "parameters": { + "operation": "deleteFile", + "fileId": { + "__rl": true, + "value": "={{ $json.deleteFileId }}", + "mode": "id" + }, + "options": { + "deletePermanently": true + } + }, + "type": "n8n-nodes-base.googleDrive", + "typeVersion": 3, + "position": [ + 7248, + 800 + ], + "id": "d924d82b-5ff6-4ab6-b84c-369cce1a95eb", + "name": "Eliminar temporal XLSX email", + "retryOnFail": true, + "maxTries": 2, + "waitBetweenTries": 1500, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Agregar análisis XLSX email\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 7488, + 800 + ], + "id": "0d5af946-c85f-47f4-a11f-a947696196af", + "name": "Restaurar base tras limpieza XLSX" + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Agregar análisis XLSX email\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 7248, + 1040 + ], + "id": "8d0f1365-ea58-4f3f-9fcd-edcc09773181", + "name": "Restaurar base sin limpieza XLSX" + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,spreadsheetAnalysis:null,spreadsheetAnalysisError:false,spreadsheetSheetNames:[],spreadsheetExtractionWarnings:[]}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 5088, + 1248 + ], + "id": "3dfe6356-38d4-4be1-b08a-18ff31309002", + "name": "Sin XLSX email" + }, + { + "parameters": { + "jsCode": "return [{json:$json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 7728, + 1088 + ], + "id": "b447a80b-ee83-4c9d-850e-a2dfe62f1a9a", + "name": "Base email lista para agente" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_ingest", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.gmailThreadId,p_gmail_message_id:$json.gmailMessageId,p_sender_email:$json.senderEmail,p_sender_name:$json.senderName,p_subject:$json.subject,p_body_text:$json.bodyText,p_body_html:$json.bodyHtml||null,p_attachments:$json.attachmentMeta||[],p_country_code:$json.countryCode||null}) }", + "options": { + "timeout": 40000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 7968, + 1088 + ], + "id": "26cb64c2-0b25-4d30-b054-d2a991ba468f", + "name": "Supabase - Ingestar email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500 + }, + { + "parameters": { + "jsCode": "const base=$node[\"Base email lista para agente\"].json; const raw=$json||{}; const ing=raw.body&&typeof raw.body==='object'?raw.body:(raw.data&&typeof raw.data==='object'?raw.data:raw);\nconst parts=[String(base.bodyText||'').trim()];\nif(base.imageAnalysis)parts.push('[ANÁLISIS REAL DE IMÁGENES ADJUNTAS]\\n'+base.imageAnalysis);\nif(base.documentAnalysis)parts.push('[ANÁLISIS REAL DE PDF ADJUNTOS]\\n'+base.documentAnalysis);\nif(base.audioTranscription)parts.push('[TRANSCRIPCIÓN REAL DE AUDIO ADJUNTO]\\n'+base.audioTranscription);\nif(base.spreadsheetAnalysis)parts.push('[CONTENIDO REAL EXTRAÍDO DE XLSX ADJUNTO]\\n'+base.spreadsheetAnalysis);\nif((base.unsupportedAttachments||[]).length)parts.push('[ADJUNTOS NO ANALIZADOS AUTOMÁTICAMENTE]\\n'+base.unsupportedAttachments.map(a=>`${a.filename} (${a.mediaType})`).join('\\n'));\nreturn [{json:{...base,ingest:ing,agentRequest:{gmailThreadId:base.gmailThreadId,gmailMessageId:base.gmailMessageId,senderEmail:base.senderEmail,senderName:base.senderName,text:parts.filter(Boolean).join('\\n\\n'),attachments:[],countryCode:base.countryCode,history:Array.isArray(ing.history)?ing.history:[],context:ing.context&&typeof ing.context==='object'?ing.context:{},emailMeta:{subject:base.subject,to:base.to,cc:base.cc,sentAt:base.sentAt,attachmentMeta:base.attachmentMeta||[],spreadsheetSheetNames:base.spreadsheetSheetNames||[]}}}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 8208, + 1088 + ], + "id": "02146f13-9a85-4727-8d27-a81a1c3d07fa", + "name": "Construir solicitud agente email" + }, + { + "parameters": { + "method": "POST", + "url": "https://agenteit.digitalcompass.agency/webhook/cotizador-wmc-email-agent", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "Content-Type", + "value": "application/json" + }, + { + "name": "X-WMC-Internal-Secret", + "value": "fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={{ JSON.stringify($json.agentRequest) }}", + "options": { + "timeout": 240000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 8448, + 1088 + ], + "id": "d13eba8c-3cc5-4c21-a8f8-a60b048d15ee", + "name": "Agente WMC - Procesar email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 4000, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Construir solicitud agente email\"].json; const raw=$json||{}; const a=(raw.body&&typeof raw.body==='object')?raw.body:raw; const cfg=base.ingest?.config||{};\nconst disposition=String(a.emailDisposition||'process').toLowerCase(); const action=String(a.action||'chat'); const quote=a.quote&&typeof a.quote==='object'?a.quote:null; const total=Number(quote?.totalUsd||0)||0; const threshold=Number(cfg.approval_threshold_usd??cfg.approvalThresholdUsd??10000)||10000;\nconst nonTariff=[]; if(quote&&Array.isArray(quote.items)){for(const it of quote.items){const amount=Math.abs(Number(it?.totalUsd||0));if(!(amount>0))continue;const code=String(it?.metadata?.priceSourceCode||it?.priceSourceCode||'').toUpperCase();if(code!=='T')nonTariff.push({description:String(it?.description||''),code:code||'E',amount});}}\nconst reasons=[];if(total>threshold)reasons.push({code:'OVER_10000',text:`Total USD ${total.toFixed(2)} supera el umbral de USD ${threshold.toFixed(2)}.`});if(nonTariff.length)reasons.push({code:'NON_TARIFF',text:`${nonTariff.length} partida(s) usan referencia fuera del tarifario oficial.`,items:nonTariff});\nconst approvalRequired=!!quote && ['generate_quote','generate_proposal','generate_monthly_glm'].includes(action) && reasons.length>0;\nconst generatedActions=['generate_quote','generate_proposal','generate_monthly_glm','generate_image'];\nconst artifactFailure=generatedActions.includes(action) && !a.artifactUrl;\nif(artifactFailure){\n a.reply='No pude generar el archivo solicitado en este momento. Por favor responde a este mismo correo para reintentarlo.';\n a.warnings=[...(Array.isArray(a.warnings)?a.warnings:[]),'El artefacto no fue generado; no se envió ningún archivo.'];\n}\nlet customerMode='final'; if(disposition==='ignore')customerMode='ignore'; else if(action==='chat'||artifactFailure)customerMode='clarification'; else if(approvalRequired)customerMode='approval';\nconst artifactType=String(a.artifactType||''); const artifactId=String(a.artifactId||''); const shouldExport=!!artifactId&&['quote','proposal','monthly_glm'].includes(artifactType);\nreturn [{json:{...base,agent:a,config:cfg,customerMode,approvalRequired,approvalReasons:reasons,nonTariffItems:nonTariff,totalUsd:total,thresholdUsd:threshold,artifactType,artifactId,artifactUrl:a.artifactUrl||null,artifactTitle:a.title||quote?.project||'WMC',quote,shouldExport,artifactFailure}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 8688, + 1088 + ], + "id": "339b335b-e1ad-4696-92a3-43c4bcb7d437", + "name": "Evaluar respuesta agente email" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "93182a6b-e065-4c35-93a8-e5c81bcddd2b", + "leftValue": "={{ $json.customerMode }}", + "rightValue": "ignore", + "operator": { + "type": "string", + "operation": "equals", + "name": "filter.operator.equals" + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 8928, + 1088 + ], + "id": "81685b4e-e097-456a-8a99-511234820fc6", + "name": "¿Ignorar correo?" + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 9168, + 928 + ], + "id": "f80493b2-681c-491c-a844-605f26421534", + "name": "Fin - Correo fuera de alcance" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "257b6ccb-e648-4422-bd6d-025089fed298", + "leftValue": "={{ $json.approvalRequired }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 9168, + 1248 + ], + "id": "e8fc2f77-6ee2-4c75-916c-975c282e8fde", + "name": "¿Requiere aprobación interna?" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_create_approval", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.gmailThreadId,p_quote:$json.quote,p_document_url:$json.artifactUrl,p_artifact_id:$json.artifactId,p_artifact_type:$json.artifactType,p_artifact_title:$json.artifactTitle,p_customer_gmail_message_id:$json.gmailMessageId,p_reason:$json.approvalReasons}) }", + "options": { + "timeout": 40000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 9408, + 1488 + ], + "id": "d14f3a22-591f-495a-9f49-63f218e8dbe0", + "name": "Supabase - Crear aprobación email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500 + }, + { + "parameters": { + "jsCode": "const base=$node[\"Evaluar respuesta agente email\"].json;const raw=$json||{};const r=raw.body&&typeof raw.body==='object'?raw.body:raw;const approvalId=String(r.approvalId||'');\nconst esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nconst q=base.quote||{};const items=(base.nonTariffItems||[]).map(x=>`
  • ${esc(x.code)} · ${esc(x.description)} · USD ${Number(x.amount||0).toFixed(2)}
  • `).join('');\nconst reasons=(base.approvalReasons||[]).map(x=>`
    ${esc(x.text)}
    `).join('');\nconst html=`
    \"GomezLee
    COTIZADOR WALMART CONNECT · APROBACIÓN INTERNA

    Cotización pendiente de aprobación

    El agente preparó una cotización recibida por correo que no puede enviarse automáticamente.

    ${reasons}
    Proyecto${esc(q.project||'—')}
    Anunciante${esc(q.advertiser||'—')}
    País${esc(q.country||q.countryCode||'—')}
    Solicitante${esc(base.senderEmail)}
    TotalUSD ${Number(base.totalUsd||0).toFixed(2)}
    ${items?`
    Partidas fuera de tarifario
      ${items}
    `:''}
    Para decidir, responde a este mismo correo:
    APROBAR · envía la cotización al cliente.
    RECHAZAR · no la envía.
    CAMBIAR: seguido de la modificación solicitada · el agente regenera el borrador y vuelve a pedir aprobación.
    ${base.artifactUrl?`

    Abrir borrador en Google Workspace

    `:''}
    Referencia interna: ${esc(approvalId)}
    `;\nconst approverEmails=(Array.isArray(base.config?.approver_emails)?base.config.approver_emails:(Array.isArray(base.emailConfig?.approver_emails)?base.emailConfig.approver_emails:['jgomez@gomezleemarketing.com','wlopez@gomezleemarketing.com'])).map(x=>String(x||'').trim()).filter(Boolean);return [{json:{...base,approvalId,requiredApprovals:Number(r.requiredApprovals||1),approvalSubject:`[APROBACIÓN WMC] ${q.project||q.advertiser||'Cotización'} · USD ${Number(base.totalUsd||0).toFixed(2)}`,approvalHtml:html,approverList:approverEmails.join(', '),approverEmails}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 9648, + 1488 + ], + "id": "f15c6913-b9ee-47f9-9eb8-03529ff1b481", + "name": "Preparar correo aprobación GLM" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "dccfd9d3-857b-4b82-a269-6eef3029549d", + "leftValue": "={{ $json.shouldExport }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 9888, + 1488 + ], + "id": "5a76b54f-0585-438c-ad80-be0c812e27ad", + "name": "¿Adjuntar borrador a aprobación?" + }, + { + "parameters": { + "url": "={{ 'https://www.googleapis.com/drive/v3/files/' + encodeURIComponent($json.artifactId) + '/export?mimeType=' + encodeURIComponent($json.artifactType === 'proposal' ? 'application/pdf' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "options": { + "response": { + "response": { + "responseFormat": "file" + } + }, + "timeout": 90000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 10320, + 1408 + ], + "id": "975d8649-99b7-41d0-993a-ce032b6fd94a", + "name": "Descargar borrador para aprobación", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Preparar correo aprobación GLM\"].json;const b=$binary?.data||null;if(b){b.fileName=(String(base.artifactTitle||'Cotizacion_WMC').replace(/[^a-zA-Z0-9._-]+/g,'_').slice(0,100))+(base.artifactType==='proposal'?'.pdf':'.xlsx');b.mimeType=base.artifactType==='proposal'?'application/pdf':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';}\nreturn [{json:{...base,exportOk:!!b},binary:b?{data:b}:{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 10560, + 1408 + ], + "id": "79448614-99a4-4125-a885-baf0f2da5d9f", + "name": "Preparar adjunto aprobación" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "7eb6cac5-d384-4161-9ac3-7b4ade92b248", + "leftValue": "={{ $json.exportOk }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 11008, + 1376 + ], + "id": "24d47913-b611-4203-ae4b-04be6e8311b9", + "name": "¿Borrador descargado?" + }, + { + "parameters": { + "sendTo": "=iaracena@gomezleemarketing.com", + "subject": "={{ $json.approvalSubject }}", + "message": "={{ $json.approvalHtml }}", + "options": { + "appendAttribution": false, + "attachmentsUi": { + "attachmentsBinary": [ + {} + ] + }, + "senderName": "Walmart Connect | GomezLee Marketing" + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11552, + 1264 + ], + "id": "bf6b11ec-3341-42ad-b433-316684ad660c", + "name": "Gmail - Enviar aprobación con adjunto", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "64450f47-d0b4-424f-a091-341c4a34c2cd", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "sendTo": "=iaracena@gomezleemarketing.com", + "subject": "={{ $json.approvalSubject }}", + "message": "={{ $json.approvalHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect | GomezLee Marketing" + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11776, + 1472 + ], + "id": "cc24abfe-a768-4cb8-a227-575a8695bcd6", + "name": "Gmail - Enviar aprobación sin adjunto", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "b538ae39-7ec0-496a-a263-ce5263a9499f", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "jsCode": "return [{json:{...$json,exportOk:false}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 10992, + 1856 + ], + "id": "5c3cec29-debb-4d98-8a51-6fcba1561663", + "name": "Preparar aprobación sin exportar" + }, + { + "parameters": { + "sendTo": "=iaracena@gomezleemarketing.com", + "subject": "={{ $json.approvalSubject }}", + "message": "={{ $json.approvalHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect | GomezLee Marketing" + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11232, + 1856 + ], + "id": "78b06108-0570-4e13-939b-0c722ff2fdcb", + "name": "Gmail - Enviar aprobación solo enlace", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "f13b8337-eee5-4a66-846d-908c2ea31ad9", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_set_approval_gmail_thread", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_id:$node['Preparar correo aprobación GLM'].json.approvalId,p_approval_gmail_thread_id:$json.threadId,p_approval_gmail_message_id:$json.id}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 13376, + 1680 + ], + "id": "5a9dafcd-c828-433b-aa0b-1d7d56fc5316", + "name": "Supabase - Vincular hilo de aprobación", + "continueOnFail": true + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_record_message", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$node['Evaluar respuesta agente email'].json.gmailThreadId,p_gmail_message_id:'approval-out-'+$node['Preparar correo aprobación GLM'].json.approvalId,p_direction:'internal_out',p_from_email:'wmc@gomezlee.marketing',p_to_emails:$node['Preparar correo aprobación GLM'].json.approverEmails,p_subject:$node['Preparar correo aprobación GLM'].json.approvalSubject,p_body_text:'Solicitud de aprobación interna de cotización WMC.',p_body_html:$node['Preparar correo aprobación GLM'].json.approvalHtml,p_attachments:[],p_metadata:{approvalId:$node['Preparar correo aprobación GLM'].json.approvalId},p_status:'pending_approval'}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 13616, + 1680 + ], + "id": "e7d604e0-1355-4350-8869-3c363498d708", + "name": "Supabase - Registrar solicitud aprobación", + "continueOnFail": true + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 13856, + 1680 + ], + "id": "c599c6f8-093e-459e-8390-b14279ccebe8", + "name": "Fin - Esperando aprobación" + }, + { + "parameters": { + "jsCode": "const b=$json;const a=b.agent||{};const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const name=String(b.senderName||'').trim();const greeting=name?`Hola ${esc(name.split(/\\s+/)[0])},`:'Hola,';const reply=esc(a.reply||'').replace(/\\n/g,'
    ');const isClar=b.customerMode==='clarification';const title=isClar?'Necesitamos una confirmación para continuar':'Cotización Walmart Connect';const intro=isClar?'Gracias por tu solicitud. Para continuar correctamente necesitamos confirmar lo siguiente:':'La solicitud fue procesada. Encontrarás el archivo correspondiente adjunto o disponible en el enlace incluido.';\nconst html=`
    \"Walmart

    ${esc(title)}

    ${greeting}

    ${esc(intro)}

    ${reply||'Listo.'}
    ${!isClar&&b.artifactUrl?`

    Abrir archivo en Google Workspace

    `:''}${isClar?'

    Por favor responde a este mismo correo con la información solicitada y continuaremos desde aquí.

    ':'

    Quedamos atentos a cualquier comentario o ajuste.

    '}
    Walmart Connect · Gestión automatizada de cotizaciones
    `;return [{json:{...b,customerHtml:html,customerSubject:b.subject}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 9408, + 1168 + ], + "id": "ee0eab64-c0ec-4e4b-800b-e1942931944c", + "name": "Construir HTML cliente Walmart" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "e94406c9-0285-4541-ab19-a06c44a85b99", + "leftValue": "={{ $json.customerMode }}", + "rightValue": "clarification", + "operator": { + "type": "string", + "operation": "equals", + "name": "filter.operator.equals" + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 9648, + 1168 + ], + "id": "b5f91adb-ca7d-4f7c-8680-a6697855b7d1", + "name": "¿Es aclaración?" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 10192, + 752 + ], + "id": "92fd8304-6172-4aa1-8067-cf2edc56905f", + "name": "Gmail - Responder aclaración cliente", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "160a5c37-d2e5-4ae9-8c18-327091bf22e5", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "1aebba2a-7e1b-47b2-b464-7835a163efe1", + "leftValue": "={{ $json.shouldExport }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 9888, + 1280 + ], + "id": "f58741f6-91f1-4843-b35c-619046a2839e", + "name": "¿Adjuntar archivo al cliente?" + }, + { + "parameters": { + "url": "={{ 'https://www.googleapis.com/drive/v3/files/' + encodeURIComponent($json.artifactId) + '/export?mimeType=' + encodeURIComponent($json.artifactType === 'proposal' ? 'application/pdf' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "options": { + "response": { + "response": { + "responseFormat": "file" + } + }, + "timeout": 90000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 10208, + 1008 + ], + "id": "f43c7d77-f75f-4e9c-b067-92d62b151074", + "name": "Descargar artefacto para cliente", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Construir HTML cliente Walmart\"].json;const b=$binary?.data||null;if(b){b.fileName=(String(base.artifactTitle||'Cotizacion_WMC').replace(/[^a-zA-Z0-9._-]+/g,'_').slice(0,100))+(base.artifactType==='proposal'?'.pdf':'.xlsx');b.mimeType=base.artifactType==='proposal'?'application/pdf':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';}return [{json:{...base,exportOk:!!b},binary:b?{data:b}:{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 10448, + 1008 + ], + "id": "3d6acf36-9b2a-46b2-8253-3bba8b2e09bc", + "name": "Preparar adjunto cliente" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "f45ceb76-0896-4be4-bd24-03175f38373c", + "leftValue": "={{ $json.exportOk }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 10736, + 976 + ], + "id": "f9f98ee7-51c2-4c8d-948d-bfc26f480705", + "name": "¿Archivo cliente descargado?" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "attachmentsUi": { + "attachmentsBinary": [ + {} + ] + }, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11248, + 656 + ], + "id": "c7b347ba-e3a0-47b7-87ec-5f60858a0162", + "name": "Gmail - Responder cliente con archivo", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "ced5a909-e80a-4a90-8da6-cdd9b9f2d13d", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 11088, + 1088 + ], + "id": "d1706a6c-4fb8-46c7-aba1-2e0b63ccc99a", + "name": "Gmail - Responder cliente sin archivo", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "541a4fe0-64c3-4eb0-acbe-65f3082d2845", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 10320, + 1184 + ], + "id": "01ba8fb0-98c7-4f97-a5d6-1b0d754ddee8", + "name": "Gmail - Responder cliente solo enlace", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "7520e58c-aa85-4301-be4d-b74d633610b4", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "jsCode": "const base=$node[\"Construir HTML cliente Walmart\"].json;const g=$json||{};return [{json:{...base,sentGmailMessageId:String(g.id||''),sentGmailThreadId:String(g.threadId||base.gmailThreadId),sentOk:!!g.id}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 11632, + 928 + ], + "id": "7ba23678-b7c4-4681-b8c5-75eadefb8977", + "name": "Postprocesar envío cliente" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "d974d8c2-6e06-41e0-880c-a2ab2f81f641", + "leftValue": "={{ !!$json.quote && $json.customerMode === \"final\" }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 11872, + 928 + ], + "id": "793b94a2-a6d0-4c0b-8ca8-a611dc5c975f", + "name": "¿Guardar quote enviado?" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_save_sent_quote", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.gmailThreadId,p_quote:$json.quote,p_document_url:$json.artifactUrl,p_artifact_id:$json.artifactId,p_artifact_type:$json.artifactType,p_artifact_title:$json.artifactTitle,p_sent_gmail_message_id:$json.sentGmailMessageId}) }", + "options": { + "timeout": 40000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 12368, + 800 + ], + "id": "d691d86e-23bc-4834-8651-3e35072b0c25", + "name": "Supabase - Guardar cotización enviada", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Postprocesar envío cliente\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 12608, + 800 + ], + "id": "7698dbfb-1fac-4906-bf24-5a0a6316a48c", + "name": "Restaurar post envío tras guardar" + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Postprocesar envío cliente\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 12464, + 1232 + ], + "id": "35274e8e-3527-4bb2-9b96-a23c40c6ab22", + "name": "Continuar sin guardar quote" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_record_message", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.gmailThreadId,p_gmail_message_id:$json.sentGmailMessageId,p_direction:'outbound',p_from_email:'wmc@gomezlee.marketing',p_to_emails:[$json.senderEmail],p_subject:$json.subject,p_body_text:$json.agent.reply||'',p_body_html:$json.customerHtml,p_attachments:$json.customerMode==='final'&&$json.artifactUrl?[{filename:$json.artifactTitle||'WMC',mediaType:$json.artifactType||'artifact',url:$json.artifactUrl}]:[],p_metadata:{action:$json.agent.action||'chat',artifactUrl:$json.artifactUrl||null},p_status:$json.customerMode==='clarification'?'awaiting_clarification':'sent'}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 13408, + 1248 + ], + "id": "5463d643-ff69-4a0e-bdcc-02a71bc746ec", + "name": "Supabase - Registrar respuesta al cliente", + "continueOnFail": true + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 13648, + 1248 + ], + "id": "87ab6e4b-9587-4a2d-abe9-011ba22e31b7", + "name": "Fin - Email cliente procesado" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_get_pending_approval", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_gmail_thread_id:$json.gmailThreadId,p_approver_email:$json.senderEmail}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 720, + 448 + ], + "id": "2885f662-e411-420a-bb10-e12588d7c594", + "name": "Supabase - Buscar aprobación pendiente", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const mail=$node[\"Normalizar correo entrante\"].json;\nconst raw=$json||{};\nconst r=raw.body&&typeof raw.body==='object'?raw.body:raw;\nconst found=!!r.found;\nconst normalize=v=>String(v||'').toLowerCase().normalize('NFD').replace(/[\\u0300-\\u036f]/g,'').replace(/\\s+/g,' ').trim();\nconst text=normalize(mail.bodyText||'');\nlet decision='change';\n// Se evalúa únicamente la respuesta nueva (el texto citado de Gmail ya fue retirado).\nif (/^(rechazar|rechazo|no aprobar|no apruebo|cancelar)\\b/.test(text)) decision='reject';\nelse if (/^(aprobar|apruebo|aprobado|confirmo|confirmado|adelante)\\b/.test(text)) decision='approve';\nelse if (/^(cambiar|cambio|modificar|ajustar|corregir)\\b/.test(text)) decision='change';\nreturn [{json:{...mail,pending:r,found,approval:r.approval||null,customerThread:r.customerThread||null,history:r.history||[],context:r.context||{},approvalDecision:decision,approvalInstructions:mail.bodyText}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 960, + 448 + ], + "id": "87090417-f5f4-492a-a9f3-ee99a77f92d2", + "name": "Preparar respuesta de aprobación" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "2391c203-8c51-436b-a7c4-62e86f2963d1", + "leftValue": "={{ $json.found }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 1200, + 448 + ], + "id": "80a80c46-df48-4e3c-b658-db1f72f8bb8b", + "name": "¿Aprobación pendiente encontrada?" + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 1440, + 208 + ], + "id": "2c48258c-8563-4f1b-9ca4-37d5ac6d93cc", + "name": "Fin - Sin aprobación pendiente" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_record_message", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$json.customerThread.gmailThreadId,p_gmail_message_id:$json.gmailMessageId,p_direction:'internal_in',p_from_email:$json.senderEmail,p_to_emails:['wmc@gomezlee.marketing'],p_subject:$json.subject,p_body_text:$json.bodyText,p_body_html:$json.bodyHtml||null,p_attachments:$json.attachmentMeta||[],p_metadata:{approvalId:$json.approval.id},p_status:'pending_approval'}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 1440, + 528 + ], + "id": "a0fcc6ee-8aa6-4f58-8506-626bfbe42ba0", + "name": "Supabase - Registrar respuesta aprobador", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "return [{json:$node[\"Preparar respuesta de aprobación\"].json}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1680, + 528 + ], + "id": "a362cd2f-e5ac-4bd5-a6e0-6279fef142b1", + "name": "Restaurar aprobación tras registro" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "70b77420-e9f5-45c2-a5ce-ba7c06d88ef9", + "leftValue": "={{ $json.approvalDecision }}", + "rightValue": "change", + "operator": { + "type": "string", + "operation": "equals", + "name": "filter.operator.equals" + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 1920, + 528 + ], + "id": "5be3f8fa-7c0b-4e38-b9fe-a4ce636fd7d2", + "name": "¿Solicita cambios internos?" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_decide_approval", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_id:$json.approval.id,p_approver_email:$json.senderEmail,p_decision:$json.approvalDecision,p_note:$json.bodyText}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 2160, + 688 + ], + "id": "1d1234b9-dc97-480e-803f-8661b31645cb", + "name": "Supabase - Decidir aprobación", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Restaurar aprobación tras registro\"].json;const raw=$json||{};const r=raw.body&&typeof raw.body==='object'?raw.body:raw;return [{json:{...base,decisionResult:r,finalDecision:String(r.finalDecision||''),approvalFinalOk:r.ok!==false}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2400, + 688 + ], + "id": "6230ea05-3cc2-4de8-a6f6-5cbd64936aa7", + "name": "Evaluar decisión interna" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "75942c37-1cb3-4221-a5ee-01dca0898f55", + "leftValue": "={{ $json.finalDecision }}", + "rightValue": "approved", + "operator": { + "type": "string", + "operation": "equals", + "name": "filter.operator.equals" + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 2640, + 688 + ], + "id": "cc0e5278-4017-477d-944b-8531f812179d", + "name": "¿Aprobado final?" + }, + { + "parameters": { + "jsCode": "const b=$json;const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const rejected=b.finalDecision==='rejected';const msg=rejected?'La cotización fue rechazada y no se enviará al cliente.':'La aprobación quedó registrada y continúa pendiente de las aprobaciones requeridas.';const html=`

    ${rejected?'Cotización rechazada':'Aprobación registrada'}

    ${esc(msg)}

    `;return [{json:{...b,internalAckHtml:html}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2880, + 848 + ], + "id": "13d60b72-4de5-413f-8091-ac9a615d2b60", + "name": "Preparar confirmación decisión interna" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.internalAckHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 3120, + 848 + ], + "id": "c827ea05-0996-430d-818d-99c01e3decf6", + "name": "Gmail - Confirmar decisión al aprobador", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "23dccd92-8d02-43bd-bca5-c96ce84abd6c", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 3360, + 848 + ], + "id": "63689e52-aad6-468f-8e61-9a851ae73c07", + "name": "Fin - Decisión interna registrada" + }, + { + "parameters": { + "jsCode": "const b=$json;const a=b.approval||{};const q=a.candidateQuote||b.decisionResult?.candidateQuote||{};const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const html=`

    Cotización Walmart Connect

    Hola,

    Adjunto encontrarás la cotización solicitada para ${esc(q.project||'el proyecto indicado')}.

    ${a.artifactUrl?`

    Abrir cotización en Google Workspace

    `:''}

    Quedamos atentos a cualquier comentario o ajuste.

    `;const type=String(a.artifactType||'');return [{json:{...b,quote:q,artifactId:a.artifactId,artifactUrl:a.artifactUrl,artifactType:type,artifactTitle:a.artifactTitle||q.project||'Cotizacion WMC',customerHtml:html,customerMessageId:a.customerGmailMessageId,shouldExport:!!a.artifactId&&['quote','proposal','monthly_glm'].includes(type)}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2880, + 528 + ], + "id": "6325982d-9758-4b41-9b54-abb442790169", + "name": "Preparar envío aprobado al cliente" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "d25c7755-c533-472c-b27e-62b8a46da16e", + "leftValue": "={{ $json.shouldExport }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 3120, + 528 + ], + "id": "9fc5b7cf-f07f-48a3-96fe-dc48e432030d", + "name": "¿Adjuntar archivo aprobado?" + }, + { + "parameters": { + "url": "={{ 'https://www.googleapis.com/drive/v3/files/' + encodeURIComponent($json.artifactId) + '/export?mimeType=' + encodeURIComponent($json.artifactType === 'proposal' ? 'application/pdf' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') }}", + "authentication": "predefinedCredentialType", + "nodeCredentialType": "googleDriveOAuth2Api", + "options": { + "response": { + "response": { + "responseFormat": "file" + } + }, + "timeout": 90000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 3504, + 272 + ], + "id": "3d9f2351-adea-48f2-a349-54d2fd3556ec", + "name": "Descargar artefacto aprobado", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 2500, + "credentials": { + "googleDriveOAuth2Api": { + "id": "g23xdGLZRzBGqKgH", + "name": "Isaac - Google Drive" + } + }, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const base=$node[\"Preparar envío aprobado al cliente\"].json;const b=$binary?.data||null;if(b){b.fileName=(String(base.artifactTitle||'Cotizacion_WMC').replace(/[^a-zA-Z0-9._-]+/g,'_').slice(0,100))+(base.artifactType==='proposal'?'.pdf':'.xlsx');b.mimeType=base.artifactType==='proposal'?'application/pdf':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';}return [{json:{...base,exportOk:!!b},binary:b?{data:b}:{}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3744, + 272 + ], + "id": "074c1f03-b7bc-4d8d-a25c-76fa616db4d1", + "name": "Preparar adjunto aprobado" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "6d87afdd-9702-4c7a-809a-38f5b7331a0f", + "leftValue": "={{ $json.exportOk }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 4240, + 224 + ], + "id": "14065d5b-400d-432f-b30e-83f3e408c1ff", + "name": "¿Archivo aprobado descargado?" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.customerMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "attachmentsUi": { + "attachmentsBinary": [ + {} + ] + }, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 4480, + 144 + ], + "id": "9b7f449f-2574-432c-b318-32c475f10ea7", + "name": "Gmail - Enviar aprobado con archivo", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "ab9cd32a-ae42-48f1-87ba-26e33714c900", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.customerMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 4480, + 352 + ], + "id": "a326b49f-39cd-41c1-aa43-670e4f348933", + "name": "Gmail - Enviar aprobado sin archivo", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "ff99c43e-af13-44ec-8ed5-63b891dbb5a5", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.customerMessageId }}", + "message": "={{ $json.customerHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 3360, + 640 + ], + "id": "7448f893-a0da-49d4-a0c8-6ac38f4a5459", + "name": "Gmail - Enviar aprobado solo enlace", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "0a92c11b-b768-4729-ac5a-d6547891db37", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": { + "jsCode": "const base=$node[\"Preparar envío aprobado al cliente\"].json;const g=$json||{};return [{json:{...base,sentGmailMessageId:String(g.id||''),sentGmailThreadId:String(g.threadId||base.customerThread?.gmailThreadId||'')}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 5360, + 384 + ], + "id": "506a308d-aaec-4d24-8634-9fdbe8aeeddc", + "name": "Postprocesar envío aprobado" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_mark_approval_sent", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_id:$json.approval.id,p_sent_gmail_message_id:$json.sentGmailMessageId}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 5600, + 384 + ], + "id": "a1f193f6-61e8-42d9-a5dc-9dfa58b5da87", + "name": "Supabase - Marcar aprobación enviada", + "continueOnFail": true + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_record_message", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_gmail_thread_id:$node['Postprocesar envío aprobado'].json.customerThread.gmailThreadId,p_gmail_message_id:$node['Postprocesar envío aprobado'].json.sentGmailMessageId,p_direction:'outbound',p_from_email:'wmc@gomezlee.marketing',p_to_emails:[$node['Postprocesar envío aprobado'].json.customerThread.requesterEmail],p_subject:$node['Postprocesar envío aprobado'].json.customerThread.subject,p_body_text:'Cotización aprobada y enviada.',p_body_html:$node['Postprocesar envío aprobado'].json.customerHtml,p_attachments:[{filename:$node['Postprocesar envío aprobado'].json.artifactTitle,mediaType:$node['Postprocesar envío aprobado'].json.artifactType,url:$node['Postprocesar envío aprobado'].json.artifactUrl}],p_metadata:{approvalId:$node['Postprocesar envío aprobado'].json.approval.id},p_status:'sent'}) }", + "options": { + "timeout": 30000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 5840, + 384 + ], + "id": "9299ffeb-f273-4512-8c6a-029931e7139f", + "name": "Supabase - Registrar envío aprobado cliente", + "continueOnFail": true + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 6080, + 384 + ], + "id": "ad781ca1-ba7b-4850-ae31-2ed33cb7cf05", + "name": "Fin - Aprobación enviada al cliente" + }, + { + "parameters": { + "jsCode": "const b=$node[\"Restaurar aprobación tras registro\"].json;const a=b.approval||{};return [{json:{...b,revisionRequest:{gmailThreadId:b.customerThread.gmailThreadId,gmailMessageId:b.gmailMessageId,senderEmail:b.senderEmail,senderName:b.senderName,text:`Revisión interna autorizada por ${b.senderEmail}:\\n${b.approvalInstructions}`,attachments:[],countryCode:b.customerThread.countryCode||null,history:b.history||[],context:b.context||{},emailMeta:{subject:b.customerThread.subject,internalApproval:true,approverEmail:b.senderEmail,requesterEmail:b.customerThread.requesterEmail},approvalRevision:{approvalId:a.id,approverEmail:b.senderEmail,instructions:b.approvalInstructions,candidateQuote:a.candidateQuote,artifactUrl:a.artifactUrl}}}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2160, + 368 + ], + "id": "3e523ab8-90fb-431e-ad5b-384ee83e03a7", + "name": "Preparar revisión interna para agente" + }, + { + "parameters": { + "method": "POST", + "url": "https://agenteit.digitalcompass.agency/webhook/cotizador-wmc-email-agent", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "Content-Type", + "value": "application/json" + }, + { + "name": "X-WMC-Internal-Secret", + "value": "fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={{ JSON.stringify($json.revisionRequest) }}", + "options": { + "timeout": 240000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 2400, + 368 + ], + "id": "b9b37eb4-bedb-4bf4-b29e-983835b05c59", + "name": "Agente WMC - Aplicar cambios aprobador", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 4000, + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const b=$node[\"Preparar revisión interna para agente\"].json;const raw=$json||{};const a=raw.body&&typeof raw.body==='object'?raw.body:raw;const ready=!!(a.quote&&a.artifactUrl&&a.artifactId)&&a.action!=='chat';const q=a.quote||{};const nonT=[];for(const it of (q.items||[])){if(Number(it.totalUsd||0)>0){const c=String(it?.metadata?.priceSourceCode||'').toUpperCase()||'E';if(c!=='T')nonT.push({description:it.description,code:c,amount:Number(it.totalUsd||0)});}}const reasons=[];if(Number(q.totalUsd||0)>10000)reasons.push({code:'OVER_10000',text:`Total USD ${Number(q.totalUsd).toFixed(2)} supera USD 10,000.`});if(nonT.length)reasons.push({code:'NON_TARIFF',text:`${nonT.length} partida(s) fuera de tarifario.`,items:nonT});return [{json:{...b,revisionAgent:a,revisionReady:ready,revisionQuote:a.quote||null,revisionArtifactId:a.artifactId||null,revisionArtifactUrl:a.artifactUrl||null,revisionArtifactType:a.artifactType||null,revisionArtifactTitle:a.title||q.project||'WMC',revisionReasons:reasons}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2640, + 368 + ], + "id": "6e2488a6-0781-45da-8fd5-e2ec64fab9ff", + "name": "Evaluar revisión interna" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 2 + }, + "conditions": [ + { + "id": "21c1085b-3260-4823-8161-2d59fba12d14", + "leftValue": "={{ $json.revisionReady }}", + "rightValue": true, + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.2, + "position": [ + 2880, + 368 + ], + "id": "fe12a681-17e1-4863-aebe-eb77df9fec26", + "name": "¿Revisión regenerada?" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_replace_approval_candidate", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08',p_approval_id:$json.approval.id,p_approver_email:$json.senderEmail,p_quote:$json.revisionQuote,p_document_url:$json.revisionArtifactUrl,p_artifact_id:$json.revisionArtifactId,p_artifact_type:$json.revisionArtifactType,p_artifact_title:$json.revisionArtifactTitle,p_reason:$json.revisionReasons}) }", + "options": { + "timeout": 40000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 3264, + -16 + ], + "id": "d2205239-e261-4540-89f3-8ec3b95bcae8", + "name": "Supabase - Reemplazar candidato aprobación", + "continueOnFail": true + }, + { + "parameters": { + "jsCode": "const b=$node[\"Evaluar revisión interna\"].json;const q=b.revisionQuote||{};const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const html=`

    Borrador actualizado

    Se aplicaron los cambios solicitados. El nuevo total es USD ${Number(q.totalUsd||0).toFixed(2)}.

    ${b.revisionArtifactUrl?`

    Abrir borrador actualizado

    `:''}
    Responde a este hilo con APROBAR, RECHAZAR o CAMBIAR: ...
    `;return [{json:{...b,internalRevisionHtml:html}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3504, + -16 + ], + "id": "4b0e8f7e-8f97-4c15-b1dc-ad0cb3e6a3d0", + "name": "Preparar confirmación revisión GLM" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.internalRevisionHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 3744, + -16 + ], + "id": "bd39629e-7f00-4024-8e06-b97b76da06ea", + "name": "Gmail - Enviar borrador actualizado al aprobador", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "b5b19d95-d7d7-456e-ba99-2c60e80498a9", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 3984, + -16 + ], + "id": "31181c4a-f6fe-43b0-96a2-784e0d809824", + "name": "Fin - Revisión pendiente nueva decisión" + }, + { + "parameters": { + "jsCode": "const b=$json;const esc=s=>String(s??'').replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const msg=esc(b.revisionAgent?.reply||'Necesito una precisión adicional para aplicar el cambio.').replace(/\\n/g,'
    ');const html=`

    Necesito confirmar un detalle del cambio

    ${msg}

    Responde a este mismo correo con la aclaración.

    `;return [{json:{...b,internalRevisionHtml:html}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 3152, + 320 + ], + "id": "175d6f84-a294-41e3-bedd-9ebd7f3215d2", + "name": "Preparar aclaración cambio al aprobador" + }, + { + "parameters": { + "operation": "reply", + "messageId": "={{ $json.gmailMessageId }}", + "message": "={{ $json.internalRevisionHtml }}", + "options": { + "appendAttribution": false, + "senderName": "Walmart Connect", + "replyToSenderOnly": true + } + }, + "type": "n8n-nodes-base.gmail", + "typeVersion": 2.2, + "position": [ + 3616, + 464 + ], + "id": "5ecffd80-3047-438f-9855-30ee11bc5704", + "name": "Gmail - Pedir aclaración al aprobador", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 3000, + "webhookId": "e282116c-ad2a-4509-8f12-be7e95b06c14", + "credentials": { + "gmailOAuth2": { + "id": "8yUN5we9ms6Gjp3h", + "name": "WMC - Gmail - wmc@gomezlee.marketing" + } + } + }, + { + "parameters": {}, + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [ + 3856, + 464 + ], + "id": "f85e6ffd-e7f0-4732-b161-ceed68521561", + "name": "Fin - Esperando aclaración aprobador" + }, + { + "parameters": { + "method": "POST", + "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/cotizador_wmc_email_get_config", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "apikey", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ] + }, + "sendBody": true, + "contentType": "raw", + "rawContentType": "application/json", + "body": "={{ JSON.stringify({p_secret:'fLf-Fl4AcRL912NsWfC4wGwlfEZ9kvOXJ33ylUjXJ9prTuML4b2sSJt3tDrG5D08'}) }}", + "options": { + "timeout": 20000 + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + -32, + 528 + ], + "id": "74d66de7-d63a-4400-ba2b-498c01800035", + "name": "Supabase - Config canal email", + "retryOnFail": true, + "maxTries": 3, + "waitBetweenTries": 1500 + }, + { + "parameters": { + "jsCode": "const mail=$node[\"Normalizar correo entrante\"].json;\nconst raw=$json||{};\nconst cfg=(raw.body&&typeof raw.body==='object')?raw.body:(raw.data&&typeof raw.data==='object'?raw.data:raw);\nconst enabled=cfg.enabled===true || String(cfg.enabled||'').toLowerCase()==='true';\nconst allowTest=cfg.allow_test_sender===true || cfg.allowTestSender===true || String(cfg.allow_test_sender??cfg.allowTestSender??'').toLowerCase()==='true';\nconst testSender=String(cfg.test_sender_email??cfg.testSenderEmail??'iaracena@gomezleemarketing.com').trim().toLowerCase();\nconst walmartDomain=String(cfg.walmart_sender_domain??cfg.walmartSenderDomain??'walmart.com').trim().toLowerCase();\nconst approversRaw=cfg.approver_emails??cfg.approverEmails??['jgomez@gomezleemarketing.com','wlopez@gomezleemarketing.com'];\nconst approvers=(Array.isArray(approversRaw)?approversRaw:String(approversRaw||'').split(',')).map(x=>String(x||'').trim().toLowerCase()).filter(Boolean);\nconst sender=String(mail.senderEmail||'').trim().toLowerCase();\nconst domain=(sender.split('@')[1]||'').toLowerCase();\nconst isApprover=approvers.includes(sender);\nconst isSelf=sender==='wmc@gomezlee.marketing';\nconst isAllowedRequester=enabled && !isSelf && (domain===walmartDomain || (allowTest && sender===testSender));\nreturn [{json:{...mail,emailConfig:cfg,emailEnabled:enabled,allowTestSender:allowTest,testSender,walmartSenderDomain:walmartDomain,approvers,isApprover,isSelf,isAllowedRequester}}];" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 208, + 528 + ], + "id": "f0a4115a-e0c8-44ec-bf85-47cff0143b0a", + "name": "Aplicar configuración canal email" + } + ], + "connections": { + "Gmail Trigger - WMC Inbox": { + "main": [ + [ + { + "node": "Normalizar correo entrante", + "type": "main", + "index": 0 + } + ] + ] + }, + "Normalizar correo entrante": { + "main": [ + [ + { + "node": "Supabase - Config canal email", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Respuesta de aprobador?": { + "main": [ + [ + { + "node": "Supabase - Buscar aprobación pendiente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "¿Remitente permitido?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Remitente permitido?": { + "main": [ + [ + { + "node": "Preparar imágenes email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Fin - Remitente ignorado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar imágenes email": { + "main": [ + [ + { + "node": "¿Tiene imágenes email?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Tiene imágenes email?": { + "main": [ + [ + { + "node": "Gemini - Analizar imágenes email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Sin imágenes email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gemini - Analizar imágenes email": { + "main": [ + [ + { + "node": "Integrar análisis imágenes", + "type": "main", + "index": 0 + } + ] + ] + }, + "Integrar análisis imágenes": { + "main": [ + [ + { + "node": "Preparar PDFs email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sin imágenes email": { + "main": [ + [ + { + "node": "Preparar PDFs email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar PDFs email": { + "main": [ + [ + { + "node": "¿Tiene PDFs email?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Tiene PDFs email?": { + "main": [ + [ + { + "node": "Gemini - Analizar PDFs email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Sin PDFs email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gemini - Analizar PDFs email": { + "main": [ + [ + { + "node": "Integrar análisis PDFs", + "type": "main", + "index": 0 + } + ] + ] + }, + "Integrar análisis PDFs": { + "main": [ + [ + { + "node": "Preparar audio email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sin PDFs email": { + "main": [ + [ + { + "node": "Preparar audio email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar audio email": { + "main": [ + [ + { + "node": "¿Tiene audio email?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Tiene audio email?": { + "main": [ + [ + { + "node": "Gemini - Transcribir audio email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Sin audio email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gemini - Transcribir audio email": { + "main": [ + [ + { + "node": "Integrar transcripción audio", + "type": "main", + "index": 0 + } + ] + ] + }, + "Integrar transcripción audio": { + "main": [ + [ + { + "node": "Preparar XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sin audio email": { + "main": [ + [ + { + "node": "Preparar XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar XLSX email": { + "main": [ + [ + { + "node": "¿Tiene XLSX email?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Tiene XLSX email?": { + "main": [ + [ + { + "node": "Expandir XLSX email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Sin XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Expandir XLSX email": { + "main": [ + [ + { + "node": "Subir XLSX email temporal a Drive", + "type": "main", + "index": 0 + } + ] + ] + }, + "Subir XLSX email temporal a Drive": { + "main": [ + [ + { + "node": "Mapear XLSX email temporal", + "type": "main", + "index": 0 + } + ] + ] + }, + "Mapear XLSX email temporal": { + "main": [ + [ + { + "node": "Convertir XLSX email a Google Sheets", + "type": "main", + "index": 0 + } + ] + ] + }, + "Convertir XLSX email a Google Sheets": { + "main": [ + [ + { + "node": "Mapear XLSX convertido email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Mapear XLSX convertido email": { + "main": [ + [ + { + "node": "Leer todas las hojas XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Leer todas las hojas XLSX email": { + "main": [ + [ + { + "node": "Agregar análisis XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Agregar análisis XLSX email": { + "main": [ + [ + { + "node": "Preparar limpieza XLSX email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar limpieza XLSX email": { + "main": [ + [ + { + "node": "¿Hay temporal XLSX?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Hay temporal XLSX?": { + "main": [ + [ + { + "node": "Eliminar temporal XLSX email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Restaurar base sin limpieza XLSX", + "type": "main", + "index": 0 + } + ] + ] + }, + "Eliminar temporal XLSX email": { + "main": [ + [ + { + "node": "Restaurar base tras limpieza XLSX", + "type": "main", + "index": 0 + } + ] + ] + }, + "Restaurar base tras limpieza XLSX": { + "main": [ + [ + { + "node": "Base email lista para agente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Restaurar base sin limpieza XLSX": { + "main": [ + [ + { + "node": "Base email lista para agente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sin XLSX email": { + "main": [ + [ + { + "node": "Base email lista para agente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Base email lista para agente": { + "main": [ + [ + { + "node": "Supabase - Ingestar email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Ingestar email": { + "main": [ + [ + { + "node": "Construir solicitud agente email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Construir solicitud agente email": { + "main": [ + [ + { + "node": "Agente WMC - Procesar email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Agente WMC - Procesar email": { + "main": [ + [ + { + "node": "Evaluar respuesta agente email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Evaluar respuesta agente email": { + "main": [ + [ + { + "node": "¿Ignorar correo?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Ignorar correo?": { + "main": [ + [ + { + "node": "Fin - Correo fuera de alcance", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "¿Requiere aprobación interna?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Requiere aprobación interna?": { + "main": [ + [ + { + "node": "Supabase - Crear aprobación email", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Construir HTML cliente Walmart", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Crear aprobación email": { + "main": [ + [ + { + "node": "Preparar correo aprobación GLM", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar correo aprobación GLM": { + "main": [ + [ + { + "node": "¿Adjuntar borrador a aprobación?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Adjuntar borrador a aprobación?": { + "main": [ + [ + { + "node": "Descargar borrador para aprobación", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Preparar aprobación sin exportar", + "type": "main", + "index": 0 + } + ] + ] + }, + "Descargar borrador para aprobación": { + "main": [ + [ + { + "node": "Preparar adjunto aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar adjunto aprobación": { + "main": [ + [ + { + "node": "¿Borrador descargado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Borrador descargado?": { + "main": [ + [ + { + "node": "Gmail - Enviar aprobación con adjunto", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Enviar aprobación sin adjunto", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar aprobación sin exportar": { + "main": [ + [ + { + "node": "Gmail - Enviar aprobación solo enlace", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobación con adjunto": { + "main": [ + [ + { + "node": "Supabase - Vincular hilo de aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobación sin adjunto": { + "main": [ + [ + { + "node": "Supabase - Vincular hilo de aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobación solo enlace": { + "main": [ + [ + { + "node": "Supabase - Vincular hilo de aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Vincular hilo de aprobación": { + "main": [ + [ + { + "node": "Supabase - Registrar solicitud aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Registrar solicitud aprobación": { + "main": [ + [ + { + "node": "Fin - Esperando aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Construir HTML cliente Walmart": { + "main": [ + [ + { + "node": "¿Es aclaración?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Es aclaración?": { + "main": [ + [ + { + "node": "Gmail - Responder aclaración cliente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "¿Adjuntar archivo al cliente?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Adjuntar archivo al cliente?": { + "main": [ + [ + { + "node": "Descargar artefacto para cliente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Responder cliente solo enlace", + "type": "main", + "index": 0 + } + ] + ] + }, + "Descargar artefacto para cliente": { + "main": [ + [ + { + "node": "Preparar adjunto cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar adjunto cliente": { + "main": [ + [ + { + "node": "¿Archivo cliente descargado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Archivo cliente descargado?": { + "main": [ + [ + { + "node": "Gmail - Responder cliente con archivo", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Responder cliente sin archivo", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Responder aclaración cliente": { + "main": [ + [ + { + "node": "Postprocesar envío cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Responder cliente con archivo": { + "main": [ + [ + { + "node": "Postprocesar envío cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Responder cliente sin archivo": { + "main": [ + [ + { + "node": "Postprocesar envío cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Responder cliente solo enlace": { + "main": [ + [ + { + "node": "Postprocesar envío cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Postprocesar envío cliente": { + "main": [ + [ + { + "node": "¿Guardar quote enviado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Guardar quote enviado?": { + "main": [ + [ + { + "node": "Supabase - Guardar cotización enviada", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Continuar sin guardar quote", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Guardar cotización enviada": { + "main": [ + [ + { + "node": "Restaurar post envío tras guardar", + "type": "main", + "index": 0 + } + ] + ] + }, + "Restaurar post envío tras guardar": { + "main": [ + [ + { + "node": "Supabase - Registrar respuesta al cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Continuar sin guardar quote": { + "main": [ + [ + { + "node": "Supabase - Registrar respuesta al cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Registrar respuesta al cliente": { + "main": [ + [ + { + "node": "Fin - Email cliente procesado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Buscar aprobación pendiente": { + "main": [ + [ + { + "node": "Preparar respuesta de aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar respuesta de aprobación": { + "main": [ + [ + { + "node": "¿Aprobación pendiente encontrada?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Aprobación pendiente encontrada?": { + "main": [ + [ + { + "node": "Supabase - Registrar respuesta aprobador", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Fin - Sin aprobación pendiente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Registrar respuesta aprobador": { + "main": [ + [ + { + "node": "Restaurar aprobación tras registro", + "type": "main", + "index": 0 + } + ] + ] + }, + "Restaurar aprobación tras registro": { + "main": [ + [ + { + "node": "¿Solicita cambios internos?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Solicita cambios internos?": { + "main": [ + [ + { + "node": "Preparar revisión interna para agente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Supabase - Decidir aprobación", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Decidir aprobación": { + "main": [ + [ + { + "node": "Evaluar decisión interna", + "type": "main", + "index": 0 + } + ] + ] + }, + "Evaluar decisión interna": { + "main": [ + [ + { + "node": "¿Aprobado final?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Aprobado final?": { + "main": [ + [ + { + "node": "Preparar envío aprobado al cliente", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Preparar confirmación decisión interna", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar confirmación decisión interna": { + "main": [ + [ + { + "node": "Gmail - Confirmar decisión al aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Confirmar decisión al aprobador": { + "main": [ + [ + { + "node": "Fin - Decisión interna registrada", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar envío aprobado al cliente": { + "main": [ + [ + { + "node": "¿Adjuntar archivo aprobado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Adjuntar archivo aprobado?": { + "main": [ + [ + { + "node": "Descargar artefacto aprobado", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Enviar aprobado solo enlace", + "type": "main", + "index": 0 + } + ] + ] + }, + "Descargar artefacto aprobado": { + "main": [ + [ + { + "node": "Preparar adjunto aprobado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar adjunto aprobado": { + "main": [ + [ + { + "node": "¿Archivo aprobado descargado?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Archivo aprobado descargado?": { + "main": [ + [ + { + "node": "Gmail - Enviar aprobado con archivo", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Gmail - Enviar aprobado sin archivo", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobado con archivo": { + "main": [ + [ + { + "node": "Postprocesar envío aprobado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobado sin archivo": { + "main": [ + [ + { + "node": "Postprocesar envío aprobado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar aprobado solo enlace": { + "main": [ + [ + { + "node": "Postprocesar envío aprobado", + "type": "main", + "index": 0 + } + ] + ] + }, + "Postprocesar envío aprobado": { + "main": [ + [ + { + "node": "Supabase - Marcar aprobación enviada", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Marcar aprobación enviada": { + "main": [ + [ + { + "node": "Supabase - Registrar envío aprobado cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Registrar envío aprobado cliente": { + "main": [ + [ + { + "node": "Fin - Aprobación enviada al cliente", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar revisión interna para agente": { + "main": [ + [ + { + "node": "Agente WMC - Aplicar cambios aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Agente WMC - Aplicar cambios aprobador": { + "main": [ + [ + { + "node": "Evaluar revisión interna", + "type": "main", + "index": 0 + } + ] + ] + }, + "Evaluar revisión interna": { + "main": [ + [ + { + "node": "¿Revisión regenerada?", + "type": "main", + "index": 0 + } + ] + ] + }, + "¿Revisión regenerada?": { + "main": [ + [ + { + "node": "Supabase - Reemplazar candidato aprobación", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Preparar aclaración cambio al aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Reemplazar candidato aprobación": { + "main": [ + [ + { + "node": "Preparar confirmación revisión GLM", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar confirmación revisión GLM": { + "main": [ + [ + { + "node": "Gmail - Enviar borrador actualizado al aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Enviar borrador actualizado al aprobador": { + "main": [ + [ + { + "node": "Fin - Revisión pendiente nueva decisión", + "type": "main", + "index": 0 + } + ] + ] + }, + "Preparar aclaración cambio al aprobador": { + "main": [ + [ + { + "node": "Gmail - Pedir aclaración al aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Gmail - Pedir aclaración al aprobador": { + "main": [ + [ + { + "node": "Fin - Esperando aclaración aprobador", + "type": "main", + "index": 0 + } + ] + ] + }, + "Supabase - Config canal email": { + "main": [ + [ + { + "node": "Aplicar configuración canal email", + "type": "main", + "index": 0 + } + ] + ] + }, + "Aplicar configuración canal email": { + "main": [ + [ + { + "node": "¿Respuesta de aprobador?", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "authors": "Isaac Aracena", + "name": "Version 5c4f87b4", + "description": "", + "autosaved": true, + "workflowPublishHistory": [ + { + "createdAt": "2026-08-30T00:40:38.081Z", + "id": 5317, + "workflowId": "p4rDtVLIWyPuK0LI", + "versionId": "5c4f87b4-f17a-4b66-9600-388931fcd2b9", + "event": "activated", + "userId": "0a88c0b1-928e-4412-896e-c5d1c99b2029" + } + ] + } +} \ No newline at end of file