/
aastray
/
StudentPart
Обзор
Документация
Войти
/
aastray
/
StudentPart
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
service/src/services/document_generator.py
191 строка
8 KB
aastray
Реализован функционал загрузки файлов и просмотра документов, удалены базовые эндпоинты, обновлена документация
10 янв 2026, 15:38
10 янв 2026, 15:38
4d47c55
Код
Авторство
О чём код?
""" Сервис для генерации заполненных документов из шаблонов. Заполняет шаблоны данными из анкеты студента используя python-docx-template. """ from pathlib import Path from typing import Dict, Any, Optional, List from docxtpl import DocxTemplate from src.utils.docx_helper import ( generate_signature_from_full_name, generate_name_short_format, generate_name_genitive, generate_name_dative ) def map_application_data_to_template_fields(application_data: Dict[str, Any]) -> Dict[str, Any]: """ Создаёт маппинг данных из анкеты на переменные шаблона. Соответствует переменным из FOR_DOCX_INFO.md. Args: application_data: Данные из анкеты студента Returns: Dict[str, Any]: Маппинг значений для замены в шаблоне """ context = {} # Данные студента student_full_name = application_data.get('student_full_name', '') if student_full_name: context['student_full_name'] = student_full_name context['student_name_short'] = generate_signature_from_full_name(student_full_name) context['student_full_name_dative'] = generate_name_dative(student_full_name) student_group = application_data.get('group') or application_data.get('student_group', '') if student_group: context['student_group'] = student_group student_course = application_data.get('course') or application_data.get('student_course') if student_course: context['student_course'] = str(student_course) # Данные о практике practice_start_date = application_data.get('practice_start_date') or application_data.get('date_start', '') practice_end_date = application_data.get('practice_end_date') or application_data.get('date_end', '') if practice_start_date and practice_end_date: context['practice_dates'] = f"{practice_start_date} – {practice_end_date}" practice_city = application_data.get('practice_city', '') if practice_city: context['practice_city'] = practice_city practice_department = application_data.get('practice_department', '') if practice_department: context['practice_department'] = practice_department # Данные организации org_name_full = application_data.get('organization_name') or application_data.get('org_name_full', '') if org_name_full: context['org_name_full'] = org_name_full org_name_short = application_data.get('organization_name_short') or application_data.get('org_name_short', '') if org_name_short: context['org_name_short'] = org_name_short director_full_name = application_data.get('director_full_name') or application_data.get('director_name', '') if director_full_name: context['director_name_genitive'] = generate_name_genitive(director_full_name) context['director_name_short'] = generate_name_short_format(director_full_name) org_address_physical = application_data.get('organization_address') or application_data.get('org_address_physical', '') if org_address_physical: context['org_address_physical'] = org_address_physical org_address_legal = application_data.get('organization_legal_address') or application_data.get('org_address_legal', '') if org_address_legal: context['org_address_legal'] = org_address_legal org_inn = application_data.get('organization_inn') or application_data.get('org_inn', '') if org_inn: context['org_inn'] = str(org_inn) org_kpp = application_data.get('organization_kpp') or application_data.get('org_kpp', '') if org_kpp: context['org_kpp'] = str(org_kpp) org_ogrn = application_data.get('organization_ogrn') or application_data.get('org_ogrn', '') if org_ogrn: context['org_ogrn'] = str(org_ogrn) org_phone = application_data.get('organization_phone') or application_data.get('org_phone', '') if org_phone: context['org_phone'] = org_phone org_email = application_data.get('organization_email') or application_data.get('org_email', '') if org_email: context['org_email'] = org_email org_premises = application_data.get('org_premises', '') if org_premises: context['org_premises'] = org_premises # Руководитель практики от организации org_supervisor_full_name = application_data.get('organization_supervisor_full_name') or application_data.get('org_supervisor_full_name', '') if org_supervisor_full_name: context['org_supervisor_full_name'] = org_supervisor_full_name context['org_supervisor_short'] = generate_signature_from_full_name(org_supervisor_full_name) # Руководитель от университета (ТИУ) - может быть передан извне university_supervisor_full_name = application_data.get('university_supervisor_full_name', '') if university_supervisor_full_name: context['university_supervisor_full_name'] = university_supervisor_full_name # Доверенность (если есть) proxy_number = application_data.get('proxy_number', '') if proxy_number: context['proxy_number'] = proxy_number proxy_date = application_data.get('proxy_date', '') if proxy_date: context['proxy_date'] = proxy_date return context def fill_template_with_data( template_path: str, application_data: Dict[str, Any], fill_green_fields: bool = True, template_fields: Optional[List[Dict[str, str]]] = None ) -> DocxTemplate: """ Заполняет шаблон документа данными из анкеты используя python-docx-template. Args: template_path: Путь к файлу шаблона application_data: Данные из анкеты студента fill_green_fields: Если True, заполняет некоторые системные поля (если они есть в данных) template_fields: Список полей из БД (опционально, не используется для python-docx-template) Returns: DocxTemplate: Заполненный шаблон (нужно вызвать .save() для сохранения) """ # Загружаем шаблон через python-docx-template doc = DocxTemplate(template_path) # Создаём контекст с данными для шаблона context = map_application_data_to_template_fields(application_data) # Рендерим шаблон с данными doc.render(context) return doc def generate_document( template_path: str, application_data: Dict[str, Any], output_path: Optional[str] = None, template_fields: Optional[List[Dict[str, str]]] = None ) -> Path: """ Генерирует заполненный документ из шаблона используя python-docx-template. Args: template_path: Путь к файлу шаблона application_data: Данные из анкеты студента output_path: Путь для сохранения заполненного документа (опционально) template_fields: Список полей из БД (опционально, не используется для python-docx-template) Returns: Path: Путь к сохранённому документу """ # Заполняем шаблон filled_doc = fill_template_with_data( template_path, application_data, fill_green_fields=True, template_fields=template_fields ) # Определяем путь для сохранения if output_path is None: template_file = Path(template_path) output_path = template_file.parent / f"filled_{template_file.name}" # Сохраняем документ filled_doc.save(str(output_path)) return Path(output_path)