{ "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" } ] } }