Fully added report system

This commit is contained in:
Ali 2025-04-22 11:36:20 +04:00
parent 33939cbfc4
commit e07740ce6d
3 changed files with 681 additions and 450 deletions

View File

@ -91,31 +91,26 @@ 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)
# Создаем новый словарь для обработанных фильтров
final_filters = {}
# Копируем компанию и другие базовые фильтры (не даты)
for key, value in filters.items():
if not ('from_date' in key or 'to_date' in key or 'from' == key or 'to' == key or 'period_start_date' == key or 'period_end_date' == key):
final_filters[key] = value
# Проверяем и устанавливаем значение компании по умолчанию
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
from_date_value = None
to_date_value = None
# Ищем фильтры с операторами для дат
for key, value in filters.items():
if 'from_date>' in key or 'from_date>=' in key:
from_date_key = key
@ -124,7 +119,6 @@ def run_report_for_formula(report_name, filters, field_name=None):
to_date_key = key
to_date_value = value
# Если нашли специальные операторы, используем их значения
if from_date_key and from_date_value:
if isinstance(from_date_value, str):
from_date_value = frappe.utils.getdate(from_date_value)
@ -137,22 +131,14 @@ def run_report_for_formula(report_name, filters, field_name=None):
final_filters['to_date'] = to_date_value
frappe.log_error(f"ОТЧЕТ API - используем to_date из {to_date_key}: {final_filters['to_date']}", "Report API Debug")
# Если нет специальных операторов, проверяем обычные поля from_date и to_date
if 'from_date' not in final_filters and 'from_date' in filters:
if isinstance(filters['from_date'], str):
final_filters['from_date'] = frappe.utils.getdate(filters['from_date'])
else:
final_filters['from_date'] = 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 isinstance(filters['to_date'], str):
final_filters['to_date'] = frappe.utils.getdate(filters['to_date'])
else:
final_filters['to_date'] = 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:
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")
@ -161,63 +147,58 @@ def run_report_for_formula(report_name, filters, field_name=None):
final_filters['to_date'] = frappe.utils.nowdate()
frappe.log_error(f"ОТЧЕТ API - устанавливаем to_date по умолчанию: {final_filters['to_date']}", "Report API Debug")
# Специальная обработка для отчетов в зависимости от их типа
if report_name.lower() in ["general ledger", "general_ledger"]:
# Для General Ledger нужны поля from и to
final_filters['from'] = final_filters['from_date']
final_filters['to'] = final_filters['to_date']
elif report_name.lower() in ["cash flow", "cash_flow"]:
# Для Cash Flow нужны period_start_date и period_end_date
final_filters['period_start_date'] = final_filters['from_date']
final_filters['period_end_date'] = final_filters['to_date']
# Также добавляем filter_based_on со значением "Date Range"
final_filters['filter_based_on'] = "Date Range"
# и periodicity со значением "Monthly"
final_filters['periodicity'] = "Monthly"
# === Универсальная логика для подстановки доп. полей на основе даты ===
has_date_filters = 'from_date' in final_filters or 'to_date' in final_filters
report_name_lc = report_name.lower()
if has_date_filters:
# Применяем поля from и to для всех отчетов, кроме cash flow
if report_name_lc not in ["cash flow", "cash_flow"]:
final_filters['from'] = final_filters.get('from_date')
final_filters['to'] = final_filters.get('to_date')
# Специальная обработка только для cash flow
elif report_name_lc in ["cash flow", "cash_flow"]:
final_filters['period_start_date'] = final_filters.get('from_date')
final_filters['period_end_date'] = final_filters.get('to_date')
final_filters['filter_based_on'] = "Date Range"
final_filters['periodicity'] = "Monthly"
frappe.log_error(f"ОТЧЕТ API - финальные фильтры: {final_filters}", "Report API Debug")
# Для указанных отчетов просто используем подготовленные фильтры
if report_name.lower() in ["general ledger", "general_ledger", "cash flow", "cash_flow"]:
# === Универсальное поведение: если есть дата-фильтры — используем их напрямую ===
if has_date_filters:
standard_filters = final_filters
custom_filters = {}
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,

View File

@ -36,7 +36,7 @@
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-04-08 17:10:17.242850",
"modified": "2025-04-18 18:47:01.288110",
"modified_by": "Administrator",
"module": "Formula Editor",
"name": "Report Simulator",