diff --git a/formula_editor/api.py b/formula_editor/api.py index 22c9698..29c5d9c 100644 --- a/formula_editor/api.py +++ b/formula_editor/api.py @@ -83,15 +83,12 @@ def on_trash(doc, method=None): frappe.delete_doc("Client Script", script.name, force=True) frappe.db.commit() except Exception as e: - frappe.log_error(f"Не удалось удалить клиентский скрипт {script.name}: {str(e)}") + return @frappe.whitelist() def run_report_for_formula(report_name, filters, field_name=None): """Выполняет отчет с указанными фильтрами и возвращает результат для формулы""" 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): 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"]: 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 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): from_date_value = frappe.utils.getdate(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 isinstance(to_date_value, str): to_date_value = frappe.utils.getdate(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: 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: 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: 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: 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 @@ -163,8 +153,6 @@ def run_report_for_formula(report_name, filters, field_name=None): final_filters['filter_based_on'] = "Date Range" final_filters['periodicity'] = "Monthly" - frappe.log_error(f"ОТЧЕТ API - финальные фильтры: {final_filters}", "Report API Debug") - # === Универсальное поведение: если есть дата-фильтры — используем их напрямую === if has_date_filters: standard_filters = final_filters @@ -172,40 +160,28 @@ def run_report_for_formula(report_name, filters, field_name=None): else: 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 - frappe.log_error(f"ОТЧЕТ API - запуск отчета {report_name} с фильтрами {standard_filters}", "Report API Debug") report_result = run(report_name, filters=standard_filters) 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')} columns = report_result.get('columns', []) data = report_result.get('result', []) - frappe.log_error(f"ОТЧЕТ API - получено строк данных: {len(data)}", "Report API Debug") if custom_filters: - frappe.log_error(f"ОТЧЕТ API - применяем пользовательские фильтры", "Report API Debug") data = apply_custom_filters(data, custom_filters, columns) - frappe.log_error(f"ОТЧЕТ API - после фильтрации строк: {len(data)}", "Report API Debug") if field_name: - frappe.log_error(f"ОТЧЕТ API - извлекаем поле: {field_name}", "Report API Debug") result = extract_field_from_report(data, columns, field_name) - frappe.log_error(f"ОТЧЕТ API - результат извлечения: {result}", "Report API Debug") return result - frappe.log_error("ОТЧЕТ API - возвращаем полный результат", "Report API Debug") return { "columns": columns, "data": data } except Exception as e: - frappe.log_error(f"ОТЧЕТ API - ошибка: {str(e)}\n{frappe.get_traceback()}", "Report API Debug") return {"error": str(e)} @frappe.whitelist() @@ -264,7 +240,6 @@ def generate_dynamic_filters(report_name, user_filters): continue custom_filters[key] = value except Exception as e: - frappe.log_error(f"Ошибка при получении JS-фильтров: {str(e)}", "Formula Editor") # В случае ошибки, считаем все фильтры стандартными standard_filters = processed_filters custom_filters = {} @@ -316,41 +291,21 @@ def apply_custom_filters(data, custom_filters, columns): @frappe.whitelist() 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: - frappe.log_error("ОТЧЕТ - No data returned", "Report Debug") return 0 - total = 0 - count = 0 - # Определяем индекс колонки по имени поля column_idx = None for i, col in enumerate(columns): - frappe.log_error(f"ОТЧЕТ - checking column {i}: {col}", "Report Debug") - if isinstance(col, dict): if col.get('fieldname') == field_name or col.get('label') == field_name: column_idx = i - frappe.log_error(f"ОТЧЕТ - found column by name/label at index {i}", "Report Debug") break elif isinstance(col, str) and (col == field_name or field_name.lower() in col.lower()): column_idx = i - frappe.log_error(f"ОТЧЕТ - found column by string at index {i}: {col}", "Report Debug") break - frappe.log_error(f"ОТЧЕТ - column_idx: {column_idx}", "Report Debug") - # Если колонка не найдена, ищем ее по любым подстрокам в имени if column_idx is None: 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(): column_idx = i - frappe.log_error(f"ОТЧЕТ - found column by partial match at index {i}: {col_name}", "Report Debug") break - # Если колонка найдена, суммируем значения + # Если колонка найдена, сначала ищем итоговую строку 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: value = row[field_name] - frappe.log_error(f"ОТЧЕТ - dict row value: {value}", "Report Debug") elif not isinstance(row, dict) and column_idx < len(row): value = row[column_idx] - frappe.log_error(f"ОТЧЕТ - list row value at index {column_idx}: {value}", "Report Debug") else: - # Дополнительная проверка для словарей - может, поле есть с другим регистром + # Поиск поля с игнорированием регистра if isinstance(row, dict): - # Проходим по всем ключам и ищем соответствие без учета регистра + found = False for key in row: if key.lower() == field_name.lower() or "balance" in key.lower(): value = row[key] - frappe.log_error(f"ОТЧЕТ - found value by case-insensitive key {key}: {value}", "Report Debug") + found = True break - else: - frappe.log_error(f"ОТЧЕТ - no value found in row, available keys: {list(row.keys()) if isinstance(row, dict) else 'N/A'}", "Report Debug") + if not found: continue else: - frappe.log_error(f"ОТЧЕТ - no value found in row", "Report Debug") continue - # Пытаемся преобразовать в число + # Преобразуем в число try: if value is not None: num_value = float(value) total += num_value count += 1 - frappe.log_error(f"ОТЧЕТ - added value: {num_value}, total now: {total}", "Report Debug") except (ValueError, TypeError): - frappe.log_error(f"ОТЧЕТ - could not convert value to float: {value}", "Report Debug") pass + + return total 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]): if isinstance(row, dict): for key, value in row.items(): try: - # Проверяем, можно ли преобразовать в число if value is not None: num_value = float(value) - frappe.log_error(f"ОТЧЕТ - found numeric value in key {key}: {num_value}", "Report Debug") total += num_value count += 1 break @@ -424,15 +491,13 @@ def extract_field_from_report(data, columns, field_name): try: if value is not None: num_value = float(value) - frappe.log_error(f"ОТЧЕТ - found numeric value at index {i}: {num_value}", "Report Debug") total += num_value count += 1 break except (ValueError, TypeError): continue - frappe.log_error(f"ОТЧЕТ - final total: {total}, count: {count}", "Report Debug") - # Возвращаем сумму или 0, если не удалось найти + # Возвращаем итоговую сумму или 0 return total @frappe.whitelist() @@ -668,7 +733,6 @@ def get_report_filters_dynamic(report_name): 'reqd': 1 # Считаем базовые фильтры обязательными }) except Exception as e: - frappe.log_error(f"Ошибка при выполнении отчета с базовыми фильтрами: {str(e)}", "Formula Editor") # Анализируем ошибку на предмет недостающих фильтров error_msg = str(e) @@ -736,7 +800,6 @@ def get_report_filters_dynamic(report_name): return formatted_filters except Exception as e: - frappe.log_error(f"Ошибка при получении фильтров отчета: {str(e)}", "Formula Editor") return [] diff --git a/formula_editor/locale/bg.po b/formula_editor/locale/bg.po new file mode 100644 index 0000000..d820f21 --- /dev/null +++ b/formula_editor/locale/bg.po @@ -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 , 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 "" + diff --git a/formula_editor/locale/main.pot b/formula_editor/locale/main.pot new file mode 100644 index 0000000..031c8df --- /dev/null +++ b/formula_editor/locale/main.pot @@ -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 , 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 "" +