Files
aiform_prod/docs/N8N_CODE_PROCESS_UPLOADED_FILES_FIXED.js
AI Assistant 080e7ec105 feat: Получение cf_2624 из MySQL и блокировка полей при подтверждении данных
- Добавлен сервис CrmMySQLService для прямого подключения к MySQL CRM
- Обновлён метод get_draft() для получения cf_2624 напрямую из БД
- Реализована блокировка полей (readonly) при contact_data_confirmed = true
- Добавлен выбор банка для СБП выплат с динамической загрузкой из API
- Обновлена документация по работе с cf_2624 и MySQL
- Добавлен network_mode: host в docker-compose для доступа к MySQL
- Обновлены компоненты формы для поддержки блокировки полей
2025-12-04 12:22:23 +03:00

161 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ============================================================================
// 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}]`;
// ✅ ИСПРАВЛЕНО: uploads_field_labels содержит элементы с индексом 0 (текущий запрос),
// а grp - это позиция в documents_required. Используем индекс 0 для массивов текущего запроса.
const field_label = uploads_field_labels[0] || uploads_field_names[0] || uploads_descriptions[0] || `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[0] || '');
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
}
}];