Fixed bug with logs

This commit is contained in:
Away 2025-04-22 18:33:58 +00:00
parent 644b57204a
commit 022c809acc
3 changed files with 712 additions and 71 deletions

View File

@ -83,15 +83,12 @@ def on_trash(doc, method=None):
frappe.delete_doc("Client Script", script.name, force=True) frappe.delete_doc("Client Script", script.name, force=True)
frappe.db.commit() frappe.db.commit()
except Exception as e: except Exception as e:
frappe.log_error(f"Не удалось удалить клиентский скрипт {script.name}: {str(e)}") return
@frappe.whitelist() @frappe.whitelist()
def run_report_for_formula(report_name, filters, field_name=None): def run_report_for_formula(report_name, filters, field_name=None):
"""Выполняет отчет с указанными фильтрами и возвращает результат для формулы""" """Выполняет отчет с указанными фильтрами и возвращает результат для формулы"""
try: try:
frappe.log_error(f"ОТЧЕТ API - начало запроса: {report_name}, поле: {field_name}", "Report API Debug")
frappe.log_error(f"ОТЧЕТ API - фильтры: {filters}", "Report API Debug")
frappe.log_error(f"ОТЧЕТ API - сырые фильтры (тип: {type(filters)}): {filters}", "Report API Debug")
if isinstance(filters, str): if isinstance(filters, str):
filters = json.loads(filters) filters = json.loads(filters)
@ -104,7 +101,6 @@ def run_report_for_formula(report_name, filters, field_name=None):
if "company" not in final_filters or not final_filters["company"]: if "company" not in final_filters or not final_filters["company"]:
final_filters["company"] = frappe.defaults.get_user_default("Company") or frappe.db.get_single_value("Global Defaults", "default_company") final_filters["company"] = frappe.defaults.get_user_default("Company") or frappe.db.get_single_value("Global Defaults", "default_company")
frappe.log_error(f"ОТЧЕТ API - установлена компания по умолчанию: {final_filters['company']}", "Report API Debug")
from_date_key = None from_date_key = None
to_date_key = None to_date_key = None
@ -123,29 +119,23 @@ def run_report_for_formula(report_name, filters, field_name=None):
if isinstance(from_date_value, str): if isinstance(from_date_value, str):
from_date_value = frappe.utils.getdate(from_date_value) from_date_value = frappe.utils.getdate(from_date_value)
final_filters['from_date'] = from_date_value final_filters['from_date'] = from_date_value
frappe.log_error(f"ОТЧЕТ API - используем from_date из {from_date_key}: {final_filters['from_date']}", "Report API Debug")
if to_date_key and to_date_value: if to_date_key and to_date_value:
if isinstance(to_date_value, str): if isinstance(to_date_value, str):
to_date_value = frappe.utils.getdate(to_date_value) to_date_value = frappe.utils.getdate(to_date_value)
final_filters['to_date'] = to_date_value final_filters['to_date'] = to_date_value
frappe.log_error(f"ОТЧЕТ API - используем to_date из {to_date_key}: {final_filters['to_date']}", "Report API Debug")
if 'from_date' not in final_filters and 'from_date' in filters: if 'from_date' not in final_filters and 'from_date' in filters:
final_filters['from_date'] = frappe.utils.getdate(filters['from_date']) if isinstance(filters['from_date'], str) else filters['from_date'] final_filters['from_date'] = frappe.utils.getdate(filters['from_date']) if isinstance(filters['from_date'], str) else filters['from_date']
frappe.log_error(f"ОТЧЕТ API - используем стандартное поле from_date: {final_filters['from_date']}", "Report API Debug")
if 'to_date' not in final_filters and 'to_date' in filters: if 'to_date' not in final_filters and 'to_date' in filters:
final_filters['to_date'] = frappe.utils.getdate(filters['to_date']) if isinstance(filters['to_date'], str) else filters['to_date'] final_filters['to_date'] = frappe.utils.getdate(filters['to_date']) if isinstance(filters['to_date'], str) else filters['to_date']
frappe.log_error(f"ОТЧЕТ API - используем стандартное поле to_date: {final_filters['to_date']}", "Report API Debug")
if 'from_date' not in final_filters: if 'from_date' not in final_filters:
final_filters['from_date'] = frappe.utils.get_first_day(frappe.utils.nowdate()) final_filters['from_date'] = frappe.utils.get_first_day(frappe.utils.nowdate())
frappe.log_error(f"ОТЧЕТ API - устанавливаем from_date по умолчанию: {final_filters['from_date']}", "Report API Debug")
if 'to_date' not in final_filters: if 'to_date' not in final_filters:
final_filters['to_date'] = frappe.utils.nowdate() final_filters['to_date'] = frappe.utils.nowdate()
frappe.log_error(f"ОТЧЕТ API - устанавливаем to_date по умолчанию: {final_filters['to_date']}", "Report API Debug")
# === Универсальная логика для подстановки доп. полей на основе даты === # === Универсальная логика для подстановки доп. полей на основе даты ===
has_date_filters = 'from_date' in final_filters or 'to_date' in final_filters has_date_filters = 'from_date' in final_filters or 'to_date' in final_filters
@ -163,8 +153,6 @@ def run_report_for_formula(report_name, filters, field_name=None):
final_filters['filter_based_on'] = "Date Range" final_filters['filter_based_on'] = "Date Range"
final_filters['periodicity'] = "Monthly" final_filters['periodicity'] = "Monthly"
frappe.log_error(f"ОТЧЕТ API - финальные фильтры: {final_filters}", "Report API Debug")
# === Универсальное поведение: если есть дата-фильтры — используем их напрямую === # === Универсальное поведение: если есть дата-фильтры — используем их напрямую ===
if has_date_filters: if has_date_filters:
standard_filters = final_filters standard_filters = final_filters
@ -172,40 +160,28 @@ def run_report_for_formula(report_name, filters, field_name=None):
else: else:
standard_filters, custom_filters = generate_dynamic_filters(report_name, final_filters) standard_filters, custom_filters = generate_dynamic_filters(report_name, final_filters)
frappe.log_error(f"ОТЧЕТ API - стандартные фильтры: {standard_filters}", "Report API Debug")
frappe.log_error(f"ОТЧЕТ API - пользовательские фильтры: {custom_filters}", "Report API Debug")
from frappe.desk.query_report import run from frappe.desk.query_report import run
frappe.log_error(f"ОТЧЕТ API - запуск отчета {report_name} с фильтрами {standard_filters}", "Report API Debug")
report_result = run(report_name, filters=standard_filters) report_result = run(report_name, filters=standard_filters)
if isinstance(report_result, dict) and report_result.get('message'): if isinstance(report_result, dict) and report_result.get('message'):
frappe.log_error(f"ОТЧЕТ API - получена ошибка: {report_result.get('message')}", "Report API Debug")
return {"error": report_result.get('message')} return {"error": report_result.get('message')}
columns = report_result.get('columns', []) columns = report_result.get('columns', [])
data = report_result.get('result', []) data = report_result.get('result', [])
frappe.log_error(f"ОТЧЕТ API - получено строк данных: {len(data)}", "Report API Debug")
if custom_filters: if custom_filters:
frappe.log_error(f"ОТЧЕТ API - применяем пользовательские фильтры", "Report API Debug")
data = apply_custom_filters(data, custom_filters, columns) data = apply_custom_filters(data, custom_filters, columns)
frappe.log_error(f"ОТЧЕТ API - после фильтрации строк: {len(data)}", "Report API Debug")
if field_name: if field_name:
frappe.log_error(f"ОТЧЕТ API - извлекаем поле: {field_name}", "Report API Debug")
result = extract_field_from_report(data, columns, field_name) result = extract_field_from_report(data, columns, field_name)
frappe.log_error(f"ОТЧЕТ API - результат извлечения: {result}", "Report API Debug")
return result return result
frappe.log_error("ОТЧЕТ API - возвращаем полный результат", "Report API Debug")
return { return {
"columns": columns, "columns": columns,
"data": data "data": data
} }
except Exception as e: except Exception as e:
frappe.log_error(f"ОТЧЕТ API - ошибка: {str(e)}\n{frappe.get_traceback()}", "Report API Debug")
return {"error": str(e)} return {"error": str(e)}
@frappe.whitelist() @frappe.whitelist()
@ -264,7 +240,6 @@ def generate_dynamic_filters(report_name, user_filters):
continue continue
custom_filters[key] = value custom_filters[key] = value
except Exception as e: except Exception as e:
frappe.log_error(f"Ошибка при получении JS-фильтров: {str(e)}", "Formula Editor")
# В случае ошибки, считаем все фильтры стандартными # В случае ошибки, считаем все фильтры стандартными
standard_filters = processed_filters standard_filters = processed_filters
custom_filters = {} custom_filters = {}
@ -317,40 +292,20 @@ def apply_custom_filters(data, custom_filters, columns):
def extract_field_from_report(data, columns, field_name): def extract_field_from_report(data, columns, field_name):
"""Извлекает значение конкретного поля из результатов отчета""" """Извлекает значение конкретного поля из результатов отчета"""
# Логгируем входящие параметры
frappe.log_error(f"ОТЧЕТ - field_name: {field_name}", "Report Debug")
frappe.log_error(f"ОТЧЕТ - columns: {columns[:10] if columns else 'None'}", "Report Debug")
frappe.log_error(f"ОТЧЕТ - data count: {len(data) if data else 0}", "Report Debug")
if data and len(data) > 0:
frappe.log_error(f"ОТЧЕТ - first row type: {type(data[0])}", "Report Debug")
frappe.log_error(f"ОТЧЕТ - first row content: {data[0]}", "Report Debug")
# Проверяем, есть ли данные
if not data: if not data:
frappe.log_error("ОТЧЕТ - No data returned", "Report Debug")
return 0 return 0
total = 0
count = 0
# Определяем индекс колонки по имени поля # Определяем индекс колонки по имени поля
column_idx = None column_idx = None
for i, col in enumerate(columns): for i, col in enumerate(columns):
frappe.log_error(f"ОТЧЕТ - checking column {i}: {col}", "Report Debug")
if isinstance(col, dict): if isinstance(col, dict):
if col.get('fieldname') == field_name or col.get('label') == field_name: if col.get('fieldname') == field_name or col.get('label') == field_name:
column_idx = i column_idx = i
frappe.log_error(f"ОТЧЕТ - found column by name/label at index {i}", "Report Debug")
break break
elif isinstance(col, str) and (col == field_name or field_name.lower() in col.lower()): elif isinstance(col, str) and (col == field_name or field_name.lower() in col.lower()):
column_idx = i column_idx = i
frappe.log_error(f"ОТЧЕТ - found column by string at index {i}: {col}", "Report Debug")
break break
frappe.log_error(f"ОТЧЕТ - column_idx: {column_idx}", "Report Debug")
# Если колонка не найдена, ищем ее по любым подстрокам в имени # Если колонка не найдена, ищем ее по любым подстрокам в имени
if column_idx is None: if column_idx is None:
for i, col in enumerate(columns): for i, col in enumerate(columns):
@ -363,57 +318,169 @@ def extract_field_from_report(data, columns, field_name):
# Проверка на частичное совпадение # Проверка на частичное совпадение
if field_name.lower() in col_name.lower() or "balance" in col_name.lower(): if field_name.lower() in col_name.lower() or "balance" in col_name.lower():
column_idx = i column_idx = i
frappe.log_error(f"ОТЧЕТ - found column by partial match at index {i}: {col_name}", "Report Debug")
break break
# Если колонка найдена, суммируем значения # Если колонка найдена, сначала ищем итоговую строку
if column_idx is not None: if column_idx is not None:
for idx, row in enumerate(data[:10]): # Логируем только первые 10 строк для производительности # Определяем возможные маркеры итоговых строк
frappe.log_error(f"ОТЧЕТ - processing row {idx}: {row}", "Report Debug") total_markers = ['total', 'итого', 'grand total', 'общий итог', 'итого по', 'total row']
# Ищем итоговые строки
total_rows = []
for idx, row in enumerate(data):
is_total_row = False
if isinstance(row, dict):
# Проверяем ключи и значения на наличие маркеров итога
for key, value in row.items():
if isinstance(value, str) and any(marker in value.lower() for marker in total_markers):
is_total_row = True
break
if isinstance(key, str) and any(marker in key.lower() for marker in total_markers):
is_total_row = True
break
# Проверяем специальные атрибуты итоговых строк
if (row.get('is_total_row') or
row.get('bold') or
row.get('total_row') or
row.get('is_group', 0) == 0 and row.get('indent', 0) == 0):
is_total_row = True
elif isinstance(row, list) and len(row) > 0:
# Для списков проверяем первый элемент
first_element = str(row[0]) if row[0] is not None else ""
if any(marker in first_element.lower() for marker in total_markers):
is_total_row = True
if is_total_row:
total_rows.append((idx, row))
# Если нашли итоговые строки, используем последнюю (обычно она Grand Total)
if total_rows:
# Сортируем по индексу в обратном порядке, чтобы получить последнюю итоговую строку
total_rows.sort(key=lambda x: x[0], reverse=True)
_, total_row = total_rows[0]
# Извлекаем значение из итоговой строки
if isinstance(total_row, dict):
if field_name in total_row:
value = total_row[field_name]
else:
# Поиск с игнорированием регистра
for key in total_row:
if key.lower() == field_name.lower() or (
field_name.lower() in key.lower() and
any(num_word in key.lower() for num_word in ['amount', 'total', 'sum', 'balance'])
):
value = total_row[key]
break
else:
value = None
elif isinstance(total_row, list) and column_idx < len(total_row):
value = total_row[column_idx]
else:
value = None
# Преобразуем в число
try:
if value is not None:
return float(value)
except (ValueError, TypeError):
pass
# Если итоговую строку не нашли, проверяем последнюю строку
# (часто это итоговая строка без явного маркера)
if len(data) > 0:
last_row = data[-1]
# Извлекаем значение из последней строки
if isinstance(last_row, dict):
if field_name in last_row:
value = last_row[field_name]
else:
# Поиск с игнорированием регистра
for key in last_row:
if key.lower() == field_name.lower() or (
field_name.lower() in key.lower() and
any(num_word in key.lower() for num_word in ['amount', 'total', 'sum', 'balance'])
):
value = last_row[key]
break
else:
value = None
elif isinstance(last_row, list) and column_idx < len(last_row):
value = last_row[column_idx]
else:
value = None
# Проверяем, похоже ли это на итоговую строку
# (по сравнению с предпоследней строкой)
try:
if value is not None and len(data) > 1:
second_last_row = data[-2]
second_last_value = None
if isinstance(second_last_row, dict) and field_name in second_last_row:
second_last_value = second_last_row[field_name]
elif not isinstance(second_last_row, dict) and column_idx < len(second_last_row):
second_last_value = second_last_row[column_idx]
# Если последнее значение существенно больше предыдущего,
# вероятно это строка итога
if (second_last_value is not None and
isinstance(value, (int, float)) and
isinstance(second_last_value, (int, float)) and
value > second_last_value * 1.5):
return float(value)
except (ValueError, TypeError, IndexError):
pass
# Если ни одна из проверок не сработала, суммируем все значения как раньше
total = 0
count = 0
for row in data:
if isinstance(row, dict) and field_name in row: if isinstance(row, dict) and field_name in row:
value = row[field_name] value = row[field_name]
frappe.log_error(f"ОТЧЕТ - dict row value: {value}", "Report Debug")
elif not isinstance(row, dict) and column_idx < len(row): elif not isinstance(row, dict) and column_idx < len(row):
value = row[column_idx] value = row[column_idx]
frappe.log_error(f"ОТЧЕТ - list row value at index {column_idx}: {value}", "Report Debug")
else: else:
# Дополнительная проверка для словарей - может, поле есть с другим регистром # Поиск поля с игнорированием регистра
if isinstance(row, dict): if isinstance(row, dict):
# Проходим по всем ключам и ищем соответствие без учета регистра found = False
for key in row: for key in row:
if key.lower() == field_name.lower() or "balance" in key.lower(): if key.lower() == field_name.lower() or "balance" in key.lower():
value = row[key] value = row[key]
frappe.log_error(f"ОТЧЕТ - found value by case-insensitive key {key}: {value}", "Report Debug") found = True
break break
else: if not found:
frappe.log_error(f"ОТЧЕТ - no value found in row, available keys: {list(row.keys()) if isinstance(row, dict) else 'N/A'}", "Report Debug")
continue continue
else: else:
frappe.log_error(f"ОТЧЕТ - no value found in row", "Report Debug")
continue continue
# Пытаемся преобразовать в число # Преобразуем в число
try: try:
if value is not None: if value is not None:
num_value = float(value) num_value = float(value)
total += num_value total += num_value
count += 1 count += 1
frappe.log_error(f"ОТЧЕТ - added value: {num_value}, total now: {total}", "Report Debug")
except (ValueError, TypeError): except (ValueError, TypeError):
frappe.log_error(f"ОТЧЕТ - could not convert value to float: {value}", "Report Debug")
pass pass
return total
else: else:
# Если колонка не найдена, попробуем найти первое числовое поле как заглушку # Если колонка не найдена, ищем любое первое числовое поле
frappe.log_error(f"ОТЧЕТ - column not found, trying to find any numeric field", "Report Debug") total = 0
count = 0
for idx, row in enumerate(data[:5]): for idx, row in enumerate(data[:5]):
if isinstance(row, dict): if isinstance(row, dict):
for key, value in row.items(): for key, value in row.items():
try: try:
# Проверяем, можно ли преобразовать в число
if value is not None: if value is not None:
num_value = float(value) num_value = float(value)
frappe.log_error(f"ОТЧЕТ - found numeric value in key {key}: {num_value}", "Report Debug")
total += num_value total += num_value
count += 1 count += 1
break break
@ -424,15 +491,13 @@ def extract_field_from_report(data, columns, field_name):
try: try:
if value is not None: if value is not None:
num_value = float(value) num_value = float(value)
frappe.log_error(f"ОТЧЕТ - found numeric value at index {i}: {num_value}", "Report Debug")
total += num_value total += num_value
count += 1 count += 1
break break
except (ValueError, TypeError): except (ValueError, TypeError):
continue continue
frappe.log_error(f"ОТЧЕТ - final total: {total}, count: {count}", "Report Debug") # Возвращаем итоговую сумму или 0
# Возвращаем сумму или 0, если не удалось найти
return total return total
@frappe.whitelist() @frappe.whitelist()
@ -668,7 +733,6 @@ def get_report_filters_dynamic(report_name):
'reqd': 1 # Считаем базовые фильтры обязательными 'reqd': 1 # Считаем базовые фильтры обязательными
}) })
except Exception as e: except Exception as e:
frappe.log_error(f"Ошибка при выполнении отчета с базовыми фильтрами: {str(e)}", "Formula Editor")
# Анализируем ошибку на предмет недостающих фильтров # Анализируем ошибку на предмет недостающих фильтров
error_msg = str(e) error_msg = str(e)
@ -736,7 +800,6 @@ def get_report_filters_dynamic(report_name):
return formatted_filters return formatted_filters
except Exception as e: except Exception as e:
frappe.log_error(f"Ошибка при получении фильтров отчета: {str(e)}", "Formula Editor")
return [] return []

