1069 lines
38 KiB
JSON
1069 lines
38 KiB
JSON
{
|
|
"updatedAt": "2026-06-25T11:37:37.854Z",
|
|
"createdAt": "2026-06-10T19:07:24.089Z",
|
|
"id": "IZLgEpGSfWhjj6Qy",
|
|
"name": "Tablero CDC - Migrar Legacy Sheet a Supabase",
|
|
"description": null,
|
|
"active": true,
|
|
"isArchived": false,
|
|
"nodes": [
|
|
{
|
|
"parameters": {
|
|
"documentId": {
|
|
"__rl": true,
|
|
"value": "1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q",
|
|
"mode": "list",
|
|
"cachedResultName": "APROBACIONES PROYECTOS",
|
|
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q/edit?usp=drivesdk"
|
|
},
|
|
"sheetName": {
|
|
"__rl": true,
|
|
"value": 1563472127,
|
|
"mode": "list",
|
|
"cachedResultName": "PROYECTOS 2026",
|
|
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q/edit#gid=1563472127"
|
|
},
|
|
"options": {
|
|
"dataLocationOnSheet": {
|
|
"values": {
|
|
"rangeDefinition": "specifyRangeA1",
|
|
"range": "A3:N183"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.googleSheets",
|
|
"typeVersion": 4.7,
|
|
"position": [
|
|
160,
|
|
-16
|
|
],
|
|
"id": "c2e04d79-3014-49ec-b213-931cf57fa5f1",
|
|
"name": "Sheets - Leer legacy rows",
|
|
"credentials": {
|
|
"googleSheetsOAuth2Api": {
|
|
"id": "K0hDZh3a85MpOHCs",
|
|
"name": "Google Sheets account 2"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const rows = $input.all();\n\nconst FIRST_DATA_ROW = 4;\n\n// PRUEBA SEGURA:\n// Solo migramos la fila 4 por ahora.\n// Cuando validemos, cambiamos esto a 183.\nconst LAST_LEGACY_ROW = 183;\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction createUuid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (char) {\n const random = Math.random() * 16 | 0;\n const value = char === 'x' ? random : (random & 0x3 | 0x8);\n return value.toString(16);\n });\n}\n\nfunction parseAmount(value) {\n const text = clean(value);\n if (!text) return null;\n\n const normalized = text\n .replace(/RD\\$/gi, '')\n .replace(/DOP/gi, '')\n .replace(/,/g, '')\n .trim();\n\n const number = Number(normalized);\n return Number.isFinite(number) ? number : null;\n}\n\nfunction extractRequestedBy(comments) {\n const text = clean(comments);\n const match = text.match(/^solicitado\\s+por\\s+(.+)$/i);\n return match ? match[1].trim() : '';\n}\n\nconst output = [];\n\nrows.forEach((item, index) => {\n const row = item.json;\n\n const sheetRowNumber = FIRST_DATA_ROW + index;\n\n if (sheetRowNumber < FIRST_DATA_ROW || sheetRowNumber > LAST_LEGACY_ROW) {\n return;\n }\n\n const existingProjectId = clean(row['Project ID']);\n if (existingProjectId) {\n return;\n }\n\n const title = clean(row['Tipo o nombre de proyecto']);\n const client = clean(row['Cliente']);\n const country = clean(row['BU Solicita']);\n const brand = clean(row['Marca']);\n const countryManager = clean(row['CM']);\n const status = clean(row['Status']) || 'Activo';\n const comments = clean(row['Comentarios']);\n const proposalLink = clean(row['Link de propuesta']);\n const internalAmount = parseAmount(row['$ Interno Cargado']);\n const briefLink = clean(row['Link del Brief']);\n const finalArtLink = clean(row['Link de artes finales']);\n const year = clean(row['Año']);\n const month = clean(row['Mes']);\n\n if (!title || !client || !country || !brand) {\n throw new Error(\n `Fila ${sheetRowNumber}: faltan campos mínimos. title=\"${title}\", client=\"${client}\", country=\"${country}\", brand=\"${brand}\"`\n );\n }\n\n const projectId = createUuid();\n\n const projectPayload = {\n id: projectId,\n title,\n client,\n brand,\n country,\n requested_by: extractRequestedBy(comments) || null,\n country_manager: countryManager || null,\n description: comments || null,\n status,\n internal_amount: internalAmount,\n currency: 'DOP',\n brief_link: briefLink || null,\n extra_data: {\n legacy_migration: true,\n legacy_source: 'PROYECTOS 2026',\n legacy_sheet_row_number: sheetRowNumber,\n legacy_year: year,\n legacy_month: month,\n migrated_at: new Date().toISOString(),\n },\n };\n\n const links = [];\n\n if (proposalLink) {\n links.push({\n project_id: projectId,\n link_type: 'proposal',\n url: proposalLink,\n label: 'Propuesta legacy',\n extra_data: {\n legacy_migration: true,\n legacy_sheet_row_number: sheetRowNumber,\n },\n });\n }\n\n if (finalArtLink) {\n links.push({\n project_id: projectId,\n link_type: 'final_art',\n url: finalArtLink,\n label: 'Artes finales legacy',\n extra_data: {\n legacy_migration: true,\n legacy_sheet_row_number: sheetRowNumber,\n },\n });\n }\n\n output.push({\n json: {\n sheet_row_number: sheetRowNumber,\n project_id: projectId,\n project_id_cell: `N${sheetRowNumber}`,\n title,\n project_payload: projectPayload,\n links,\n },\n });\n});\n\nreturn output;"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
416,
|
|
-16
|
|
],
|
|
"id": "0303074a-5370-4bab-9fb8-e06e265d17aa",
|
|
"name": "Code - Preparar migracion legacy"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "https://dbit.digitalcompass.agency/rest/v1/tablero_cdc_projects",
|
|
"sendHeaders": true,
|
|
"headerParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "apikey",
|
|
"value": "TU_SERVICE_ROLE_KEY_REAL"
|
|
},
|
|
{
|
|
"name": "Authorization",
|
|
"value": "Bearer TU_SERVICE_ROLE_KEY_REAL"
|
|
},
|
|
{
|
|
"name": "Content-Type",
|
|
"value": "application/json"
|
|
},
|
|
{
|
|
"name": "Prefer",
|
|
"value": "return=minimal"
|
|
}
|
|
]
|
|
},
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ $json.project_payload }}",
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.4,
|
|
"position": [
|
|
624,
|
|
-16
|
|
],
|
|
"id": "6be4d8e1-13d5-4273-b5c5-d83b9ae28188",
|
|
"name": "Supabase - Insertar proyecto legacy"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const preparedItems = $('Code - Preparar migracion legacy').all();\n\nconst output = [];\n\nfor (const item of preparedItems) {\n const links = item.json.links || [];\n\n for (const link of links) {\n output.push({\n json: link,\n });\n }\n}\n\nreturn output;"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
832,
|
|
-16
|
|
],
|
|
"id": "5c149992-85e2-4ade-a32f-e280131b0d5a",
|
|
"name": "Code - Preparar links legacy"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "https://dbit.digitalcompass.agency/rest/v1/tablero_cdc_project_links",
|
|
"sendHeaders": true,
|
|
"headerParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "apikey",
|
|
"value": "TU_SERVICE_ROLE_KEY_REAL"
|
|
},
|
|
{
|
|
"name": "Authorization",
|
|
"value": "Bearer TU_SERVICE_ROLE_KEY_REAL"
|
|
},
|
|
{
|
|
"name": "Content-Type",
|
|
"value": "application/json"
|
|
},
|
|
{
|
|
"name": "Prefer",
|
|
"value": "return=minimal"
|
|
}
|
|
]
|
|
},
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ $json }}",
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.4,
|
|
"position": [
|
|
1040,
|
|
-16
|
|
],
|
|
"id": "5968b76f-2846-4c2f-a643-a52116e544a3",
|
|
"name": "Supabase - Insertar links legacy"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const preparedItems = $('Code - Preparar migracion legacy').all();\n\nreturn preparedItems.map(item => {\n return {\n json: {\n row_number: item.json.sheet_row_number,\n project_id: item.json.project_id,\n title: item.json.title,\n project_id_cell: item.json.project_id_cell,\n },\n };\n});"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1248,
|
|
-16
|
|
],
|
|
"id": "056908f7-3f2c-48d6-8613-90cd8eb3a3d3",
|
|
"name": "Code - Preparar Project IDs Sheet"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"operation": "update",
|
|
"documentId": {
|
|
"__rl": true,
|
|
"value": "1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q",
|
|
"mode": "list",
|
|
"cachedResultName": "APROBACIONES PROYECTOS",
|
|
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q/edit?usp=drivesdk"
|
|
},
|
|
"sheetName": {
|
|
"__rl": true,
|
|
"value": 1563472127,
|
|
"mode": "list",
|
|
"cachedResultName": "PROYECTOS 2026",
|
|
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q/edit#gid=1563472127"
|
|
},
|
|
"columns": {
|
|
"mappingMode": "defineBelow",
|
|
"value": {
|
|
"row_number": "={{ $json.row_number }}",
|
|
"Project ID": "={{ $json.project_id }}"
|
|
},
|
|
"matchingColumns": [
|
|
"row_number"
|
|
],
|
|
"schema": [
|
|
{
|
|
"id": "Año",
|
|
"displayName": "Año",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Mes",
|
|
"displayName": "Mes",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Tipo o nombre de proyecto",
|
|
"displayName": "Tipo o nombre de proyecto",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Cliente",
|
|
"displayName": "Cliente",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "BU Solicita",
|
|
"displayName": "BU Solicita",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Marca",
|
|
"displayName": "Marca",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "CM",
|
|
"displayName": "CM",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Status",
|
|
"displayName": "Status",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Comentarios",
|
|
"displayName": "Comentarios",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Link de propuesta",
|
|
"displayName": "Link de propuesta",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "$ Interno Cargado",
|
|
"displayName": "$ Interno Cargado",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Link del Brief",
|
|
"displayName": "Link del Brief",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Link de artes finales",
|
|
"displayName": "Link de artes finales",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Project ID",
|
|
"displayName": "Project ID",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": false
|
|
},
|
|
{
|
|
"id": "row_number",
|
|
"displayName": "row_number",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "number",
|
|
"canBeUsedToMatch": true,
|
|
"readOnly": true,
|
|
"removed": false
|
|
}
|
|
],
|
|
"attemptToConvertTypes": false,
|
|
"convertFieldsToString": false
|
|
},
|
|
"options": {
|
|
"locationDefine": {
|
|
"values": {
|
|
"headerRow": 3,
|
|
"firstDataRow": 4
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.googleSheets",
|
|
"typeVersion": 4.7,
|
|
"position": [
|
|
1456,
|
|
-16
|
|
],
|
|
"id": "666a950b-cd80-4f0a-885b-80745e74bb0b",
|
|
"name": "Sheets - Escribir Project ID legacy",
|
|
"credentials": {
|
|
"googleSheetsOAuth2Api": {
|
|
"id": "K0hDZh3a85MpOHCs",
|
|
"name": "Google Sheets account 2"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"path": "tablero-cdc-migracion-legacy-archivada",
|
|
"responseMode": "responseNode",
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.webhook",
|
|
"typeVersion": 2.1,
|
|
"position": [
|
|
-304,
|
|
16
|
|
],
|
|
"id": "9ba81599-f14c-45c7-b273-2ee1f6d2e8da",
|
|
"name": "Webhook",
|
|
"webhookId": "ba3e5457-3806-4e55-ac0b-9e4d90d3735c"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"respondWith": "json",
|
|
"responseBody": "{\n \"ok\": true,\n \"status\": \"archived\",\n \"workflow\": \"Tablero CDC - Migrar Legacy Sheet a Supabase\",\n \"message\": \"Workflow archivado solo para respaldo en Gitea. No ejecuta migración.\"\n}",
|
|
"options": {
|
|
"responseCode": 200
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.respondToWebhook",
|
|
"typeVersion": 1.5,
|
|
"position": [
|
|
-48,
|
|
16
|
|
],
|
|
"id": "aef53048-0059-46ce-9eb6-36be924d678b",
|
|
"name": "Respond - Workflow archivado"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"content": "## Migrar los proyectos históricos del Sheet PROYECTOS 2026 a Supabase.\n\nEl Webhook publicado es solo para que el flujo de respaldo a Gitea pueda guardar este workflow.\n\n",
|
|
"height": 336,
|
|
"width": 2048,
|
|
"color": "#33801E"
|
|
},
|
|
"type": "n8n-nodes-base.stickyNote",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
-352,
|
|
-128
|
|
],
|
|
"id": "f45a8a78-a258-4934-b755-9f82792a6d69",
|
|
"name": "Sticky Note"
|
|
}
|
|
],
|
|
"connections": {
|
|
"Sheets - Leer legacy rows": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code - Preparar migracion legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code - Preparar migracion legacy": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Supabase - Insertar proyecto legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Supabase - Insertar proyecto legacy": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code - Preparar links legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code - Preparar links legacy": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Supabase - Insertar links legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Supabase - Insertar links legacy": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code - Preparar Project IDs Sheet",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code - Preparar Project IDs Sheet": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Sheets - Escribir Project ID legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Webhook": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Respond - Workflow archivado",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Respond - Workflow archivado": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Sheets - Leer legacy rows",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"settings": {
|
|
"executionOrder": "v1",
|
|
"binaryMode": "separate"
|
|
},
|
|
"staticData": null,
|
|
"meta": {
|
|
"templateCredsSetupCompleted": true
|
|
},
|
|
"versionId": "e3cc75d8-5d2d-421f-9714-45efb1d62aa1",
|
|
"activeVersionId": "e3cc75d8-5d2d-421f-9714-45efb1d62aa1",
|
|
"versionCounter": 173,
|
|
"triggerCount": 1,
|
|
"shared": [
|
|
{
|
|
"updatedAt": "2026-06-10T19:07:24.096Z",
|
|
"createdAt": "2026-06-10T19:07:24.096Z",
|
|
"role": "workflow:owner",
|
|
"workflowId": "IZLgEpGSfWhjj6Qy",
|
|
"projectId": "PJpTANzTXIFibWsW",
|
|
"project": {
|
|
"updatedAt": "2026-04-22T14:25:09.686Z",
|
|
"createdAt": "2026-04-22T14:22:54.790Z",
|
|
"id": "PJpTANzTXIFibWsW",
|
|
"name": "Isaac Aracena <iaracena@gomezleemarketing.com>",
|
|
"type": "personal",
|
|
"icon": null,
|
|
"description": null,
|
|
"creatorId": "0a88c0b1-928e-4412-896e-c5d1c99b2029"
|
|
}
|
|
}
|
|
],
|
|
"tags": [],
|
|
"activeVersion": {
|
|
"updatedAt": "2026-06-25T11:37:39.000Z",
|
|
"createdAt": "2026-06-25T11:37:37.856Z",
|
|
"versionId": "e3cc75d8-5d2d-421f-9714-45efb1d62aa1",
|
|
"workflowId": "IZLgEpGSfWhjj6Qy",
|
|
"nodes": [
|
|
{
|
|
"parameters": {
|
|
"documentId": {
|
|
"__rl": true,
|
|
"value": "1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q",
|
|
"mode": "list",
|
|
"cachedResultName": "APROBACIONES PROYECTOS",
|
|
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q/edit?usp=drivesdk"
|
|
},
|
|
"sheetName": {
|
|
"__rl": true,
|
|
"value": 1563472127,
|
|
"mode": "list",
|
|
"cachedResultName": "PROYECTOS 2026",
|
|
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q/edit#gid=1563472127"
|
|
},
|
|
"options": {
|
|
"dataLocationOnSheet": {
|
|
"values": {
|
|
"rangeDefinition": "specifyRangeA1",
|
|
"range": "A3:N183"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.googleSheets",
|
|
"typeVersion": 4.7,
|
|
"position": [
|
|
160,
|
|
-16
|
|
],
|
|
"id": "c2e04d79-3014-49ec-b213-931cf57fa5f1",
|
|
"name": "Sheets - Leer legacy rows",
|
|
"credentials": {
|
|
"googleSheetsOAuth2Api": {
|
|
"id": "K0hDZh3a85MpOHCs",
|
|
"name": "Google Sheets account 2"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const rows = $input.all();\n\nconst FIRST_DATA_ROW = 4;\n\n// PRUEBA SEGURA:\n// Solo migramos la fila 4 por ahora.\n// Cuando validemos, cambiamos esto a 183.\nconst LAST_LEGACY_ROW = 183;\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction createUuid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (char) {\n const random = Math.random() * 16 | 0;\n const value = char === 'x' ? random : (random & 0x3 | 0x8);\n return value.toString(16);\n });\n}\n\nfunction parseAmount(value) {\n const text = clean(value);\n if (!text) return null;\n\n const normalized = text\n .replace(/RD\\$/gi, '')\n .replace(/DOP/gi, '')\n .replace(/,/g, '')\n .trim();\n\n const number = Number(normalized);\n return Number.isFinite(number) ? number : null;\n}\n\nfunction extractRequestedBy(comments) {\n const text = clean(comments);\n const match = text.match(/^solicitado\\s+por\\s+(.+)$/i);\n return match ? match[1].trim() : '';\n}\n\nconst output = [];\n\nrows.forEach((item, index) => {\n const row = item.json;\n\n const sheetRowNumber = FIRST_DATA_ROW + index;\n\n if (sheetRowNumber < FIRST_DATA_ROW || sheetRowNumber > LAST_LEGACY_ROW) {\n return;\n }\n\n const existingProjectId = clean(row['Project ID']);\n if (existingProjectId) {\n return;\n }\n\n const title = clean(row['Tipo o nombre de proyecto']);\n const client = clean(row['Cliente']);\n const country = clean(row['BU Solicita']);\n const brand = clean(row['Marca']);\n const countryManager = clean(row['CM']);\n const status = clean(row['Status']) || 'Activo';\n const comments = clean(row['Comentarios']);\n const proposalLink = clean(row['Link de propuesta']);\n const internalAmount = parseAmount(row['$ Interno Cargado']);\n const briefLink = clean(row['Link del Brief']);\n const finalArtLink = clean(row['Link de artes finales']);\n const year = clean(row['Año']);\n const month = clean(row['Mes']);\n\n if (!title || !client || !country || !brand) {\n throw new Error(\n `Fila ${sheetRowNumber}: faltan campos mínimos. title=\"${title}\", client=\"${client}\", country=\"${country}\", brand=\"${brand}\"`\n );\n }\n\n const projectId = createUuid();\n\n const projectPayload = {\n id: projectId,\n title,\n client,\n brand,\n country,\n requested_by: extractRequestedBy(comments) || null,\n country_manager: countryManager || null,\n description: comments || null,\n status,\n internal_amount: internalAmount,\n currency: 'DOP',\n brief_link: briefLink || null,\n extra_data: {\n legacy_migration: true,\n legacy_source: 'PROYECTOS 2026',\n legacy_sheet_row_number: sheetRowNumber,\n legacy_year: year,\n legacy_month: month,\n migrated_at: new Date().toISOString(),\n },\n };\n\n const links = [];\n\n if (proposalLink) {\n links.push({\n project_id: projectId,\n link_type: 'proposal',\n url: proposalLink,\n label: 'Propuesta legacy',\n extra_data: {\n legacy_migration: true,\n legacy_sheet_row_number: sheetRowNumber,\n },\n });\n }\n\n if (finalArtLink) {\n links.push({\n project_id: projectId,\n link_type: 'final_art',\n url: finalArtLink,\n label: 'Artes finales legacy',\n extra_data: {\n legacy_migration: true,\n legacy_sheet_row_number: sheetRowNumber,\n },\n });\n }\n\n output.push({\n json: {\n sheet_row_number: sheetRowNumber,\n project_id: projectId,\n project_id_cell: `N${sheetRowNumber}`,\n title,\n project_payload: projectPayload,\n links,\n },\n });\n});\n\nreturn output;"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
416,
|
|
-16
|
|
],
|
|
"id": "0303074a-5370-4bab-9fb8-e06e265d17aa",
|
|
"name": "Code - Preparar migracion legacy"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "https://dbit.digitalcompass.agency/rest/v1/tablero_cdc_projects",
|
|
"sendHeaders": true,
|
|
"headerParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "apikey",
|
|
"value": "TU_SERVICE_ROLE_KEY_REAL"
|
|
},
|
|
{
|
|
"name": "Authorization",
|
|
"value": "Bearer TU_SERVICE_ROLE_KEY_REAL"
|
|
},
|
|
{
|
|
"name": "Content-Type",
|
|
"value": "application/json"
|
|
},
|
|
{
|
|
"name": "Prefer",
|
|
"value": "return=minimal"
|
|
}
|
|
]
|
|
},
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ $json.project_payload }}",
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.4,
|
|
"position": [
|
|
624,
|
|
-16
|
|
],
|
|
"id": "6be4d8e1-13d5-4273-b5c5-d83b9ae28188",
|
|
"name": "Supabase - Insertar proyecto legacy"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const preparedItems = $('Code - Preparar migracion legacy').all();\n\nconst output = [];\n\nfor (const item of preparedItems) {\n const links = item.json.links || [];\n\n for (const link of links) {\n output.push({\n json: link,\n });\n }\n}\n\nreturn output;"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
832,
|
|
-16
|
|
],
|
|
"id": "5c149992-85e2-4ade-a32f-e280131b0d5a",
|
|
"name": "Code - Preparar links legacy"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "https://dbit.digitalcompass.agency/rest/v1/tablero_cdc_project_links",
|
|
"sendHeaders": true,
|
|
"headerParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "apikey",
|
|
"value": "TU_SERVICE_ROLE_KEY_REAL"
|
|
},
|
|
{
|
|
"name": "Authorization",
|
|
"value": "Bearer TU_SERVICE_ROLE_KEY_REAL"
|
|
},
|
|
{
|
|
"name": "Content-Type",
|
|
"value": "application/json"
|
|
},
|
|
{
|
|
"name": "Prefer",
|
|
"value": "return=minimal"
|
|
}
|
|
]
|
|
},
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ $json }}",
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 4.4,
|
|
"position": [
|
|
1040,
|
|
-16
|
|
],
|
|
"id": "5968b76f-2846-4c2f-a643-a52116e544a3",
|
|
"name": "Supabase - Insertar links legacy"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const preparedItems = $('Code - Preparar migracion legacy').all();\n\nreturn preparedItems.map(item => {\n return {\n json: {\n row_number: item.json.sheet_row_number,\n project_id: item.json.project_id,\n title: item.json.title,\n project_id_cell: item.json.project_id_cell,\n },\n };\n});"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1248,
|
|
-16
|
|
],
|
|
"id": "056908f7-3f2c-48d6-8613-90cd8eb3a3d3",
|
|
"name": "Code - Preparar Project IDs Sheet"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"operation": "update",
|
|
"documentId": {
|
|
"__rl": true,
|
|
"value": "1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q",
|
|
"mode": "list",
|
|
"cachedResultName": "APROBACIONES PROYECTOS",
|
|
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q/edit?usp=drivesdk"
|
|
},
|
|
"sheetName": {
|
|
"__rl": true,
|
|
"value": 1563472127,
|
|
"mode": "list",
|
|
"cachedResultName": "PROYECTOS 2026",
|
|
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MfoIs_y7-4ad-g5dxzOo8oAFIdraA_ZT4k-OCGMtT4Q/edit#gid=1563472127"
|
|
},
|
|
"columns": {
|
|
"mappingMode": "defineBelow",
|
|
"value": {
|
|
"row_number": "={{ $json.row_number }}",
|
|
"Project ID": "={{ $json.project_id }}"
|
|
},
|
|
"matchingColumns": [
|
|
"row_number"
|
|
],
|
|
"schema": [
|
|
{
|
|
"id": "Año",
|
|
"displayName": "Año",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Mes",
|
|
"displayName": "Mes",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Tipo o nombre de proyecto",
|
|
"displayName": "Tipo o nombre de proyecto",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Cliente",
|
|
"displayName": "Cliente",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "BU Solicita",
|
|
"displayName": "BU Solicita",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Marca",
|
|
"displayName": "Marca",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "CM",
|
|
"displayName": "CM",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Status",
|
|
"displayName": "Status",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Comentarios",
|
|
"displayName": "Comentarios",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Link de propuesta",
|
|
"displayName": "Link de propuesta",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "$ Interno Cargado",
|
|
"displayName": "$ Interno Cargado",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Link del Brief",
|
|
"displayName": "Link del Brief",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Link de artes finales",
|
|
"displayName": "Link de artes finales",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "Project ID",
|
|
"displayName": "Project ID",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": false
|
|
},
|
|
{
|
|
"id": "row_number",
|
|
"displayName": "row_number",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "number",
|
|
"canBeUsedToMatch": true,
|
|
"readOnly": true,
|
|
"removed": false
|
|
}
|
|
],
|
|
"attemptToConvertTypes": false,
|
|
"convertFieldsToString": false
|
|
},
|
|
"options": {
|
|
"locationDefine": {
|
|
"values": {
|
|
"headerRow": 3,
|
|
"firstDataRow": 4
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.googleSheets",
|
|
"typeVersion": 4.7,
|
|
"position": [
|
|
1456,
|
|
-16
|
|
],
|
|
"id": "666a950b-cd80-4f0a-885b-80745e74bb0b",
|
|
"name": "Sheets - Escribir Project ID legacy",
|
|
"credentials": {
|
|
"googleSheetsOAuth2Api": {
|
|
"id": "K0hDZh3a85MpOHCs",
|
|
"name": "Google Sheets account 2"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"path": "tablero-cdc-migracion-legacy-archivada",
|
|
"responseMode": "responseNode",
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.webhook",
|
|
"typeVersion": 2.1,
|
|
"position": [
|
|
-304,
|
|
16
|
|
],
|
|
"id": "9ba81599-f14c-45c7-b273-2ee1f6d2e8da",
|
|
"name": "Webhook",
|
|
"webhookId": "ba3e5457-3806-4e55-ac0b-9e4d90d3735c"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"respondWith": "json",
|
|
"responseBody": "{\n \"ok\": true,\n \"status\": \"archived\",\n \"workflow\": \"Tablero CDC - Migrar Legacy Sheet a Supabase\",\n \"message\": \"Workflow archivado solo para respaldo en Gitea. No ejecuta migración.\"\n}",
|
|
"options": {
|
|
"responseCode": 200
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.respondToWebhook",
|
|
"typeVersion": 1.5,
|
|
"position": [
|
|
-48,
|
|
16
|
|
],
|
|
"id": "aef53048-0059-46ce-9eb6-36be924d678b",
|
|
"name": "Respond - Workflow archivado"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"content": "## Migrar los proyectos históricos del Sheet PROYECTOS 2026 a Supabase.\n\nEl Webhook publicado es solo para que el flujo de respaldo a Gitea pueda guardar este workflow.\n\n",
|
|
"height": 336,
|
|
"width": 2048,
|
|
"color": "#33801E"
|
|
},
|
|
"type": "n8n-nodes-base.stickyNote",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
-352,
|
|
-128
|
|
],
|
|
"id": "f45a8a78-a258-4934-b755-9f82792a6d69",
|
|
"name": "Sticky Note"
|
|
}
|
|
],
|
|
"connections": {
|
|
"Sheets - Leer legacy rows": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code - Preparar migracion legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code - Preparar migracion legacy": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Supabase - Insertar proyecto legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Supabase - Insertar proyecto legacy": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code - Preparar links legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code - Preparar links legacy": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Supabase - Insertar links legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Supabase - Insertar links legacy": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code - Preparar Project IDs Sheet",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code - Preparar Project IDs Sheet": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Sheets - Escribir Project ID legacy",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Webhook": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Respond - Workflow archivado",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Respond - Workflow archivado": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Sheets - Leer legacy rows",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"authors": "Isaac Aracena",
|
|
"name": "Version e3cc75d8",
|
|
"description": "",
|
|
"autosaved": true,
|
|
"workflowPublishHistory": [
|
|
{
|
|
"createdAt": "2026-06-25T11:37:39.415Z",
|
|
"id": 1875,
|
|
"workflowId": "IZLgEpGSfWhjj6Qy",
|
|
"versionId": "e3cc75d8-5d2d-421f-9714-45efb1d62aa1",
|
|
"event": "activated",
|
|
"userId": "0a88c0b1-928e-4412-896e-c5d1c99b2029"
|
|
}
|
|
]
|
|
}
|
|
} |