Added order in row formulas

This commit is contained in:
Away 2025-04-22 20:29:23 +00:00
parent 022c809acc
commit 1699e76dcc
1 changed files with 109 additions and 62 deletions

View File

@ -5598,18 +5598,22 @@ function createTableRowFormulaModal() {
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-4"> <div class="col-md-3">
<label for="table_row_table">Табличная часть:</label> <label for="table_row_table">Табличная часть:</label>
<select id="table_row_table" class="form-control"></select> <select id="table_row_table" class="form-control"></select>
</div> </div>
<div class="col-md-4"> <div class="col-md-3">
<label for="table_row_field">Поле:</label> <label for="table_row_field">Поле:</label>
<select id="table_row_field" class="form-control" disabled></select> <select id="table_row_field" class="form-control" disabled></select>
</div> </div>
<div class="col-md-4"> <div class="col-md-3">
<label for="table_row_index">Номер строки:</label> <label for="table_row_index">Номер строки:</label>
<input type="number" id="table_row_index" class="form-control" min="1" value="1"> <input type="number" id="table_row_index" class="form-control" min="1" value="1">
</div> </div>
<div class="col-md-3">
<label for="table_row_order">Порядок выполнения:</label>
<input type="number" id="table_row_order" class="form-control" min="0" value="10">
</div>
</div> </div>
<div class="formula-workspace"> <div class="formula-workspace">
<div class="formula-result-container"> <div class="formula-result-container">
@ -5660,11 +5664,11 @@ function createTableRowFormulaModal() {
$('body').append(modalHtml); $('body').append(modalHtml);
// Добавляем обработчики для селектов // Обработчики для селекторов
$("#table_row_table").on('change', function() { $("#table_row_table").on('change', function() {
const selectedTable = $(this).val(); const selectedTable = $(this).val();
if (selectedTable) { if (selectedTable) {
loadTableFields(selectedTable); loadTableFieldsForSelector(selectedTable);
$("#table_row_field").prop('disabled', false); $("#table_row_field").prop('disabled', false);
} else { } else {
$("#table_row_field").prop('disabled', true).empty().append('<option value="">Выберите поле</option>'); $("#table_row_field").prop('disabled', true).empty().append('<option value="">Выберите поле</option>');
@ -5791,6 +5795,9 @@ function openTableRowFormulaModal(frm, formulaId = null) {
$("#table_row_field").val(formula.field_name); $("#table_row_field").val(formula.field_name);
$("#table_row_index").val(formula.row_index); $("#table_row_index").val(formula.row_index);
// Загружаем порядок выполнения (если существует, иначе значение по умолчанию 10)
$("#table_row_order").val(formula.order || 10);
// Заполняем формулу и триггеры // Заполняем формулу и триггеры
parseAndRenderFormula($resultContainer, formula.formula, true); parseAndRenderFormula($resultContainer, formula.formula, true);
parseAndRenderTriggers($triggerContainer, formula.triggers); parseAndRenderTriggers($triggerContainer, formula.triggers);
@ -5839,7 +5846,7 @@ function openTableRowFormulaModal(frm, formulaId = null) {
const formula = getFormulaText($resultContainer); const formula = getFormulaText($resultContainer);
const triggers = getTriggerFieldsText($triggerContainer); const triggers = getTriggerFieldsText($triggerContainer);
// Сохраняем формулу // Сохраняем формулу со всеми необходимыми данными, включая порядок
saveTableRowFormula(frm, { saveTableRowFormula(frm, {
table_name: tableName, table_name: tableName,
field_name: fieldName, field_name: fieldName,
@ -5850,7 +5857,7 @@ function openTableRowFormulaModal(frm, formulaId = null) {
$modal.modal('hide'); $modal.modal('hide');
}); });
// Обработчик для кнопки "При открытии документа" // Обработчик для кнопки "При открытии документа"
$modal.find('.add-predefined-event').off('click').on('click', function() { $modal.find('.add-predefined-event').off('click').on('click', function() {
addTokenToTriggers("При открытии документа", $triggerContainer, 'event'); addTokenToTriggers("При открытии документа", $triggerContainer, 'event');
@ -6341,7 +6348,13 @@ function saveTableRowFormula(frm, formulaData, formulaId = null) {
try { try {
let tableRowFormulas = JSON.parse(frm.doc.table_row_formulas_storage || "{}"); let tableRowFormulas = JSON.parse(frm.doc.table_row_formulas_storage || "{}");
// Сохраняем формулу // Получаем значение порядка из интерфейса
const order = parseInt($("#table_row_order").val()) || 10;
// Добавляем порядок в данные формулы
formulaData.order = order;
// Сохраняем новую или обновленную формулу
tableRowFormulas[newFormulaId] = formulaData; tableRowFormulas[newFormulaId] = formulaData;
// Обновляем значение в форме // Обновляем значение в форме
@ -6383,6 +6396,7 @@ function renderTableRowFormulas(frm) {
<th>Табличная часть</th> <th>Табличная часть</th>
<th>Поле</th> <th>Поле</th>
<th>Строка</th> <th>Строка</th>
<th>Порядок</th>
<th>Формула</th> <th>Формула</th>
<th>Обновлять при изменении</th> <th>Обновлять при изменении</th>
<th>Действия</th> <th>Действия</th>
@ -6403,6 +6417,7 @@ function renderTableRowFormulas(frm) {
<td>${formula.table_name}</td> <td>${formula.table_name}</td>
<td>${formula.field_name}</td> <td>${formula.field_name}</td>
<td>${formula.row_index}</td> <td>${formula.row_index}</td>
<td>${formula.order || 10}</td>
<td>${formula.formula}</td> <td>${formula.formula}</td>
<td>${formula.triggers || '-'}</td> <td>${formula.triggers || '-'}</td>
<td> <td>
@ -6874,64 +6889,79 @@ function generateTableRowFormulasHandlers(table_row_formulas, functions, target_
let initFunction = ` let initFunction = `
// Функция для инициализации формул строк табличных частей // Функция для инициализации формул строк табличных частей
function initialize_table_row_formulas(frm) { function initialize_table_row_formulas(frm) {
try {
// Получаем информацию о формулах для строк табличных частей // Получаем информацию о формулах для строк табличных частей
const formulas = JSON.parse(frm.doc.table_row_formulas_storage || "{}"); const formulas = JSON.parse(frm.doc.table_row_formulas_storage || "{}");
// Группируем формулы по табличным частям
const formulasByTable = {};
Object.keys(formulas).forEach(formulaId => {
const formula = formulas[formulaId];
const tableName = formula.table_name;
if (!formulasByTable[tableName]) { // ВАЖНО: Преобразуем объект в массив и сортируем его по порядку выполнения
formulasByTable[tableName] = []; const sortedFormulas = Object.entries(formulas).map(([id, formula]) => {
} return { id, ...formula };
}).sort((a, b) => {
// Сортировка по значению поля order (если порядок не задан, используем 10 по умолчанию)
const orderA = a.order !== undefined ? parseInt(a.order) : 10;
const orderB = b.order !== undefined ? parseInt(b.order) : 10;
return orderA - orderB;
});
formulasByTable[tableName].push(formula); // Группируем формулы по табличным частям и строкам
}); const formulasByTableAndRow = {};
// Устанавливаем обработчики для каждой табличной части
Object.keys(formulasByTable).forEach(tableName => {
if (!frm.doc[tableName]) {
return;
}
rowFormulas.forEach(async formula => { sortedFormulas.forEach(formula => {
try { const tableName = formula.table_name;
// Проверяем, нужен ли асинхронный вызов const rowIndex = parseInt(formula.row_index);
const usesUniversal = formula.formula && formula.formula.includes("univ(");
const usesReports = formula.formula && formula.formula.includes("report(");
// Всегда используем явный вызов calculate_table_row_field
await calculate_table_row_field(frm, tableName, rowIndex, formula.field_name, formula.formula, "refresh");
} catch (error) {
}
});
// Вычисляем формулы для строки только если у них есть триггер "При открытии документа" if (!formulasByTableAndRow[tableName]) {
rowFormulas.forEach(formula => { formulasByTableAndRow[tableName] = {};
try { }
// Проверяем, нужен ли асинхронный вызов
const usesUniversal = formula.formula && formula.formula.includes("univ("); if (!formulasByTableAndRow[tableName][rowIndex]) {
const usesReports = formula.formula && formula.formula.includes("report("); formulasByTableAndRow[tableName][rowIndex] = [];
}
if (usesUniversal || usesReports) {
// Используем setTimeout для асинхронных вызовов, чтобы не блокировать процесс formulasByTableAndRow[tableName][rowIndex].push(formula);
setTimeout(async () => { });
try {
await calculate_table_row_field(frm, tableName, rowIndex, formula.field_name, formula.formula, "refresh"); // Устанавливаем обработчики для каждой табличной части
} catch (error) { Object.keys(formulasByTableAndRow).forEach(tableName => {
} if (!frm.doc[tableName]) {
}, 0); return;
} else { }
// Синхронный вызов для обычных формул
calculate_table_row_field(frm, tableName, rowIndex, formula.field_name, formula.formula, "refresh"); // Для каждой строки таблицы
frm.doc[tableName].forEach((row, rowIdx) => {
// Получаем отсортированные формулы для текущей строки (строки нумеруются с 1, а индексы с 0)
const rowFormulas = formulasByTableAndRow[tableName][rowIdx + 1] || [];
// Выполняем формулы в порядке сортировки (по полю order)
for (const formula of rowFormulas) {
try {
// Определяем необходимость асинхронного вызова
const usesUniversal = formula.formula && formula.formula.includes("univ(");
const usesReports = formula.formula && formula.formula.includes("report(");
// Вызываем расчет формулы согласно установленному порядку
if (usesUniversal || usesReports) {
// Для асинхронных вызовов используем await в асинхронной IIFE
(async () => {
try {
await calculate_table_row_field(frm, tableName, rowIdx, formula.field_name, formula.formula, "refresh");
} catch (asyncError) {
console.error("Ошибка при асинхронном расчете формулы (порядок " + (formula.order || 10) + "):", asyncError);
}
})();
} else {
// Для синхронных вызовов выполняем напрямую
calculate_table_row_field(frm, tableName, rowIdx, formula.field_name, formula.formula, "refresh");
}
} catch (error) {
console.error("Ошибка расчета формулы для " + tableName + "[" + rowIdx + "]." + formula.field_name + " (порядок " + (formula.order || 10) + "):", error);
} }
} catch (error) {
} }
}); });
}); });
} catch (error) {
console.error("Ошибка инициализации формул строк табличных частей:", error);
}
}`; }`;
functions.push(initFunction); functions.push(initFunction);
@ -9042,12 +9072,28 @@ function deleteReportField(frm, fieldId) {
); );
} }
// Обработка формул строк таблиц для генерации клиентского скрипта
function processTableRowFormulas(table_row_formulas, table_doctypes) { function processTableRowFormulas(table_row_formulas, table_doctypes) {
// Хранилище для объединенных обработчиков // Хранилище для объединенных обработчиков
const triggerHandlers = {}; const triggerHandlers = {};
// Проверяем, что объект table_row_formulas не пустой
if (!table_row_formulas || Object.keys(table_row_formulas).length === 0) {
return triggerHandlers;
}
// Получаем отсортированные формулы по порядку выполнения
const sortedFormulas = Object.entries(table_row_formulas).map(([id, formula]) => {
return { id, ...formula };
}).sort((a, b) => {
// Сортировка по значению поля order (если порядок не задан, используем 10 по умолчанию)
const orderA = a.order !== undefined ? parseInt(a.order) : 10;
const orderB = b.order !== undefined ? parseInt(b.order) : 10;
return orderA - orderB;
});
// Группируем формулы по триггерам // Группируем формулы по триггерам
Object.values(table_row_formulas).forEach(formula => { sortedFormulas.forEach(formula => {
const tableName = formula.table_name; const tableName = formula.table_name;
const rowIndex = parseInt(formula.row_index); const rowIndex = parseInt(formula.row_index);
const usesUniversal = formula.formula && formula.formula.includes("univ("); const usesUniversal = formula.formula && formula.formula.includes("univ(");
@ -9075,9 +9121,9 @@ function processTableRowFormulas(table_row_formulas, table_doctypes) {
triggerHandlers[trigger].isAsync = true; triggerHandlers[trigger].isAsync = true;
} }
// Код для вычисления формулы // Код для вычисления формулы, с учетом порядка выполнения
const handlerCode = ` const handlerCode = `
// Проверяем строку ${rowIndex} в таблице ${tableName} // Формула строки ${rowIndex} в таблице ${tableName} (порядок: ${formula.order || 10})
if (frm.doc.${tableName} && frm.doc.${tableName}.length >= ${rowIndex}) { if (frm.doc.${tableName} && frm.doc.${tableName}.length >= ${rowIndex}) {
try { try {
// Индекс строки на 1 меньше номера строки // Индекс строки на 1 меньше номера строки
@ -9086,6 +9132,7 @@ function processTableRowFormulas(table_row_formulas, table_doctypes) {
${usesUniversal || usesReports ? 'await ' : ''}calculate_table_row_field(frm, "${tableName}", rowIndex, "${formula.field_name}", formula, "${trigger}"); ${usesUniversal || usesReports ? 'await ' : ''}calculate_table_row_field(frm, "${tableName}", rowIndex, "${formula.field_name}", formula, "${trigger}");
} catch (error) { } catch (error) {
console.error("Ошибка вычисления формулы для ${tableName}[${rowIndex - 1}].${formula.field_name}:", error);
} }
}`; }`;
@ -9096,7 +9143,7 @@ function processTableRowFormulas(table_row_formulas, table_doctypes) {
// Добавляем обработчики для событий add_row и remove_row для каждой таблицы // Добавляем обработчики для событий add_row и remove_row для каждой таблицы
const tables = new Set(); const tables = new Set();
Object.values(table_row_formulas).forEach(formula => { sortedFormulas.forEach(formula => {
tables.add(formula.table_name); tables.add(formula.table_name);
}); });