// ============================================================================ // n8n Code Node: Обработка загруженных файлов (ИСПРАВЛЕННАЯ ВЕРСИЯ) // ============================================================================ // OCR возвращает объединённые документы: один файл на группу (group_index) // Структура: { data: [{ group_index_num: 0, files_count: 2, newfile: "...", ... }] } // Решение: обрабатываем каждый элемент из data как объединённый документ // ============================================================================ // ==== INPUT SHAPE SUPPORT ==== // OCR возвращает: { data: [ ...объединённые документы... ] } const raw = $json; const items = Array.isArray(raw?.data) ? raw.data : (Array.isArray(raw) ? raw : []); if (!items.length) { return [{ json: { claim_id: null, payload_partial_json: { documents_meta: [], edit_fields_raw: null, edit_fields_parsed: null }, filesRows: [] } }]; } // ==== CLAIM_ID DISCOVERY ==== let claim_id = $json.claim_id || $items('Edit Fields6')?.[0]?.json?.propertyName?.case_id || $('Edit Fields6').first().json.body.claim_id || null; // ==== UTILS ==== const safeStr = (v) => (v == null ? '' : String(v)); const nowIso = new Date().toISOString(); const tryParseJSON = (x) => { if (x == null) return null; if (typeof x === 'object') return x; if (typeof x === 'string') { try { return JSON.parse(x); } catch { return null; } } return null; }; // ==== ПРЕДВАРИТЕЛЬНО СОБИРАЕМ uploads_field_labels ИЗ BODY ==== const editRaw = $items('Edit Fields6')?.[0]?.json || null; const body = editRaw?.body || null; let uploads_descriptions = []; let uploads_field_names = []; let uploads_field_labels = []; if (body && typeof body === 'object') { const d = []; const f = []; const l = []; for (const k of Object.keys(body)) { const mD = k.match(/^uploads_descriptions\[(\d+)\]$/); const mF = k.match(/^uploads_field_names\[(\d+)\]$/); const mL = k.match(/^uploads_field_labels\[(\d+)\]$/); if (mD) d[Number(mD[1])] = safeStr(body[k]); if (mF) f[Number(mF[1])] = safeStr(body[k]); if (mL) l[Number(mL[1])] = safeStr(body[k]); } uploads_descriptions = d.filter(v => v !== undefined); uploads_field_names = f.filter(v => v !== undefined); uploads_field_labels = l.filter(v => v !== undefined); } // ==== BUILD documents_meta + filesRows ==== // OCR возвращает объединённые документы: один файл на group_index // Каждый элемент из data - это уже объединённый PDF (может содержать несколько страниц) const documents_meta = []; const filesRows = []; for (const it of items) { // ✅ ПРИОРИТЕТ: Используем group_index из body (переданный с фронтенда) // Если его нет - используем group_index_num из OCR // Если и его нет - пытаемся определить по document_type из uploads_field_names let grp = null; if (body && body.group_index !== undefined && body.group_index !== null) { grp = Number(body.group_index); } else if (it.group_index_num !== undefined && it.group_index_num !== null) { grp = Number(it.group_index_num); } else { // Fallback: пытаемся определить по document_type const doc_type = uploads_field_names[0] || uploads_field_labels[0] || ''; // Ищем индекс в documents_required по типу документа // Это не идеально, но лучше чем всегда 0 grp = 0; // По умолчанию 0, если не можем определить } grp = grp || 0; const file_index = 0; // После объединения всегда один файл на группу const field_name = `uploads[${grp}][${file_index}]`; const field_label = uploads_field_labels[grp] || uploads_field_names[grp] || uploads_descriptions[grp] || `group-${grp}`; // OCR уже объединил файлы, используем newfile (путь к объединённому файлу) const draft_key = safeStr(it.newfile || (it.folder && it.file_name ? `${it.folder}/${it.file_name}` : '')); const original_name = safeStr(it.file_name || `group_${grp}.pdf`); const description = safeStr(it.description || uploads_descriptions[grp] || ''); const prefix = safeStr(it.prefix || ''); // files_count показывает, сколько исходных файлов было объединено const files_count = Number(it.files_count) || 1; const pages = Number(it.pages) || null; documents_meta.push({ field_name, field_label, file_id: draft_key, file_name: original_name, original_file_name: original_name, uploaded_at: nowIso, files_count, // Информация: сколько файлов было объединено pages, // Информация: сколько страниц в объединённом PDF }); filesRows.push({ claim_id, group_index: grp, file_index, // Всегда 0 для объединённого документа original_name, draft_key, mime: 'application/pdf', size_bytes: null, description, prefix, field_name, field_label, files_count, // Информация для отладки pages, // Информация для отладки }); } // ==== ПОДТЯГИВАЕМ ВСЁ ИЗ "Edit Fields" ==== const propertyName = editRaw?.propertyName || null; const answers_parsed = body ? (tryParseJSON(body.answers) || null) : null; const wizard_plan_parsed = body ? (tryParseJSON(body.wizard_plan) || null) : null; // ==== OUTPUT ==== return [{ json: { claim_id, payload_partial_json: { documents_meta, edit_fields_raw: editRaw || null, edit_fields_parsed: { propertyName, body, uploads_descriptions, uploads_field_names, uploads_field_labels, answers_parsed, wizard_plan_parsed, } }, filesRows } }];