export function setNewValueToData(data, colId, rowId, value) { let targetObject = data; if (rowId && rowId.length) { const indices = rowId.split(".").map(Number); for (let i = 0; i < indices.length; i++) { const index = indices[i]; if (targetObject && targetObject[index] !== undefined) { targetObject = targetObject[index]; } else { console.error(`Индекс ${index} не найден на уровне ${i}`); return false; } // Если это не последний индекс, переходим в subRows if (i < indices.length - 1) { if (targetObject.subRows && Array.isArray(targetObject.subRows)) { targetObject = targetObject.subRows; } else { console.error(`Нет subRows для перехода на уровне ${i}`); return false; } } } } const keys = colId.split("."); const lastKey = keys.pop(); // Идем по вложенности path let current = targetObject; for (let i = 0; i < keys.length; i++) { const key = keys[i]; if (!current[key]) { current[key] = {}; } current = current[key]; } current[lastKey] = value; return true; } export function updateCells(data, newRows) { const updatedRows = structuredClone(data); function deepMerge(target, source) { if (!source || typeof source !== "object") { return source; } if (!target || typeof target !== "object") { target = {}; } Object.keys(source).forEach((key) => { if ( source[key] && typeof source[key] === "object" && !Array.isArray(source[key]) ) { target[key] = deepMerge(target[key], source[key]); } else { target[key] = source[key]; } }); return target; } newRows.forEach((update) => { const [rowType, depth, sortOrder, newData] = update; // Рекурсивная функция для поиска и обновления строки function findAndUpdate(rows) { for (let i = 0; i < rows.length; i++) { const row = rows[i]; if ( row.row_type === rowType && row.depth === depth && row.sort_order === sortOrder ) { if (newData && typeof newData === "object") { Object.keys(newData).forEach((key) => { if (row.data && row.data[key]) { if (typeof row.data[key] === "object") { row.data[key] = deepMerge(row.data[key], newData[key]); } else { row.data[key] = newData[key]; } } else if (row[key]) { row[key] = newData[key]; } }); } return true; } if ( row.subRows && Array.isArray(row.subRows) && row.subRows.length > 0 ) { const found = findAndUpdate(row.subRows); if (found) return true; } } return false; } findAndUpdate(updatedRows); }); return updatedRows; } export function insertCell(data, newRow, expense_item_id) { const updatedRows = JSON.parse(JSON.stringify(data)); const [row_type, depth, sort_order, dataRow] = newRow; const newRowObject = { row_type: row_type, depth: depth, sort_order: sort_order, subRows: [], data: dataRow, }; // Если expense_item_id === null, добавляем в конец if (expense_item_id === null) { updatedRows.push(newRowObject); return updatedRows; } let adding = false; function findAndUpdate(rows) { for (let i = 0; i < rows.length; i++) { const row = rows[i]; if ( (row.sort_order >= newRowObject.sort_order) & (row.data.line_id != newRowObject.data.line_id) ) { row.sort_order = row.sort_order + 1; } if (!adding & (row.data.header.expense_item_id === expense_item_id)) { if (!("subRows" in row)) { row.subRows = []; } row.subRows.push(newRowObject); adding = true; } if (row.subRows && Array.isArray(row.subRows) && row.subRows.length > 0) { const found = findAndUpdate(row.subRows); } } } findAndUpdate(updatedRows); return updatedRows; } export function deleteRow(data, lineId) { const updatedRows = JSON.parse(JSON.stringify(data)); let rowDeleteSortOrder = false; function findAndDelete(rows) { for (let i = 0; i < rows.length; i++) { const row = rows[i]; if (row.data.line_id == lineId) { rowDeleteSortOrder = row.sort_order; rows.splice(i, 1); i--; } if ((rowDeleteSortOrder > 0) & (row.sort_order >= rowDeleteSortOrder)) { row.sort_order = row.sort_order - 1; } if (row.subRows && Array.isArray(row.subRows) && row.subRows.length > 0) { const found = findAndDelete(row.subRows); } } } findAndDelete(updatedRows); return updatedRows; }