147 lines
6.1 KiB
Python
147 lines
6.1 KiB
Python
"""
|
||
Сервисы (бизнес-логика)
|
||
"""
|
||
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 {}
|
||
df = 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(df, 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 недоступен или отчет не был загружен."
|
||
)
|
||
|
||
# Загружаем DataFrame из хранилища
|
||
df = self.storage.load_dataframe(object_id)
|
||
if df is None:
|
||
return DataResult(
|
||
success=False,
|
||
message="Ошибка при загрузке данных из хранилища. Возможно, MinIO недоступен."
|
||
)
|
||
|
||
# Получаем парсер
|
||
parser = get_parser(request.report_type)
|
||
|
||
# Устанавливаем DataFrame в парсер для использования в геттерах
|
||
parser.df = df
|
||
|
||
# Получаем параметры запроса
|
||
get_params = request.get_params or {}
|
||
|
||
# Определяем имя геттера из параметра 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)}"
|
||
)
|