Files
python_parser/python_parser/core/services.py

220 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Сервисы (бизнес-логика)
"""
import tempfile
import os
from typing import Dict, Type
from core.models import UploadRequest, UploadResult, DataRequest, DataResult
from core.ports import ParserPort, StoragePort
# Глобальный словарь парсеров
PARSERS: Dict[str, Type[ParserPort]] = {}
def get_parser(report_type: str) -> ParserPort:
"""Получение парсера по типу отчета"""
if report_type not in PARSERS:
available_parsers = list(PARSERS.keys())
raise ValueError(f"Неизвестный тип отчета '{report_type}'. Доступные типы: {available_parsers}")
return PARSERS[report_type]()
class ReportService:
"""Сервис для работы с отчетами (только S3)"""
def __init__(self, storage: StoragePort):
self.storage = storage
def upload_report(self, request: UploadRequest) -> UploadResult:
"""Загрузка отчета"""
try:
# Получаем парсер для данного типа отчета
parser = get_parser(request.report_type)
# Сохраняем файл во временную директорию
suff = "." + str(request.file_name.split('.')[-1])
with tempfile.NamedTemporaryFile(delete=False, suffix=suff) as temp_file:
temp_file.write(request.file_content)
temp_file_path = temp_file.name
try:
# Парсим файл
parse_params = request.parse_params or {}
parse_result = parser.parse(temp_file_path, parse_params)
# Генерируем object_id
object_id = f"nin_excel_data_{request.report_type}"
# Удаляем старый объект, если он существует и хранилище доступно
if self.storage.object_exists(object_id):
self.storage.delete_object(object_id)
print(f"Старый объект удален: {object_id}")
# Сохраняем в хранилище
if self.storage.save_dataframe(parse_result, object_id):
return UploadResult(
success=True,
message="Отчет успешно загружен",
object_id=object_id
)
else:
return UploadResult(
success=False,
message="Ошибка при сохранении в хранилище. Возможно, MinIO недоступен."
)
finally:
# Удаляем временный файл
os.unlink(temp_file_path)
except Exception as e:
return UploadResult(
success=False,
message=f"Ошибка при обработке отчета: {str(e)}"
)
def get_data(self, request: DataRequest) -> DataResult:
"""Получение данных из отчета"""
try:
# Генерируем object_id
object_id = f"nin_excel_data_{request.report_type}"
# Проверяем существование объекта
if not self.storage.object_exists(object_id):
return DataResult(
success=False,
message=f"Отчет типа '{request.report_type}' не найден. Возможно, MinIO недоступен или отчет не был загружен."
)
# Загружаем данные из хранилища
loaded_data = self.storage.load_dataframe(object_id)
if loaded_data is None:
return DataResult(
success=False,
message="Ошибка при загрузке данных из хранилища. Возможно, MinIO недоступен."
)
# Получаем парсер
parser = get_parser(request.report_type)
# Устанавливаем данные в парсер для использования в геттерах
parser.df = loaded_data
print(f"🔍 DEBUG: ReportService.get_data - установлены данные в парсер {request.report_type}")
# Проверяем тип загруженных данных
if hasattr(loaded_data, 'shape'):
# Это DataFrame
print(f"🔍 DEBUG: DataFrame shape: {loaded_data.shape}")
print(f"🔍 DEBUG: DataFrame columns: {list(loaded_data.columns) if not loaded_data.empty else 'Empty'}")
elif isinstance(loaded_data, dict):
# Это словарь (для парсера ПМ)
print(f"🔍 DEBUG: Словарь с ключами: {list(loaded_data.keys())}")
else:
print(f"🔍 DEBUG: Неизвестный тип данных: {type(loaded_data)}")
# Получаем параметры запроса
get_params = request.get_params or {}
# Для svodka_ca определяем режим из данных или используем 'fact' по умолчанию
if request.report_type == 'svodka_ca':
# Извлекаем режим из DataFrame или используем 'fact' по умолчанию
if hasattr(parser, 'df') and parser.df is not None and not parser.df.empty:
modes_in_df = parser.df['mode'].unique() if 'mode' in parser.df.columns else ['fact']
# Используем первый найденный режим или 'fact' по умолчанию
default_mode = modes_in_df[0] if len(modes_in_df) > 0 else 'fact'
else:
default_mode = 'fact'
# Устанавливаем режим в параметры, если он не указан
if 'mode' not in get_params:
get_params['mode'] = default_mode
# Определяем имя геттера
if request.report_type == 'svodka_ca':
# Для svodka_ca используем геттер get_ca_data
getter_name = 'get_ca_data'
elif request.report_type == 'svodka_repair_ca':
# Для svodka_repair_ca используем геттер get_repair_data
getter_name = 'get_repair_data'
elif request.report_type == 'statuses_repair_ca':
# Для statuses_repair_ca используем геттер get_repair_statuses
getter_name = 'get_repair_statuses'
elif request.report_type == 'monitoring_tar':
# Для monitoring_tar определяем геттер по параметрам
if 'mode' in get_params:
# Если есть параметр mode, используем get_tar_data
getter_name = 'get_tar_data'
else:
# Если нет параметра mode, используем get_tar_full_data
getter_name = 'get_tar_full_data'
elif request.report_type == 'monitoring_fuel':
# Для monitoring_fuel определяем геттер из параметра mode
getter_name = get_params.pop("mode", None)
if not getter_name:
# Если режим не указан, берем первый доступный
available_getters = list(parser.getters.keys())
if available_getters:
getter_name = available_getters[0]
print(f"⚠️ Режим не указан, используем первый доступный: {getter_name}")
else:
return DataResult(
success=False,
message="Парсер не имеет доступных геттеров"
)
elif request.report_type == 'svodka_pm':
# Для svodka_pm определяем геттер из параметра mode
getter_name = get_params.pop("mode", None)
if not getter_name:
# Если режим не указан, берем первый доступный
available_getters = list(parser.getters.keys())
if available_getters:
getter_name = available_getters[0]
print(f"⚠️ Режим не указан, используем первый доступный: {getter_name}")
else:
return DataResult(
success=False,
message="Парсер не имеет доступных геттеров"
)
else:
# Для других парсеров определяем из параметра mode
getter_name = get_params.pop("mode", None)
if not getter_name:
# Если режим не указан, берем первый доступный
available_getters = list(parser.getters.keys())
if available_getters:
getter_name = available_getters[0]
print(f"⚠️ Режим не указан, используем первый доступный: {getter_name}")
else:
return DataResult(
success=False,
message="Парсер не имеет доступных геттеров"
)
# Получаем значение через указанный геттер
try:
value = parser.get_value(getter_name, get_params)
except ValueError as e:
return DataResult(
success=False,
message=f"Ошибка параметров: {str(e)}"
)
# Формируем результат
if value is not None:
if hasattr(value, 'to_dict'):
result_data = dict(value)
else:
result_data = {"value": value}
return DataResult(success=True, data=result_data)
else:
return DataResult(success=False, message="Значение не найдено")
except Exception as e:
return DataResult(
success=False,
message=f"Ошибка при получении данных: {str(e)}"
)