290
formula_editor/locale/bg.po Normal file
View File

@ -0,0 +1,290 @@
# Bulgarian translations for Formula Editor.
# Copyright (C) 2025 Your Company
# This file is distributed under the same license as the Formula Editor project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: Formula Editor VERSION\n"
"Report-Msgid-Bugs-To: your.email@example.com\n"
"POT-Creation-Date: 2025-04-22 08:29+0000\n"
"PO-Revision-Date: 2025-04-22 08:54+0000\n"
"Last-Translator: your.email@example.com\n"
"Language: bg\n"
"Language-Team: your.email@example.com\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.13.1\n"
#: formula_editor/doctype/formula_editor/formula_editor.js:4745
msgid "DocType ${doctype} не найден"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4226
msgid "DocType ${selectedDoctype} не найден"
msgstr ""
#. Name of a DocType
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "Formula Editor"
msgstr ""
#. Label of a Code field in DocType 'Report Simulator'
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "JSON"
msgstr ""
#. Label of a Link field in DocType 'Report Simulator'
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "Report"
msgstr ""
#. Name of a DocType
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "Report Simulator"
msgstr ""
#. Label of a Long Text field in DocType 'Report Simulator'
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "Result"
msgstr ""
#. Name of a role
#: formula_editor/doctype/formula_editor/formula_editor.json
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "System Manager"
msgstr ""
#. Label of a Section Break field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "formula_fields"
msgstr ""
#. Label of a Long Text field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "formula_storage"
msgstr ""
#. Label of a Long Text field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "report_fields_storage"
msgstr ""
#. Label of a Long Text field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "table_row_formulas_storage"
msgstr ""
#. Label of a Link field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "target_doctype"
msgstr ""
#. Label of a Long Text field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "universal_fields_storage"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:3
msgid "Быстрая симуляция"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:6
msgid "Быстрая симуляция отчета"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4793
msgid "В DocType ${doctype} не найдено числовых полей"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4246
msgid "В DocType ${selectedDoctype} не найдено подходящих полей"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4399
#: formula_editor/doctype/formula_editor/formula_editor.js:5121
#: formula_editor/doctype/formula_editor/formula_editor.js:5832
#: formula_editor/doctype/formula_editor/formula_editor.js:6846
#: formula_editor/doctype/formula_editor/formula_editor.js:8202
#: formula_editor/doctype/formula_editor/formula_editor.js:8840
msgid "Внимание"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5833
#: formula_editor/doctype/formula_editor/formula_editor.js:6847
msgid "Выберите табличную часть, поле и укажите номер строки"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:53
msgid "Выполнение отчета..."
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:4
msgid "Выполнить отчет"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:98
msgid "Динамические фильтры"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:60
msgid "Для этого отчета не найдены фильтры. Используйте формат JSON для настройки фильтров."
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:53
msgid "Загружено ${r.message.length} фильтров для отчета"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:42
msgid "Загрузка фильтров отчета..."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4400
#: formula_editor/doctype/formula_editor/formula_editor.js:8203
msgid "Заполните все обязательные поля"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:30
msgid "Запустить"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:21
msgid "Настроить фильтры"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5897
msgid "Не удалось загрузить данные для формулы строки таблицы"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:9012
msgid "Не удалось открыть поле отчета для редактирования: "
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:8885
msgid "Не удалось сохранить поле отчета: "
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5169
msgid "Не удалось сохранить универсальное поле."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:6360
msgid "Не удалось сохранить формулу для строки табличной части."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:9037
msgid "Не удалось удалить поле отчета."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5269
msgid "Не удалось удалить универсальное поле."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:6443
msgid "Не удалось удалить формулу для строки табличной части."
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:184
#: formula_editor/doctype/report_simulator/report_simulator_list.js:41
msgid "Некорректный формат JSON"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:11
msgid "Отчет"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4225
#: formula_editor/doctype/formula_editor/formula_editor.js:4744
#: formula_editor/doctype/formula_editor/formula_editor.js:5168
#: formula_editor/doctype/formula_editor/formula_editor.js:5268
#: formula_editor/doctype/formula_editor/formula_editor.js:5896
#: formula_editor/doctype/formula_editor/formula_editor.js:6359
#: formula_editor/doctype/formula_editor/formula_editor.js:6442
#: formula_editor/doctype/formula_editor/formula_editor.js:8884
#: formula_editor/doctype/formula_editor/formula_editor.js:9011
#: formula_editor/doctype/formula_editor/formula_editor.js:9036
msgid "Ошибка"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:198
msgid "Ошибка при применении фильтров: ${e.message}"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:33
msgid "Пожалуйста, выберите отчет"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:78
msgid "Пожалуйста, подождите загрузки фильтров и попробуйте снова"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:71
msgid "Пожалуйста, сначала выберите отчет"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:8877
msgid "Поле отчета сохранено"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:9031
msgid "Поле отчета удалено"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5122
#: formula_editor/doctype/formula_editor/formula_editor.js:8841
msgid "Поле с таким именем уже существует."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4245
#: formula_editor/doctype/formula_editor/formula_editor.js:4792
msgid "Предупреждение"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:155
msgid "Применить"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:11
#: formula_editor/doctype/report_simulator/report_simulator_list.js:95
msgid "Результат отчета"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:138
msgid "Ручное редактирование"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:108
msgid "Симуляция сохранена"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5161
msgid "Универсальное поле сохранено"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5263
msgid "Универсальное поле удалено"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:146
#: formula_editor/doctype/report_simulator/report_simulator_list.js:25
msgid "Фильтры (JSON)"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:153
msgid "Фильтры отчета"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:194
msgid "Фильтры успешно применены"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:6351
msgid "Формула для строки табличной части сохранена"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:6437
msgid "Формула для строки табличной части удалена"
msgstr ""

