The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"updatedAt": "2026-03-25T17:05:27.000Z",
"createdAt": "2026-01-05T04:35:09.412Z",
"id": "93ZMYatYJvCIdKTJ",
"name": "\ud611\ub825\uc0ac opem mall option \uc218\uc815",
"description": null,
"active": false,
"isArchived": true,
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
0,
0
],
"id": "dd218ad6-46a7-42ff-8557-8ec83c23756a",
"name": "When clicking \u2018Execute workflow\u2019"
},
{
"parameters": {
"fileSelector": "/home/node/vendor-automation/n8n_\uc635\uc158\ud06c\ub864\ub9c1_\ub124\uc774\ubc84_\uc644\ub8cc.xlsx",
"options": {}
},
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [
224,
0
],
"id": "67f58866-eaa1-4732-bde2-b8e6a0fdc50e",
"name": "Read/Write Files from Disk"
},
{
"parameters": {
"operation": "xlsx",
"options": {}
},
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1.1,
"position": [
448,
0
],
"id": "b012afbf-cdc2-4c89-a647-e00c4d543b17",
"name": "Extract from File"
},
{
"parameters": {
"jsCode": "const items = $input.all();\n\n// product_variant_vendor_id\ub85c \uadf8\ub8f9\ud551 (\uc21c\uc11c \uc720\uc9c0)\nconst grouped = new Map();\n\nfor (const item of items) {\n const data = item.json;\n const pvvId = data.product_variant_vendor_id;\n \n if (!pvvId) continue;\n \n if (!grouped.has(pvvId)) {\n grouped.set(pvvId, {\n options: [], // \uae30\ubcf8\uc635\uc158\n additionalOptions: [], // \ucd94\uac00\uc635\uc158\n qtyPerUnit: data.open_mall_qty_per_unit || null,\n needsManagerVerification: data.needs_manager_verification === true || data.needs_manager_verification === 'true' || data.needs_manager_verification === 'TRUE'\n });\n }\n \n if (data.option_title) {\n const optionType = data.option_type || \"\uae30\ubcf8\uc635\uc158\";\n \n if (optionType === \"\ucd94\uac00\uc635\uc158\") {\n // \ucd94\uac00\uc635\uc158 \u2192 \ud50c\ub7ab \ub9ac\uc2a4\ud2b8\n grouped.get(pvvId).additionalOptions.push({\n title: data.option_title,\n value: data.option_value || \"\",\n type: data.option_type_select || \"SELECT\"\n });\n } else {\n // \uae30\ubcf8\uc635\uc158 \u2192 \uc138\ud2b8 \uadf8\ub8f9\n grouped.get(pvvId).options.push({\n title: data.option_title,\n value: data.option_value || \"\",\n type: data.option_type_select || \"SELECT\"\n });\n }\n }\n}\n\n// GraphQL mutation input \ud615\uc2dd\uc73c\ub85c \ubcc0\ud658\nconst mutationInput = [];\n\nfor (const [pvvId, groupData] of grouped) {\n const options = groupData.options;\n const additionalOptions = groupData.additionalOptions;\n \n const encodedId = Buffer.from(`ProductVariantVendor:${pvvId}`).toString('base64');\n \n // \uae30\ubcf8\uc635\uc158: \uc138\ud2b8 \uad6c\uc870\ub85c \ubcc0\ud658\n let optionSets = null;\n if (options.length > 0) {\n const uniqueTitles = [];\n for (const opt of options) {\n if (!uniqueTitles.includes(opt.title)) {\n uniqueTitles.push(opt.title);\n }\n }\n const groupSize = uniqueTitles.length;\n \n optionSets = [];\n for (let i = 0; i < options.length; i += groupSize) {\n const setOptions = options.slice(i, i + groupSize);\n optionSets.push({ options: setOptions });\n }\n }\n \n const entry = {\n productVariantVendorId: encodedId\n };\n \n // \uae30\ubcf8\uc635\uc158\n if (optionSets && optionSets.length > 0) {\n entry.openMallOptions = optionSets;\n }\n \n // \ucd94\uac00\uc635\uc158\n if (additionalOptions.length > 0) {\n entry.openMallAdditionalOptions = additionalOptions;\n }\n \n // qtyPerUnit\n if (groupData.qtyPerUnit) {\n entry.openMallQtyPerUnit = parseInt(groupData.qtyPerUnit, 10) || null;\n }\n \n // needsManagerVerification\n if (groupData.needsManagerVerification) {\n entry.needsManagerVerification = true;\n }\n \n // \uc5c5\ub370\uc774\ud2b8\ud560 \ub0b4\uc6a9\uc774 \uc788\ub294 \uacbd\uc6b0\ub9cc \ucd94\uac00\n const hasOptions = entry.openMallOptions && entry.openMallOptions.length > 0;\n const hasAdditionalOptions = entry.openMallAdditionalOptions && entry.openMallAdditionalOptions.length > 0;\n const hasQtyPerUnit = entry.openMallQtyPerUnit;\n const hasVerification = entry.needsManagerVerification;\n \n if (hasOptions || hasAdditionalOptions || hasQtyPerUnit || hasVerification) {\n mutationInput.push(entry);\n }\n}\n\nreturn [{\n json: {\n query: `mutation ProductVariantVendorBulkUpdateOpenMall($input: [ProductVariantVendorBulkUpdateOpenMallInput!]!) {\n productVariantVendorBulkUpdateOpenMall(input: $input) {\n updatedCount\n productErrors { code message }\n }\n }`,\n variables: { input: mutationInput }\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
672,
0
],
"id": "16ac86ab-be2b-4de0-913f-0110391add37",
"name": "\uc624\ud508\ubab0 \uc635\uc158 \uc7ac\uac00\uacf5"
},
{
"parameters": {
"endpoint": "={{ $env.GRAPHQL_URL }}",
"query": "={{ $json.query }}",
"variables": "={{ $json.variables }}",
"headerParametersUi": {
"parameter": [
{
"name": "Authorization",
"value": "={{ $env.AUTH_TOKEN }}"
}
]
}
},
"type": "n8n-nodes-base.graphql",
"typeVersion": 1.1,
"position": [
896,
0
],
"id": "30a52690-fef1-4da7-97a5-9c9251d239ad",
"name": "\uc81c\ud488 \ud611\ub825\uc0ac update mutation"
}
],
"connections": {
"When clicking \u2018Execute workflow\u2019": {
"main": [
[
{
"node": "Read/Write Files from Disk",
"type": "main",
"index": 0
}
]
]
},
"Read/Write Files from Disk": {
"main": [
[
{
"node": "Extract from File",
"type": "main",
"index": 0
}
]
]
},
"Extract from File": {
"main": [
[
{
"node": "\uc624\ud508\ubab0 \uc635\uc158 \uc7ac\uac00\uacf5",
"type": "main",
"index": 0
}
]
]
},
"\uc624\ud508\ubab0 \uc635\uc158 \uc7ac\uac00\uacf5": {
"main": [
[
{
"node": "\uc81c\ud488 \ud611\ub825\uc0ac update mutation",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"meta": null,
"versionId": "c2d0afe7-0a74-482a-881d-a576d62e1e3f",
"activeVersionId": null,
"versionCounter": 23,
"triggerCount": 0,
"tags": [],
"shared": [
{
"updatedAt": "2026-01-05T04:35:09.429Z",
"createdAt": "2026-01-05T04:35:09.429Z",
"role": "workflow:owner",
"workflowId": "93ZMYatYJvCIdKTJ",
"projectId": "PyrRNJYltDksNq22",
"project": {
"updatedAt": "2025-12-17T00:26:00.367Z",
"createdAt": "2025-12-17T00:18:19.940Z",
"id": "PyrRNJYltDksNq22",
"name": "\ub3c4\ud604 \uae40 <dev-do@naver.com>",
"type": "personal",
"icon": null,
"description": null
}
}
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
협력사 opem mall option 수정. Uses readWriteFile, graphql. Event-driven trigger; 5 nodes.
Source: https://github.com/DevAdmin-Riu/auto_consignment/blob/6f555f0834cef4f1c87fff94c31e0344eed2ee52/n8n-workflows/93ZMYatYJvCIdKTJ.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
SwitchSubTask. Uses graphql, n8n-nodes-switch-nine-thousand, executeWorkflowTrigger, emailSend. Event-driven trigger; 30 nodes.
Perfect for disaster recovery or migrating between environments, this workflow automatically identifies your most recent FTP backup and provides a manual restore capability that intelligently excludes
This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.
N8N Workflow. Uses localFileTrigger, executeCommand, readWriteFile. Event-driven trigger; 16 nodes.
🎯 Purpose: Generate audio files from text scripts stored in Google Drive.