Добавлено логирование для отладки черновиков
- Добавлены логи в frontend (ClaimForm.tsx) для отслеживания unified_id и запросов к API - Добавлены логи в backend (claims.py) для отладки SQL запросов - Создан лог сессии с описанием проблемы и текущего состояния - Проблема: API возвращает 0 черновиков, хотя в БД есть данные
This commit is contained in:
212
docs/CODE1_FIXED_CODE.js
Normal file
212
docs/CODE1_FIXED_CODE.js
Normal file
@@ -0,0 +1,212 @@
|
||||
// Code node (JavaScript). Input: items[0].json = либо объект, либо массив таких объектов, как ты прислал.
|
||||
// Output: по одному нормализованному объекту на кейс.
|
||||
// Никаких внешних зависимостей, всё на ванильном JS.
|
||||
|
||||
function toNullish(v) {
|
||||
if (v === undefined || v === null) return null;
|
||||
if (typeof v === 'string' && v.trim() === '') return null;
|
||||
return v;
|
||||
}
|
||||
|
||||
function pick(o, path, def = null) {
|
||||
try {
|
||||
return toNullish(path.split('.').reduce((acc, k) => (acc == null ? undefined : acc[k]), o));
|
||||
} catch {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
function mapDocuments(docs = []) {
|
||||
// Проверяем, что docs не null и является массивом
|
||||
if (!docs || !Array.isArray(docs)) return [];
|
||||
return docs.map(d => ({
|
||||
id: toNullish(d.id),
|
||||
claim_document_id: toNullish(d.id), // у тебя id = claim_document_id
|
||||
file_id: toNullish(d.file_id),
|
||||
file_url: toNullish(d.file_url),
|
||||
file_name: toNullish(d.file_name),
|
||||
original_file_name: toNullish(d.original_file_name),
|
||||
field_name: toNullish(d.field_name),
|
||||
upload_description: toNullish(d.upload_description),
|
||||
uploaded_at: toNullish(d.uploaded_at),
|
||||
filename_for_upload: toNullish(d.filename_for_upload),
|
||||
}));
|
||||
}
|
||||
|
||||
function mapVisionDocs(vds = []) {
|
||||
// Проверяем, что vds не null и является массивом
|
||||
if (!vds || !Array.isArray(vds)) return [];
|
||||
return vds.map(v => ({
|
||||
claim_document_id: toNullish(v.claim_document_id),
|
||||
vision_document_id: toNullish(v.vision_document_id),
|
||||
pages: toNullish(v.pages),
|
||||
content_sha256: toNullish(v.content_sha256),
|
||||
vision_text: toNullish(v.vision_text),
|
||||
vision_pages: Array.isArray(v.vision_pages)
|
||||
? v.vision_pages.map(p => ({
|
||||
page: toNullish(p.page),
|
||||
uid: toNullish(p.uid),
|
||||
}))
|
||||
: null,
|
||||
}));
|
||||
}
|
||||
|
||||
function mapCombinedDocs(cds = []) {
|
||||
// Проверяем, что cds не null и является массивом
|
||||
if (!cds || !Array.isArray(cds)) return [];
|
||||
return cds.map(c => ({
|
||||
claim_document_id: toNullish(c.claim_document_id),
|
||||
combined_document_id: toNullish(c.combined_document_id),
|
||||
pages: toNullish(c.pages),
|
||||
content_sha256: toNullish(c.content_sha256),
|
||||
combined_text: toNullish(c.combined_text),
|
||||
page_summaries: Array.isArray(c.page_summaries)
|
||||
? c.page_summaries.map(ps => ({
|
||||
page: toNullish(ps.page),
|
||||
chars: toNullish(ps.chars),
|
||||
uid: toNullish(ps.uid),
|
||||
image_url: toNullish(ps.image_url),
|
||||
}))
|
||||
: null,
|
||||
}));
|
||||
}
|
||||
|
||||
function mapDialogHistory(h = []) {
|
||||
// ИСПРАВЛЕНО: Проверяем, что h не null и является массивом
|
||||
if (!h || !Array.isArray(h)) return [];
|
||||
return h.map(m => ({
|
||||
id: toNullish(m.id),
|
||||
role: toNullish(m.role),
|
||||
message: toNullish(m.message),
|
||||
message_type: toNullish(m.message_type),
|
||||
tg_message_id: toNullish(m.tg_message_id),
|
||||
created_at: toNullish(m.created_at),
|
||||
}));
|
||||
}
|
||||
|
||||
function mapCoverageReport(cr = null) {
|
||||
if (!cr) return null;
|
||||
return {
|
||||
questions: Array.isArray(cr.questions)
|
||||
? cr.questions.map(q => ({
|
||||
name: toNullish(q.name),
|
||||
value: toNullish(q.value),
|
||||
status: toNullish(q.status),
|
||||
source: toNullish(q.source),
|
||||
confidence: toNullish(q.confidence),
|
||||
}))
|
||||
: null,
|
||||
docs_missing: Array.isArray(cr.docs_missing) ? cr.docs_missing : null,
|
||||
docs_received: Array.isArray(cr.docs_received) ? cr.docs_received : null,
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeOne(src) {
|
||||
const claim = src.claim ?? {};
|
||||
const userInfo = src.user_info ?? {};
|
||||
const propertyName = claim.propertyName ?? {};
|
||||
|
||||
// answers_parsed уже есть в claim; не мудрим — возвращаем как есть, пустоты -> null
|
||||
const answersParsed = claim.answers_parsed
|
||||
? Object.fromEntries(
|
||||
Object.entries(claim.answers_parsed).map(([k, v]) => [k, toNullish(v)])
|
||||
)
|
||||
: null;
|
||||
|
||||
// wizard план (часто нужен на фронте) — оставим ключевые поля
|
||||
let wizard = null;
|
||||
try {
|
||||
const parsed = typeof claim.wizard_plan === 'string'
|
||||
? JSON.parse(claim.wizard_plan)
|
||||
: (claim.wizard_plan_parsed ?? null);
|
||||
if (parsed) {
|
||||
wizard = {
|
||||
version: toNullish(parsed.version),
|
||||
case_type: toNullish(parsed.case_type),
|
||||
goals: Array.isArray(parsed.goals) ? parsed.goals : null,
|
||||
documents: Array.isArray(parsed.documents) ? parsed.documents : null,
|
||||
questions: Array.isArray(parsed.questions) ? parsed.questions : null,
|
||||
risks: Array.isArray(parsed.risks) ? parsed.risks : null,
|
||||
deadlines: Array.isArray(parsed.deadlines) ? parsed.deadlines : null,
|
||||
ask_order: Array.isArray(parsed.ask_order) ? parsed.ask_order : null,
|
||||
notes: toNullish(parsed.notes),
|
||||
user_text: toNullish(parsed.user_text),
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
wizard = null;
|
||||
}
|
||||
|
||||
// Склеиваем user — берём user_info, плюс propertyName на всякий, и то, что лежит в диалогах
|
||||
const user = {
|
||||
channel: toNullish(userInfo.channel ?? propertyName.channel),
|
||||
user_id: toNullish(userInfo.user_id ?? propertyName.user_id),
|
||||
unified_id: toNullish(userInfo.unified_id ?? propertyName.unified_id),
|
||||
telegram_id: toNullish(userInfo.telegram_id ?? propertyName.telegram_id ?? claim.telegram_id),
|
||||
session_token: toNullish(userInfo.session_token ?? propertyName.session_token ?? claim.session_token),
|
||||
};
|
||||
|
||||
// Собираем
|
||||
const out = {
|
||||
case: {
|
||||
id: toNullish(pick(claim, 'id')),
|
||||
prefix: toNullish(pick(claim, 'prefix')),
|
||||
channel: toNullish(pick(claim, 'channel')),
|
||||
type_code: toNullish(pick(claim, 'type_code')),
|
||||
status_code: toNullish(pick(claim, 'status_code')),
|
||||
created_at: toNullish(pick(claim, 'created_at')),
|
||||
updated_at: toNullish(pick(claim, 'updated_at')),
|
||||
telegram_id: toNullish(pick(claim, 'telegram_id')),
|
||||
session_token: toNullish(pick(claim, 'session_token')),
|
||||
unified_id: toNullish(pick(claim, 'unified_id')),
|
||||
case_type: toNullish(pick(claim, 'case_type')),
|
||||
},
|
||||
|
||||
user, // см. выше
|
||||
|
||||
answers: answersParsed,
|
||||
|
||||
// что загрузили
|
||||
documents: mapDocuments(src.documents),
|
||||
|
||||
// OCR/Vision/Combined, если есть
|
||||
vision_docs: mapVisionDocs(src.vision_docs),
|
||||
combined_docs: mapCombinedDocs(src.combined_docs),
|
||||
|
||||
// что там в "coverage_report" (кто что заполнил/не заполнил в мастере)
|
||||
coverage_report: mapCoverageReport(pick(claim, 'coverage_report')),
|
||||
|
||||
// история чата (ID, роли, тексты)
|
||||
dialog_history: mapDialogHistory(src.dialog_history),
|
||||
|
||||
// на всякий — куда и что складывали на S3 в момент сохранения
|
||||
s3_manifest: {
|
||||
session_token: toNullish(pick(claim, 'session_token')),
|
||||
documents_meta: Array.isArray(claim.documents_meta) ? claim.documents_meta : null,
|
||||
},
|
||||
|
||||
// флаги/риски, что засетили при сохранении
|
||||
risks: Array.isArray(claim.risks) ? claim.risks : null,
|
||||
|
||||
// план (wizard), как есть — пригодится фронту и валидаторам
|
||||
wizard_plan: wizard,
|
||||
};
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// === entrypoint ===
|
||||
const raw = items[0]?.json ?? {};
|
||||
const arr = Array.isArray(raw) ? raw : [raw];
|
||||
|
||||
// опциональный фильтр по claim_id, если в item передадут { claim_id: "..." }
|
||||
const claimIdFilter = items[0]?.json?.claim_id || items[0]?.json?.claimId || null;
|
||||
|
||||
// Прогоняем всё, отдаём по одному Item на кейс
|
||||
const results = arr
|
||||
.map(normalizeOne)
|
||||
.filter(obj => (claimIdFilter ? obj.case.id === claimIdFilter : true))
|
||||
.map(obj => ({ json: obj }));
|
||||
|
||||
return results.length ? results : [{ json: null }];
|
||||
|
||||
Reference in New Issue
Block a user