/
aastray
/
StudentPart
Обзор
Документация
Войти
/
aastray
/
StudentPart
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
service/src/processing/HTTPprocessing.py
265 строк
11 KB
aastray
Реализован функционал загрузки файлов и просмотра документов, удалены базовые эндпоинты, обновлена документация
10 янв 2026, 15:38
10 янв 2026, 15:38
4d47c55
Код
Авторство
О чём код?
""" Обработка HTTP запросов для цифрового двойника документооборота практиками. """ import base64 import uuid from pathlib import Path from typing import Dict, Any, Optional, List from sqlalchemy.ext.asyncio import AsyncSession from src.database.db import AsyncSessionLocal from src.services.template_loader import get_template_from_db, get_templates_directory from src.services.document_generator import generate_document async def get_template_file_base64(template_path: str) -> str: """ Читает файл шаблона и возвращает его в base64. Args: template_path: Путь к файлу шаблона (относительно корня проекта) Returns: str: Base64-кодированное содержимое файла """ project_root = Path(__file__).parent.parent.parent full_path = project_root / template_path if not full_path.exists(): raise FileNotFoundError(f"Файл шаблона не найден: {full_path}") with open(full_path, 'rb') as f: file_content = f.read() return base64.b64encode(file_content).decode('utf-8') def get_temp_storage_path() -> Path: """ Возвращает путь к временному хранилищу. Returns: Path: Путь к папке temp_storage/ """ project_root = Path(__file__).parent.parent.parent temp_storage = project_root / "temp_storage" temp_storage.mkdir(exist_ok=True) return temp_storage def sanitize_filename(name: str) -> str: """ Очищает имя файла от недопустимых символов. Args: name: Исходное имя Returns: str: Очищенное имя файла """ # Заменяем недопустимые символы на подчеркивания invalid_chars = '<>:"/\\|?*' for char in invalid_chars: name = name.replace(char, '_') # Убираем лишние пробелы и заменяем на подчеркивания name = '_'.join(name.split()) return name async def generate_all_documents(application_data: Dict[str, Any]) -> List[Dict[str, Any]]: """ Генерирует все 4 документа из анкеты студента. Args: application_data: Данные из анкеты студента Returns: List[Dict]: Список сгенерированных документов (с base64 и метаданными) """ documents = [] template_types = [ "договор", "индивидуальное_задание", "лист_учета_инструктажа", "направление" ] temp_storage = get_temp_storage_path() request_id = str(uuid.uuid4()) # Получаем имя студента для создания понятных имен файлов student_name = application_data.get('student_full_name', 'Студент') student_name_clean = sanitize_filename(student_name) async with AsyncSessionLocal() as session: for template_type in template_types: try: # Получаем шаблон из БД template = await get_template_from_db( db=session, template_type=template_type, practice_type=None # Универсальные шаблоны ) if not template: documents.append({ "type": template_type, "status": "error", "error": f"Шаблон не найден: {template_type}" }) continue # Получаем полный путь к шаблону project_root = Path(__file__).parent.parent.parent template_path = project_root / template.template_file_path if not template_path.exists(): documents.append({ "type": template_type, "status": "error", "error": f"Файл шаблона не найден: {template_path}" }) continue # Генерируем понятное имя файла template_name_clean = sanitize_filename(template.template_name) output_filename = f"{template_name_clean}_{student_name_clean}_{request_id[:8]}.docx" output_path = temp_storage / output_filename # Используем поля из БД для точной замены template_fields = template.student_fields + template.system_fields filled_doc_path = generate_document( template_path=str(template_path), application_data=application_data, output_path=str(output_path), template_fields=template_fields ) # Читаем сгенерированный документ и кодируем в base64 with open(filled_doc_path, 'rb') as f: file_content = f.read() file_base64 = base64.b64encode(file_content).decode('utf-8') # Относительный путь для доступа к файлу relative_path = f"temp_storage/{output_filename}" # URL для скачивания файла download_url = f"/download/{relative_path}" documents.append({ "type": template_type, "status": "success", "file_name": f"{template.template_name}.docx", "file_path": relative_path, "file_storage_path": str(filled_doc_path), "download_url": download_url, "file_base64": file_base64, "file_size": len(file_content) }) except Exception as e: documents.append({ "type": template_type, "status": "error", "error": f"Ошибка при генерации документа: {str(e)}" }) return documents async def HTTPprocessing(data: Dict[str, Any]) -> Dict[str, Any]: """ Обрабатывает HTTP запросы для цифрового двойника. Поддерживаемые операции: - get_template: получение шаблона документа по типу и виду практики - practice_application: обработка анкеты и генерация всех документов Args: data: Словарь с данными запроса Returns: Dict с результатом обработки """ try: # Определяем тип операции operation = data.get('operation') or data.get('url') # Обработка запроса на получение шаблона if operation == 'get_template' or 'template_type' in data: template_type = data.get('template_type') practice_type = data.get('practice_type') # Может быть None if not template_type: return { "status": "error", "error": "Не указан тип шаблона (template_type)" } # Получаем шаблон из БД async with AsyncSessionLocal() as session: template = await get_template_from_db( db=session, template_type=template_type, practice_type=practice_type ) if not template: return { "status": "error", "error": f"Шаблон не найден: тип={template_type}, практика={practice_type}" } # Получаем файл шаблона в base64 try: file_base64 = await get_template_file_base64(template.template_file_path) return { "status": "success", "template": { "id": template.id, "template_type": template.template_type, "practice_type": template.practice_type, "template_name": template.template_name, "student_fields": template.student_fields, "system_fields": template.system_fields, "file_base64": file_base64, "file_name": Path(template.template_file_path).name } } except Exception as e: return { "status": "error", "error": f"Ошибка при чтении файла шаблона: {str(e)}" } # Обработка анкеты на практику и генерация документов if operation == 'practice_application' or 'student_full_name' in data: # Генерируем все документы documents = await generate_all_documents(data) # Подсчитываем успешные и неуспешные генерации success_count = sum(1 for doc in documents if doc.get('status') == 'success') error_count = len(documents) - success_count return { "status": "success" if success_count > 0 else "error", "application_data": data, "documents": documents, "summary": { "total": len(documents), "success": success_count, "errors": error_count } } # Если операция не распознана, возвращаем ошибку return { "status": "error", "error": f"Неизвестная операция: {operation}. Доступные операции: get_template, practice_application" } except Exception as e: return { "status": "error", "error": f"Ошибка обработки данных: {str(e)}" }