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