fixed a bunch of bugs

This commit is contained in:
Ali 2025-04-23 17:12:38 +04:00
parent 1699e76dcc
commit ed9e568d7d
1 changed files with 117 additions and 60 deletions

View File

@ -555,8 +555,6 @@ function generateReportFieldsFunction(report_fields) {
window.notifiedAboutRubIl = false; window.notifiedAboutRubIl = false;
async function getReportFieldValue(frm, reportName, filters, fieldName, aggregation = 'sum') { async function getReportFieldValue(frm, reportName, filters, fieldName, aggregation = 'sum') {
try { try {
// Отладочное сообщение о начальных фильтрах
console.log(\`Запуск отчета \${reportName} с начальными фильтрами:\`, JSON.stringify(filters));
// Проверка необходимости полей сразу для всех фильтров // Проверка необходимости полей сразу для всех фильтров
if (Object.values(filters).some(v => v === "$AyIlSpecial")) { if (Object.values(filters).some(v => v === "$AyIlSpecial")) {
@ -726,9 +724,6 @@ async function getReportFieldValue(frm, reportName, filters, fieldName, aggregat
processedFilters[key] = value; processedFilters[key] = value;
} }
// Отладочное сообщение об обработанных фильтрах
console.log(\`ОТЧЕТ API - запуск отчета \${reportName} с фильтрами\`, JSON.stringify(processedFilters));
// Проверяем кеш для экономии запросов // Проверяем кеш для экономии запросов
if (!window.reportCache) window.reportCache = {}; if (!window.reportCache) window.reportCache = {};
@ -756,16 +751,13 @@ async function getReportFieldValue(frm, reportName, filters, fieldName, aggregat
// Проверяем результат // Проверяем результат
if (result && result.message) { if (result && result.message) {
if (result.message.error) { if (result.message.error) {
console.log(\`Ошибка при получении данных отчета: \${result.message.error}\`);
return 0; return 0;
} }
// Получаем числовое значение // Получаем числовое значение
let value = parseFloat(result.message); let value = parseFloat(result.message);
if (isNaN(value)) value = 0; if (isNaN(value)) value = 0;
console.log(\`Результат отчета \${reportName}: \${value}\`);
// Сохраняем в кеш // Сохраняем в кеш
window.reportCache[cacheKey] = { window.reportCache[cacheKey] = {
value: value, value: value,
@ -775,12 +767,10 @@ async function getReportFieldValue(frm, reportName, filters, fieldName, aggregat
return value; return value;
} }
} catch (err) { } catch (err) {
console.error(\`Ошибка при вызове отчета \${reportName}:\`, err);
} }
return 0; return 0;
} catch (error) { } catch (error) {
console.error(\`Общая ошибка в getReportFieldValue:\`, error);
return 0; return 0;
} }
}`; }`;
@ -1262,7 +1252,7 @@ function generateTransformExpressionFunction(universal_fields, report_fields) {
let reportCalls = []; let reportCalls = [];
// === Обработка report(...) === // === Обработка report(...) ===
const reportRegex = /report\\(([^)]+)\\)/g;\n const reportRegex = /report\\\\(([^)]+)\\\\)/g;
let match; let match;
// Находим все вызовы report() в выражении // Находим все вызовы report() в выражении
@ -1340,38 +1330,35 @@ function generateTransformExpressionFunction(universal_fields, report_fields) {
${Object.keys(universal_fields).map(fieldId => { ${Object.keys(universal_fields).map(fieldId => {
const field = universal_fields[fieldId]; const field = universal_fields[fieldId];
if (!field || !field.name) return ''; if (!field || !field.name) return '';
return `transformed = transformed.replace(/univ\\(${field.name}\\)/g, "(frm.doc.__universalFields && frm.doc.__universalFields['${fieldId}'] || 0)");`; return `transformed = transformed.replace(/univ\\\\(${field.name}\\\\)/g, "(frm.doc.__universalFields && frm.doc.__universalFields['${fieldId}'] || 0)");`;
}).filter(Boolean).join('\n')} }).filter(Boolean).join('\n')}
// === Обработка val() и row() === // === Обработка val() и row() ===
const tablePrefixes = ${JSON.stringify([
"items", "taxes", "packed_items", "payments", "advances", "timesheets",
"payment_schedule", "sales_team", "aksiz_test_table"
])};
for (const prefix of tablePrefixes) { for (const prefix of tablePrefixes) {
const sumPattern = new RegExp(\`sum\\\\(\${prefix}_([^)]+)\\\\)\`, 'g'); const sumPattern = new RegExp(\`sum\\\\\\\\(\${prefix}_([^)]+)\\\\\\\\)\`, 'g');
transformed = transformed.replace(sumPattern, (m, f) => transformed = transformed.replace(sumPattern, (m, f) =>
\`(frm.doc["\${prefix}"] && frm.doc["\${prefix}"].reduce((s, r) => s + (parseFloat(r["\${f}"]) || 0), 0) || 0)\` \`(frm.doc["\${prefix}"] && frm.doc["\${prefix}"].reduce((s, r) => s + (parseFloat(r["\${f}"]) || 0), 0) || 0)\`
); );
const valPattern = new RegExp(\`val\\\\(\${prefix}_([^)]+)\\\\)\`, 'g'); const valPattern = new RegExp(\`val\\\\\\\\(\${prefix}_([^)]+)\\\\\\\\)\`, 'g');
transformed = transformed.replace(valPattern, (m, f) => transformed = transformed.replace(valPattern, (m, f) =>
\`(frm.doc["\${prefix}"] && frm.doc["\${prefix}"].reduce((s, r) => s + (parseFloat(r["\${f}"]) || 0), 0) || 0)\` \`(frm.doc["\${prefix}"] && frm.doc["\${prefix}"].reduce((s, r) => s + (parseFloat(r["\${f}"]) || 0), 0) || 0)\`
); );
} }
if (for_child_table) { if (for_child_table) {
// ИСПРАВЛЕНО: корректная обработка row() в контексте табличной части
transformed = transformed.replace(/row\\\\(([^)]+)\\\\)/g, (m, f) =>
\`(parseFloat(row["\${f}"]) || 0)\`
);
transformed = transformed.replace(/val\\\\(([^)]+)\\\\)/g, (m, f) => { transformed = transformed.replace(/val\\\\(([^)]+)\\\\)/g, (m, f) => {
if (f.startsWith(table_name + '_')) { if (f.startsWith(table_name + '_')) {
return \`(parseFloat(row["\${f.slice(table_name.length + 1)}"]) || 0)\`; return \`(parseFloat(row["\${f.slice(table_name.length + 1)}"]) || 0)\`;
} }
return \`(parseFloat(frm.doc["\${f}"]) || 0)\`; return \`(parseFloat(frm.doc["\${f}"]) || 0)\`;
}); });
transformed = transformed.replace(/row\\\\(([^)]+)\\\\)/g, (m, f) =>
\`(parseFloat(row["\${f}"]) || 0)\`
);
} else { } else {
transformed = transformed.replace(/val\\\\(([^)]+)\\\\)/g, (m, f) => transformed = transformed.replace(/val\\\\(([^)]+)\\\\)/g, (m, f) =>
\`(parseFloat(frm.doc["\${f}"]) || 0)\` \`(parseFloat(frm.doc["\${f}"]) || 0)\`
@ -5757,6 +5744,11 @@ function openTableRowFormulaModal(frm, formulaId = null) {
$triggerContainer.empty(); $triggerContainer.empty();
$modal.find(".field-groups-container").empty(); $modal.find(".field-groups-container").empty();
// ИСПРАВЛЕНИЕ: явно очищаем ID формулы, если это новая формула
if (!formulaId) {
$modal.removeData("formula-id");
}
// Показываем модальное окно с блокировкой контента // Показываем модальное окно с блокировкой контента
$modal.find(".modal-content").append('<div class="modal-overlay" style="position:absolute;top:0;left:0;right:0;bottom:0;background:rgba(255,255,255,0.8);z-index:1000;display:flex;align-items:center;justify-content:center;"><div class="text-center"><div class="spinner-border text-primary" role="status"></div><div class="mt-2">Загрузка данных...</div></div></div>'); $modal.find(".modal-content").append('<div class="modal-overlay" style="position:absolute;top:0;left:0;right:0;bottom:0;background:rgba(255,255,255,0.8);z-index:1000;display:flex;align-items:center;justify-content:center;"><div class="text-center"><div class="spinner-border text-primary" role="status"></div><div class="mt-2">Загрузка данных...</div></div></div>');
$modal.modal('show'); $modal.modal('show');
@ -5894,6 +5886,11 @@ function openTableRowFormulaModal(frm, formulaId = null) {
initTriggerDragAndDrop($modal, $triggerContainer); initTriggerDragAndDrop($modal, $triggerContainer);
setupTriggerEditableContainer($triggerContainer); setupTriggerEditableContainer($triggerContainer);
// ИСПРАВЛЕНИЕ: Добавляем обработчик закрытия модального окна для очистки данных
$modal.off('hidden.bs.modal').on('hidden.bs.modal', function() {
$modal.removeData("formula-id");
});
// Удаляем блокирующий оверлей // Удаляем блокирующий оверлей
$modal.find(".modal-overlay").remove(); $modal.find(".modal-overlay").remove();
}) })
@ -6946,7 +6943,6 @@ function generateTableRowFormulasHandlers(table_row_formulas, functions, target_
try { try {
await calculate_table_row_field(frm, tableName, rowIdx, formula.field_name, formula.formula, "refresh"); await calculate_table_row_field(frm, tableName, rowIdx, formula.field_name, formula.formula, "refresh");
} catch (asyncError) { } catch (asyncError) {
console.error("Ошибка при асинхронном расчете формулы (порядок " + (formula.order || 10) + "):", asyncError);
} }
})(); })();
} else { } else {
@ -6954,13 +6950,11 @@ function generateTableRowFormulasHandlers(table_row_formulas, functions, target_
calculate_table_row_field(frm, tableName, rowIdx, formula.field_name, formula.formula, "refresh"); calculate_table_row_field(frm, tableName, rowIdx, formula.field_name, formula.formula, "refresh");
} }
} catch (error) { } catch (error) {
console.error("Ошибка расчета формулы для " + tableName + "[" + rowIdx + "]." + formula.field_name + " (порядок " + (formula.order || 10) + "):", error);
} }
} }
}); });
}); });
} catch (error) { } catch (error) {
console.error("Ошибка инициализации формул строк табличных частей:", error);
} }
}`; }`;
@ -6971,6 +6965,7 @@ function generateTableRowFormulasHandlers(table_row_formulas, functions, target_
// Функция для расчета значения поля в строке табличной части // Функция для расчета значения поля в строке табличной части
async function calculate_table_row_field(frm, tableName, rowIndex, fieldName, formula, triggerField) { async function calculate_table_row_field(frm, tableName, rowIndex, fieldName, formula, triggerField) {
try { try {
if (!frm.doc[tableName] || !frm.doc[tableName][rowIndex]) { if (!frm.doc[tableName] || !frm.doc[tableName][rowIndex]) {
return; return;
} }
@ -6978,40 +6973,106 @@ async function calculate_table_row_field(frm, tableName, rowIndex, fieldName, fo
const row = frm.doc[tableName][rowIndex]; const row = frm.doc[tableName][rowIndex];
const cdt = frm.fields_dict[tableName].grid.doctype; const cdt = frm.fields_dict[tableName].grid.doctype;
const cdn = row.name; const cdn = row.name;
const { transformed, needsAsync, reportCalls } = transform_expression(formula, true, tableName); // === Обработка report() ===
let processedFormula = formula;
let finalExpression = transformed; if (formula.includes("report(")) {
// Регулярное выражение для поиска вызовов report()
// Загрузка универсальных полей при необходимости const reportRegex = /report\\(([^)]+)\\)/g;
if (formula.includes("univ(") && !frm.doc.__universalFields) { let match;
await calculate_universal_fields(frm); const reportPromises = [];
} const reportPlaceholders = [];
// Обработка вызовов report() // Находим все вызовы report() и заменяем их на плейсхолдеры
if (reportCalls && reportCalls.length > 0) { while ((match = reportRegex.exec(formula)) !== null) {
const reportResults = []; const fullMatch = match[0]; // report(fieldName)
const fieldName = match[1]; // fieldName
for (const call of reportCalls) {
const result = await getReportFieldValue( // Создаем уникальный плейсхолдер
frm, const placeholder = \`__REPORT_PLACEHOLDER_\${reportPromises.length}__\`;
call.reportName,
call.filters, // Ищем данные отчета в хранилище или используем предопределенный отчет
call.fieldName, let reportName, reportFilters, reportField, reportAggregation;
call.aggregation
if (fieldName === "testt") {
reportName = "General Ledger";
reportFilters = {"company":"$DefaultCompany","from_date":"$AyIlSpecial","to_date":"$AyIlSpecial"};
reportField = "debit";
reportAggregation = "sum";
} else {
// Ищем в хранилище полей отчетов
const reportFields = JSON.parse(frm.doc.report_fields_storage || "{}");
const reportObj = Object.values(reportFields).find(f => f.name === fieldName);
if (reportObj) {
reportName = reportObj.report;
reportFilters = JSON.parse(reportObj.filters_json || "{}");
reportField = reportObj.field_name;
reportAggregation = reportObj.aggregation || 'sum';
} else {
processedFormula = processedFormula.replace(fullMatch, "0");
continue;
}
}
// Добавляем промис запроса к отчету
reportPromises.push(
getReportFieldValue(
frm,
reportName,
reportFilters,
reportField,
reportAggregation
)
); );
reportResults.push({ placeholder: call.placeholder, value: result });
// Запоминаем соответствие плейсхолдера и вызова
reportPlaceholders.push({
placeholder: placeholder,
original: fullMatch
});
// Заменяем вызов отчета на плейсхолдер
processedFormula = processedFormula.replace(fullMatch, placeholder);
} }
for (const result of reportResults) { // Если нашли вызовы отчетов, ждем выполнения всех запросов
finalExpression = finalExpression.replace(result.placeholder, result.value); 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
);
}
} }
} }
// Вычисление выражения // === Обработка row() ===
// Заменяем все вызовы row() на доступ к полям текущей строки
let finalFormula = processedFormula;
const rowRegex = /row\\(([^)]+)\\)/g;
finalFormula = finalFormula.replace(rowRegex, (match, fieldName) => {
return \`(parseFloat(row["\${fieldName}"]) || 0)\`;
});
// === Обработка val() ===
// Заменяем все вызовы val() на доступ к полям документа
const valRegex = /val\\(([^)]+)\\)/g;
finalFormula = finalFormula.replace(valRegex, (match, fieldName) => {
return \`(parseFloat(frm.doc["\${fieldName}"]) || 0)\`;
});
// Вычисление выражения с доступом к объекту row
let result = 0; let result = 0;
try { try {
result = eval(finalExpression); // Создаем функцию с доступом к контексту row и frm
const evalFunc = new Function('row', 'frm', \`return \${finalFormula};\`);
result = evalFunc(row, frm);
} catch (e) { } catch (e) {
} }
@ -7019,14 +7080,14 @@ async function calculate_table_row_field(frm, tableName, rowIndex, fieldName, fo
result = 0; result = 0;
} }
// Устанавливаем вычисленное значение
frappe.model.set_value(cdt, cdn, fieldName, result); frappe.model.set_value(cdt, cdn, fieldName, result);
// Обновляем таблицу // Обновляем таблицу
frm.refresh_field(tableName); frm.refresh_field(tableName);
} catch (err) { } catch (err) {
} }
} }`;
`;
functions.push(calculateFunction); functions.push(calculateFunction);
@ -7429,7 +7490,6 @@ async function handle_predefined_events(frm) {
} }
}).join('')} }).join('')}
} catch (error) { } catch (error) {
console.error("Error in predefined events handler:", error);
} }
}`; }`;
@ -8300,7 +8360,6 @@ function restoreSpecialDateValues(d, current_filters) {
} }
}); });
} catch (e) { } catch (e) {
console.error("Error restoring special date values:", e);
} }
} }
@ -9030,7 +9089,6 @@ function editReportField(frm, fieldId) {
fieldCopy.filters_json = JSON.stringify(processedFilters); fieldCopy.filters_json = JSON.stringify(processedFilters);
fieldCopy.__has_special_dates = true; // Маркер для последующего восстановления fieldCopy.__has_special_dates = true; // Маркер для последующего восстановления
} catch (e) { } catch (e) {
console.error("Error processing filters:", e);
} }
} }
@ -9132,7 +9190,6 @@ 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);
} }
}`; }`;