- Consultations: list from DraftsContext, ticket-detail webhook, response card - Back button in bar on consultations and in support chat (miniapp:goBack) - BottomBar: back enabled on /support; Support: goBack subscription - n8n: CRM normalize (n8n_CODE_CRM_NORMALIZE), flatten data (n8n_CODE_FLATTEN_DATA) - Dashboard: filter by category for CRM items, draft card width - Backend: consultations.py, ticket-detail, n8n_ticket_form_podrobnee_webhook - CHANGELOG_MINIAPP.md: section 2026-02-25
72 lines
2.7 KiB
JavaScript
72 lines
2.7 KiB
JavaScript
/**
|
||
* n8n Code node: нормализация ответа CRM (projects_json + tickets_json)
|
||
* в массив элементов с метками для фронта (type_code, payload.source, status_code по projectstatus).
|
||
*
|
||
* Вход: один элемент с полями projects_json[], tickets_json[] (и опционально contactid, unified_id, mobile).
|
||
* Выход: один элемент { crm_items: [...] } — массив готовых объектов для склейки с черновиками из Postgres.
|
||
*/
|
||
|
||
const input = $input.first().json;
|
||
const projects = input.projects_json || [];
|
||
const tickets = input.tickets_json || [];
|
||
|
||
const normalized = [];
|
||
|
||
// Проекты из CRM → один элемент на проект (карточка «В работе» / «Решены» / «Отклонены»)
|
||
for (const p of projects) {
|
||
const projectstatus = (p.projectstatus || '').toString().toLowerCase();
|
||
let status_code = 'active';
|
||
if (projectstatus.includes('завершено') || projectstatus === 'completed') status_code = 'completed';
|
||
else if (projectstatus.includes('отклонен')) status_code = 'rejected';
|
||
|
||
normalized.push({
|
||
id: `crm_project_${p.projectid}`,
|
||
claim_id: null,
|
||
type_code: 'external_case',
|
||
payload: {
|
||
source: 'CRM',
|
||
projectid: p.projectid,
|
||
projectstatus: p.projectstatus,
|
||
},
|
||
status_code,
|
||
channel: 'crm',
|
||
problem_title: p.projectname || '',
|
||
problem_description: '',
|
||
created_at: p.createdtime || null,
|
||
updated_at: p.createdtime || null,
|
||
documents_total: 0,
|
||
documents_uploaded: 0,
|
||
unified_id: input.unified_id || null,
|
||
contact_id: input.contactid != null ? String(input.contactid) : null,
|
||
phone: input.mobile || input.phone || null,
|
||
});
|
||
}
|
||
|
||
// Тикеты из CRM → один элемент на тикет (карточка «Консультации»)
|
||
for (const t of tickets) {
|
||
normalized.push({
|
||
id: `crm_ticket_${t.ticketid}`,
|
||
claim_id: null,
|
||
type_code: 'consultation',
|
||
payload: {
|
||
source: 'CRM',
|
||
ticketid: t.ticketid,
|
||
ticket_no: t.ticket_no,
|
||
},
|
||
status_code: 'active',
|
||
channel: 'crm',
|
||
problem_title: t.title || t.ticket_no || '',
|
||
problem_description: '',
|
||
created_at: t.createdtime || null,
|
||
updated_at: t.createdtime || null,
|
||
documents_total: 0,
|
||
documents_uploaded: 0,
|
||
unified_id: input.unified_id || null,
|
||
contact_id: input.contactid != null ? String(input.contactid) : null,
|
||
phone: input.mobile || input.phone || null,
|
||
});
|
||
}
|
||
|
||
// Отдаём один элемент с массивом crm_items (далее в workflow склеиваешь с data из Postgres)
|
||
return [{ json: { crm_items: normalized } }];
|