View File

@ -0,0 +1,288 @@
# Translations template for Formula Editor.
# Copyright (C) 2025 Your Company
# This file is distributed under the same license as the Formula Editor project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: Formula Editor VERSION\n"
"Report-Msgid-Bugs-To: your.email@example.com\n"
"POT-Creation-Date: 2025-04-22 08:29+0000\n"
"PO-Revision-Date: 2025-04-22 08:29+0000\n"
"Last-Translator: your.email@example.com\n"
"Language-Team: your.email@example.com\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.13.1\n"
#: formula_editor/doctype/formula_editor/formula_editor.js:4745
msgid "DocType ${doctype} не найден"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4226
msgid "DocType ${selectedDoctype} не найден"
msgstr ""
#. Name of a DocType
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "Formula Editor"
msgstr ""
#. Label of a Code field in DocType 'Report Simulator'
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "JSON"
msgstr ""
#. Label of a Link field in DocType 'Report Simulator'
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "Report"
msgstr ""
#. Name of a DocType
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "Report Simulator"
msgstr ""
#. Label of a Long Text field in DocType 'Report Simulator'
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "Result"
msgstr ""
#. Name of a role
#: formula_editor/doctype/formula_editor/formula_editor.json
#: formula_editor/doctype/report_simulator/report_simulator.json
msgid "System Manager"
msgstr ""
#. Label of a Section Break field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "formula_fields"
msgstr ""
#. Label of a Long Text field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "formula_storage"
msgstr ""
#. Label of a Long Text field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "report_fields_storage"
msgstr ""
#. Label of a Long Text field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "table_row_formulas_storage"
msgstr ""
#. Label of a Link field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "target_doctype"
msgstr ""
#. Label of a Long Text field in DocType 'Formula Editor'
#: formula_editor/doctype/formula_editor/formula_editor.json
msgid "universal_fields_storage"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:3
msgid "Быстрая симуляция"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:6
msgid "Быстрая симуляция отчета"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4793
msgid "В DocType ${doctype} не найдено числовых полей"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4246
msgid "В DocType ${selectedDoctype} не найдено подходящих полей"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4399
#: formula_editor/doctype/formula_editor/formula_editor.js:5121
#: formula_editor/doctype/formula_editor/formula_editor.js:5832
#: formula_editor/doctype/formula_editor/formula_editor.js:6846
#: formula_editor/doctype/formula_editor/formula_editor.js:8202
#: formula_editor/doctype/formula_editor/formula_editor.js:8840
msgid "Внимание"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5833
#: formula_editor/doctype/formula_editor/formula_editor.js:6847
msgid "Выберите табличную часть, поле и укажите номер строки"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:53
msgid "Выполнение отчета..."
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:4
msgid "Выполнить отчет"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:98
msgid "Динамические фильтры"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:60
msgid "Для этого отчета не найдены фильтры. Используйте формат JSON для настройки фильтров."
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:53
msgid "Загружено ${r.message.length} фильтров для отчета"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:42
msgid "Загрузка фильтров отчета..."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4400
#: formula_editor/doctype/formula_editor/formula_editor.js:8203
msgid "Заполните все обязательные поля"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:30
msgid "Запустить"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:21
msgid "Настроить фильтры"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5897
msgid "Не удалось загрузить данные для формулы строки таблицы"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:9012
msgid "Не удалось открыть поле отчета для редактирования: "
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:8885
msgid "Не удалось сохранить поле отчета: "
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5169
msgid "Не удалось сохранить универсальное поле."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:6360
msgid "Не удалось сохранить формулу для строки табличной части."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:9037
msgid "Не удалось удалить поле отчета."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5269
msgid "Не удалось удалить универсальное поле."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:6443
msgid "Не удалось удалить формулу для строки табличной части."
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:184
#: formula_editor/doctype/report_simulator/report_simulator_list.js:41
msgid "Некорректный формат JSON"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:11
msgid "Отчет"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4225
#: formula_editor/doctype/formula_editor/formula_editor.js:4744
#: formula_editor/doctype/formula_editor/formula_editor.js:5168
#: formula_editor/doctype/formula_editor/formula_editor.js:5268
#: formula_editor/doctype/formula_editor/formula_editor.js:5896
#: formula_editor/doctype/formula_editor/formula_editor.js:6359
#: formula_editor/doctype/formula_editor/formula_editor.js:6442
#: formula_editor/doctype/formula_editor/formula_editor.js:8884
#: formula_editor/doctype/formula_editor/formula_editor.js:9011
#: formula_editor/doctype/formula_editor/formula_editor.js:9036
msgid "Ошибка"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:198
msgid "Ошибка при применении фильтров: ${e.message}"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:33
msgid "Пожалуйста, выберите отчет"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:78
msgid "Пожалуйста, подождите загрузки фильтров и попробуйте снова"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:71
msgid "Пожалуйста, сначала выберите отчет"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:8877
msgid "Поле отчета сохранено"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:9031
msgid "Поле отчета удалено"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5122
#: formula_editor/doctype/formula_editor/formula_editor.js:8841
msgid "Поле с таким именем уже существует."
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:4245
#: formula_editor/doctype/formula_editor/formula_editor.js:4792
msgid "Предупреждение"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:155
msgid "Применить"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:11
#: formula_editor/doctype/report_simulator/report_simulator_list.js:95
msgid "Результат отчета"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:138
msgid "Ручное редактирование"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator_list.js:108
msgid "Симуляция сохранена"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5161
msgid "Универсальное поле сохранено"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:5263
msgid "Универсальное поле удалено"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:146
#: formula_editor/doctype/report_simulator/report_simulator_list.js:25
msgid "Фильтры (JSON)"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:153
msgid "Фильтры отчета"
msgstr ""
#: formula_editor/doctype/report_simulator/report_simulator.js:194
msgid "Фильтры успешно применены"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:6351
msgid "Формула для строки табличной части сохранена"
msgstr ""
#: formula_editor/doctype/formula_editor/formula_editor.js:6437
msgid "Формула для строки табличной части удалена"
msgstr ""