fixed bug with duplicate in script
This commit is contained in:
parent
7b811fb607
commit
34171eaa3c
|
|
@ -246,94 +246,94 @@ frappe.require([
|
||||||
|
|
||||||
// Добавляем функцию для обработки и выполнения формул
|
// Добавляем функцию для обработки и выполнения формул
|
||||||
functions.push(`
|
functions.push(`
|
||||||
// Функция для обработки и выполнения формул
|
// Функция для обработки и выполнения формул
|
||||||
async function processFormula(frm, formula) {
|
async function processFormula(frm, formula) {
|
||||||
try {
|
try {
|
||||||
// Проверяем наличие вызовов отчетов
|
// Проверяем наличие вызовов отчетов
|
||||||
if (formula.includes("report(")) {
|
if (formula.includes("report(")) {
|
||||||
// Извлекаем все вызовы report() из формулы
|
// Извлекаем все вызовы report() из формулы
|
||||||
const reportRegex = /report\\(([^)]+)\\)/g;
|
const reportRegex = /report\\(([^)]+)\\)/g;
|
||||||
let match;
|
let match;
|
||||||
let processedFormula = formula;
|
let processedFormula = formula;
|
||||||
|
|
||||||
// Массив для хранения промисов запросов к отчетам
|
// Массив для хранения промисов запросов к отчетам
|
||||||
const reportPromises = [];
|
const reportPromises = [];
|
||||||
const reportPlaceholders = [];
|
const reportPlaceholders = [];
|
||||||
|
|
||||||
// Находим все вызовы report() и заменяем их на плейсхолдеры
|
// Находим все вызовы report() и заменяем их на плейсхолдеры
|
||||||
while ((match = reportRegex.exec(formula)) !== null) {
|
while ((match = reportRegex.exec(formula)) !== null) {
|
||||||
const fullMatch = match[0]; // report(fieldName)
|
const fullMatch = match[0]; // report(fieldName)
|
||||||
const fieldName = match[1]; // fieldName
|
const fieldName = match[1]; // fieldName
|
||||||
|
|
||||||
// Создаем уникальный плейсхолдер
|
// Создаем уникальный плейсхолдер
|
||||||
const placeholder = \`__REPORT_PLACEHOLDER_\${reportPromises.length}__\`;
|
const placeholder = \`__REPORT_PLACEHOLDER_\${reportPromises.length}__\`;
|
||||||
|
|
||||||
// Ищем данные отчета в хранилище
|
// Ищем данные отчета в хранилище
|
||||||
const reportFields = JSON.parse(frm.doc.report_fields_storage || "{}");
|
const reportFields = JSON.parse(frm.doc.report_fields_storage || "{}");
|
||||||
const reportField = Object.values(reportFields).find(f => f.name === fieldName);
|
const reportField = Object.values(reportFields).find(f => f.name === fieldName);
|
||||||
|
|
||||||
if (reportField) {
|
if (reportField) {
|
||||||
// Добавляем промис запроса к отчету
|
// Добавляем промис запроса к отчету
|
||||||
reportPromises.push(
|
reportPromises.push(
|
||||||
getReportFieldValue(
|
getReportFieldValue(
|
||||||
frm,
|
frm,
|
||||||
reportField.report,
|
reportField.report,
|
||||||
JSON.parse(reportField.filters_json || "{}"),
|
JSON.parse(reportField.filters_json || "{}"),
|
||||||
reportField.field_name,
|
reportField.field_name,
|
||||||
reportField.aggregation || 'sum'
|
reportField.aggregation || 'sum'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Запоминаем соответствие плейсхолдера и вызова
|
// Запоминаем соответствие плейсхолдера и вызова
|
||||||
reportPlaceholders.push({
|
reportPlaceholders.push({
|
||||||
placeholder: placeholder,
|
placeholder: placeholder,
|
||||||
original: fullMatch
|
original: fullMatch
|
||||||
});
|
});
|
||||||
|
|
||||||
// Заменяем вызов отчета на плейсхолдер
|
// Заменяем вызов отчета на плейсхолдер
|
||||||
processedFormula = processedFormula.replace(fullMatch, placeholder);
|
processedFormula = processedFormula.replace(fullMatch, placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если нашли вызовы отчетов, ждем выполнения всех запросов
|
||||||
|
if (reportPromises.length > 0) {
|
||||||
|
const reportResults = await Promise.all(reportPromises);
|
||||||
|
|
||||||
|
// Заменяем плейсхолдеры на результаты
|
||||||
|
for (let i = 0; i < reportPlaceholders.length; i++) {
|
||||||
|
// Убедимся, что результат - числовое значение
|
||||||
|
const reportValue = reportResults[i] !== undefined ? Number(reportResults[i]) : 0;
|
||||||
|
processedFormula = processedFormula.replace(
|
||||||
|
reportPlaceholders[i].placeholder,
|
||||||
|
reportValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Теперь формула не содержит вызовов report(), обрабатываем её обычным способом
|
||||||
|
let transformResult = transform_expression(processedFormula, false);
|
||||||
|
|
||||||
|
// Если есть внешняя трансформация, применяем её
|
||||||
|
let result;
|
||||||
|
if (transformResult && transformResult.transformed) {
|
||||||
|
result = eval(transformResult.transformed);
|
||||||
|
} else {
|
||||||
|
// Иначе просто вычисляем выражение
|
||||||
|
result = eval(processedFormula);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возвращаем результат
|
||||||
|
return isNaN(result) ? 0 : result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Если нашли вызовы отчетов, ждем выполнения всех запросов
|
// Стандартная обработка для формул без отчетов
|
||||||
if (reportPromises.length > 0) {
|
let transformResult = transform_expression(formula, false);
|
||||||
const reportResults = await Promise.all(reportPromises);
|
let result = eval(transformResult.transformed);
|
||||||
|
return isNaN(result) ? 0 : result;
|
||||||
// Заменяем плейсхолдеры на результаты
|
} catch (e) {
|
||||||
for (let i = 0; i < reportPlaceholders.length; i++) {
|
return 0;
|
||||||
// Убедимся, что результат - числовое значение
|
|
||||||
const reportValue = reportResults[i] !== undefined ? Number(reportResults[i]) : 0;
|
|
||||||
processedFormula = processedFormula.replace(
|
|
||||||
reportPlaceholders[i].placeholder,
|
|
||||||
reportValue
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Теперь формула не содержит вызовов report(), обрабатываем её обычным способом
|
|
||||||
let transformResult = transform_expression(processedFormula, false);
|
|
||||||
|
|
||||||
// Если есть внешняя трансформация, применяем её
|
|
||||||
let result;
|
|
||||||
if (transformResult && transformResult.transformed) {
|
|
||||||
result = eval(transformResult.transformed);
|
|
||||||
} else {
|
|
||||||
// Иначе просто вычисляем выражение
|
|
||||||
result = eval(processedFormula);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Возвращаем результат
|
|
||||||
return isNaN(result) ? 0 : result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}`);
|
||||||
// Стандартная обработка для формул без отчетов
|
|
||||||
let transformResult = transform_expression(formula, false);
|
|
||||||
let result = eval(transformResult.transformed);
|
|
||||||
return isNaN(result) ? 0 : result;
|
|
||||||
} catch (e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}`);
|
|
||||||
|
|
||||||
// Добавляем функцию для расчета универсальных полей
|
// Добавляем функцию для расчета универсальных полей
|
||||||
functions.push(generateUniversalFieldsFunction(universal_fields));
|
functions.push(generateUniversalFieldsFunction(universal_fields));
|
||||||
|
|
@ -343,16 +343,8 @@ frappe.require([
|
||||||
functions.push(generateReportFieldsFunction(report_fields));
|
functions.push(generateReportFieldsFunction(report_fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Добавляем обработчики для ay и il - для расчета универсальных полей
|
// НЕ добавляем обработчики для ay и il здесь отдельно
|
||||||
triggerHandlers["ay"] = {
|
// Они будут добавлены позже вместе с другими обработчиками
|
||||||
isAsync: true,
|
|
||||||
handlers: ["// Вычисляем универсальные поля только когда меняется ay", "await calculate_universal_fields(frm);"]
|
|
||||||
};
|
|
||||||
|
|
||||||
triggerHandlers["il"] = {
|
|
||||||
isAsync: true,
|
|
||||||
handlers: ["// Вычисляем универсальные поля только когда меняется il", "await calculate_universal_fields(frm);"]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Добавляем функцию преобразования выражений
|
// Добавляем функцию преобразования выражений
|
||||||
functions.push(generateTransformExpressionFunction(universal_fields, report_fields));
|
functions.push(generateTransformExpressionFunction(universal_fields, report_fields));
|
||||||
|
|
@ -440,39 +432,39 @@ frappe.require([
|
||||||
} else {
|
} else {
|
||||||
// Используем единый подход для всех формул через transform_expression
|
// Используем единый подход для всех формул через transform_expression
|
||||||
functions.push(`
|
functions.push(`
|
||||||
async function calculate_${fieldname}(frm) {
|
async function calculate_${fieldname}(frm) {
|
||||||
try {
|
try {
|
||||||
${formula.includes("univ(") ? 'await calculate_universal_fields(frm);' : ''}
|
${formula.includes("univ(") ? 'await calculate_universal_fields(frm);' : ''}
|
||||||
const { transformed, needsAsync, reportCalls } = transform_expression(${JSON.stringify(formula)}, false);
|
const { transformed, needsAsync, reportCalls } = transform_expression(${JSON.stringify(formula)}, false);
|
||||||
|
|
||||||
// Обработка вызовов отчетов, если они есть
|
// Обработка вызовов отчетов, если они есть
|
||||||
let finalExpression = transformed;
|
let finalExpression = transformed;
|
||||||
if (reportCalls && reportCalls.length > 0) {
|
if (reportCalls && reportCalls.length > 0) {
|
||||||
// Собираем все результаты отчетов
|
// Собираем все результаты отчетов
|
||||||
const reportResults = [];
|
const reportResults = [];
|
||||||
for (const call of reportCalls) {
|
for (const call of reportCalls) {
|
||||||
const result = await getReportFieldValue(
|
const result = await getReportFieldValue(
|
||||||
frm,
|
frm,
|
||||||
call.reportName,
|
call.reportName,
|
||||||
call.filters,
|
call.filters,
|
||||||
call.fieldName,
|
call.fieldName,
|
||||||
call.aggregation
|
call.aggregation
|
||||||
);
|
);
|
||||||
reportResults.push({ placeholder: call.placeholder, value: result });
|
reportResults.push({ placeholder: call.placeholder, value: result });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Заменяем плейсхолдеры на полученные значения
|
||||||
|
for (const result of reportResults) {
|
||||||
|
finalExpression = finalExpression.replace(result.placeholder, result.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Заменяем плейсхолдеры на полученные значения
|
// Теперь можно безопасно вычислить выражение
|
||||||
for (const result of reportResults) {
|
const result = eval(finalExpression);
|
||||||
finalExpression = finalExpression.replace(result.placeholder, result.value);
|
frm.set_value("${fieldname}", isNaN(result) ? 0 : result);
|
||||||
}
|
} catch (e) {
|
||||||
}
|
}
|
||||||
|
}`);
|
||||||
// Теперь можно безопасно вычислить выражение
|
|
||||||
const result = eval(finalExpression);
|
|
||||||
frm.set_value("${fieldname}", isNaN(result) ? 0 : result);
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
}`);
|
|
||||||
|
|
||||||
// Проверяем триггеры
|
// Проверяем триггеры
|
||||||
if (field_info.triggers) {
|
if (field_info.triggers) {
|
||||||
|
|
@ -577,23 +569,76 @@ frappe.require([
|
||||||
'frappe.ui.form.on("' + target_doctype + '", {\n' + refreshHandlerBody);
|
'frappe.ui.form.on("' + target_doctype + '", {\n' + refreshHandlerBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Теперь создаем обработчики для каждого триггера
|
|
||||||
Object.keys(triggerHandlers).forEach(trigger => {
|
|
||||||
const handler = triggerHandlers[trigger];
|
|
||||||
main_script += ` "${trigger}": ${handler.isAsync ? 'async ' : ''}function(frm) {
|
|
||||||
${handler.handlers.join('\n ')}
|
|
||||||
},\n`;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Обработчики для табличных частей и триггеры, связанные с ними
|
// Обработчики для табличных частей и триггеры, связанные с ними
|
||||||
const tableRowFormulaHandlers = processTableRowFormulas(table_row_formulas, table_doctypes);
|
const tableRowFormulaHandlers = processTableRowFormulas(table_row_formulas, table_doctypes);
|
||||||
|
|
||||||
|
// ВАЖНО: Объединяем обработчики формул строк таблиц с основными обработчиками
|
||||||
Object.keys(tableRowFormulaHandlers).forEach(trigger => {
|
Object.keys(tableRowFormulaHandlers).forEach(trigger => {
|
||||||
const handler = tableRowFormulaHandlers[trigger];
|
const handler = tableRowFormulaHandlers[trigger];
|
||||||
main_script += ` "${trigger}": ${handler.isAsync ? 'async ' : ''}function(frm) {
|
|
||||||
${handler.isAsync ? 'await calculate_universal_fields(frm);' : '// Универсальные поля не используются'}
|
|
||||||
|
|
||||||
${handler.handlers.join('\n ')}
|
// Проверяем, есть ли уже обработчик для этого триггера
|
||||||
},\n`;
|
if (triggerHandlers[trigger]) {
|
||||||
|
// Объединяем обработчики
|
||||||
|
// Если хотя бы один требует async, делаем весь обработчик async
|
||||||
|
if (handler.isAsync) {
|
||||||
|
triggerHandlers[trigger].isAsync = true;
|
||||||
|
}
|
||||||
|
// Добавляем новые обработчики к существующим
|
||||||
|
triggerHandlers[trigger].handlers = triggerHandlers[trigger].handlers.concat(handler.handlers);
|
||||||
|
} else {
|
||||||
|
// Если обработчика еще нет, создаем новый
|
||||||
|
triggerHandlers[trigger] = handler;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Проверяем, нужны ли обработчики для ay и il для универсальных полей и основных формул
|
||||||
|
const needsAyIlHandlers = fieldsUsingUniversalOrReports.some(f => f.uses_universal) ||
|
||||||
|
Object.keys(table_row_formulas).some(id => {
|
||||||
|
const formula = table_row_formulas[id];
|
||||||
|
return formula.formula && formula.formula.includes("univ(");
|
||||||
|
});
|
||||||
|
|
||||||
|
if (needsAyIlHandlers) {
|
||||||
|
// Добавляем или обновляем обработчики для ay и il
|
||||||
|
['ay', 'il'].forEach(field => {
|
||||||
|
if (!triggerHandlers[field]) {
|
||||||
|
triggerHandlers[field] = {
|
||||||
|
isAsync: true,
|
||||||
|
handlers: []
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
triggerHandlers[field].isAsync = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавляем вызов calculate_universal_fields в начало обработчика
|
||||||
|
const hasUniversalCall = triggerHandlers[field].handlers.some(h =>
|
||||||
|
h.includes('calculate_universal_fields')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!hasUniversalCall) {
|
||||||
|
triggerHandlers[field].handlers.unshift('await calculate_universal_fields(frm);');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Теперь создаем обработчики для каждого триггера (без дубликатов)
|
||||||
|
Object.keys(triggerHandlers).forEach(trigger => {
|
||||||
|
const handler = triggerHandlers[trigger];
|
||||||
|
main_script += ` "${trigger}": ${handler.isAsync ? 'async ' : ''}function(frm) {\n`;
|
||||||
|
|
||||||
|
// Для ay и il добавляем комментарий о вычислении универсальных полей
|
||||||
|
if (trigger === 'ay' || trigger === 'il') {
|
||||||
|
if (handler.handlers.some(h => h.includes('calculate_universal_fields'))) {
|
||||||
|
main_script += ` // Вычисляем универсальные поля только когда меняется ${trigger}\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавляем все обработчики
|
||||||
|
handler.handlers.forEach(handlerCode => {
|
||||||
|
main_script += ` ${handlerCode}\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
main_script += ' },\n';
|
||||||
});
|
});
|
||||||
|
|
||||||
main_script += `});`;
|
main_script += `});`;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue