Added order in row formulas
This commit is contained in:
parent
022c809acc
commit
1699e76dcc
|
|
@ -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,
|
||||||
|
|
@ -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 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 = {};
|
const formulasByTableAndRow = {};
|
||||||
Object.keys(formulas).forEach(formulaId => {
|
|
||||||
const formula = formulas[formulaId];
|
|
||||||
const tableName = formula.table_name;
|
|
||||||
|
|
||||||
if (!formulasByTable[tableName]) {
|
sortedFormulas.forEach(formula => {
|
||||||
formulasByTable[tableName] = [];
|
const tableName = formula.table_name;
|
||||||
}
|
const rowIndex = parseInt(formula.row_index);
|
||||||
|
|
||||||
formulasByTable[tableName].push(formula);
|
if (!formulasByTableAndRow[tableName]) {
|
||||||
});
|
formulasByTableAndRow[tableName] = {};
|
||||||
|
}
|
||||||
|
|
||||||
// Устанавливаем обработчики для каждой табличной части
|
if (!formulasByTableAndRow[tableName][rowIndex]) {
|
||||||
Object.keys(formulasByTable).forEach(tableName => {
|
formulasByTableAndRow[tableName][rowIndex] = [];
|
||||||
if (!frm.doc[tableName]) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rowFormulas.forEach(async formula => {
|
formulasByTableAndRow[tableName][rowIndex].push(formula);
|
||||||
try {
|
});
|
||||||
// Проверяем, нужен ли асинхронный вызов
|
|
||||||
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");
|
Object.keys(formulasByTableAndRow).forEach(tableName => {
|
||||||
} catch (error) {
|
if (!frm.doc[tableName]) {
|
||||||
}
|
return;
|
||||||
});
|
}
|
||||||
|
|
||||||
// Вычисляем формулы для строки только если у них есть триггер "При открытии документа"
|
// Для каждой строки таблицы
|
||||||
rowFormulas.forEach(formula => {
|
frm.doc[tableName].forEach((row, rowIdx) => {
|
||||||
try {
|
// Получаем отсортированные формулы для текущей строки (строки нумеруются с 1, а индексы с 0)
|
||||||
// Проверяем, нужен ли асинхронный вызов
|
const rowFormulas = formulasByTableAndRow[tableName][rowIdx + 1] || [];
|
||||||
const usesUniversal = formula.formula && formula.formula.includes("univ(");
|
|
||||||
const usesReports = formula.formula && formula.formula.includes("report(");
|
|
||||||
|
|
||||||
if (usesUniversal || usesReports) {
|
// Выполняем формулы в порядке сортировки (по полю order)
|
||||||
// Используем setTimeout для асинхронных вызовов, чтобы не блокировать процесс
|
for (const formula of rowFormulas) {
|
||||||
setTimeout(async () => {
|
try {
|
||||||
try {
|
// Определяем необходимость асинхронного вызова
|
||||||
await calculate_table_row_field(frm, tableName, rowIndex, formula.field_name, formula.formula, "refresh");
|
const usesUniversal = formula.formula && formula.formula.includes("univ(");
|
||||||
} catch (error) {
|
const usesReports = formula.formula && formula.formula.includes("report(");
|
||||||
}
|
|
||||||
}, 0);
|
// Вызываем расчет формулы согласно установленному порядку
|
||||||
} else {
|
if (usesUniversal || usesReports) {
|
||||||
// Синхронный вызов для обычных формул
|
// Для асинхронных вызовов используем await в асинхронной IIFE
|
||||||
calculate_table_row_field(frm, tableName, rowIndex, formula.field_name, formula.formula, "refresh");
|
(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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue