485 lines
19 KiB
Python
485 lines
19 KiB
Python
import os
|
||
from django.conf import settings
|
||
|
||
from typing import Dict
|
||
|
||
from openpyxl import Workbook
|
||
|
||
from docxtpl import DocxTemplate
|
||
import jinja2
|
||
|
||
from docxcompose.composer import Composer
|
||
|
||
from docx import Document
|
||
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
|
||
# from docx.enum.style import WD_STYLE_TYPE
|
||
from docx.shared import Mm, Pt
|
||
# from django.http import FileResponse
|
||
|
||
from datetime import datetime, timedelta
|
||
import io
|
||
|
||
from .models import * # Для доступа к моделялям импортируем и их.
|
||
|
||
|
||
FONT_SIZE = 12
|
||
|
||
def short_date(date, offset=0):
|
||
return f'{date+timedelta(days=offset):%d.%m.%Y}'
|
||
|
||
def gender_text(gender):
|
||
return 'защитивший' if gender == 'муж.' else 'защитившая'
|
||
|
||
def rus_month(date):
|
||
MONTH=[
|
||
'',
|
||
'января',
|
||
'февраля',
|
||
'марта',
|
||
'апреля',
|
||
'мая',
|
||
'июня',
|
||
'июля',
|
||
'августа',
|
||
'сентября',
|
||
'октября',
|
||
'ноября',
|
||
'декабря',
|
||
]
|
||
return f'{date:%d} {MONTH[date.month]} {date:%Y}\xa0'
|
||
|
||
jinja_env = jinja2.Environment()
|
||
jinja_env.filters['tmpl_date'] = rus_month
|
||
jinja_env.filters['tmpl_short_date'] = short_date
|
||
jinja_env.filters['tmpl_gender'] = gender_text
|
||
|
||
|
||
|
||
|
||
|
||
def order_start(document, number, date, type):
|
||
|
||
document.core_properties.title = f'№ {number} от {rus_month(date)}'
|
||
document.core_properties.subject = type
|
||
|
||
section = document.sections[0]
|
||
section.left_margin = Mm(30)
|
||
section.right_margin = Mm(14)
|
||
section.top_margin = Mm(10)
|
||
section.bottom_margin = Mm(10)
|
||
|
||
# Меняем стиль абзаца по умолчанию:
|
||
# получаем объект стиля `Normal`
|
||
style = document.styles['Normal']
|
||
# # изменяем настройки шрифта
|
||
style.font.name = 'Times New Roman'
|
||
style.font.size = Pt(FONT_SIZE)
|
||
# # настраиваем красную строку абзаца
|
||
style.paragraph_format.first_line_indent = Mm(0)
|
||
style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY
|
||
style.paragraph_format.line_spacing = 1.0
|
||
style.paragraph_format.space_after = 0
|
||
|
||
|
||
def order_footer(document, list_proposers:Dict, list_approvers:Dict, rector:str):
|
||
|
||
p = document.add_paragraph(f'Ректор___________________________________________________{rector}')
|
||
p.paragraph_format.space_before = Pt(30)
|
||
p.paragraph_format.space_after = Pt(20)
|
||
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||
|
||
lines_number = max(len(list_approvers), len(list_proposers))
|
||
table = document.add_table(rows=lines_number * 2 + 1, cols=2)
|
||
|
||
table.cell(0, 0).text = 'Проект вносят:'
|
||
table.cell(0, 0).width = Mm(120)
|
||
table.cell(0, 0).paragraphs[0].paragraph_format.space_after = Pt(8)
|
||
table.cell(0, 1).text = 'Согласовано:'
|
||
|
||
number = 1
|
||
for key, value in list_approvers.items():
|
||
table.cell(number * 2 - 1, 1).text = key
|
||
table.cell(number * 2 - 1, 1).paragraphs[0].paragraph_format.space_after = Pt(2)
|
||
table.cell(number * 2, 1).text = f'_____________ {value}'
|
||
table.cell(number * 2, 1).paragraphs[0].paragraph_format.space_after = Pt(4)
|
||
number += 1
|
||
|
||
number = 1
|
||
for key, value in list_proposers.items():
|
||
table.cell(number * 2 - 1, 0).text = key
|
||
table.cell(number * 2 - 1, 0).paragraphs[0].paragraph_format.space_after = Pt(2)
|
||
table.cell(number * 2, 0).text = f'_____________ {value}'
|
||
table.cell(number * 2, 0).paragraphs[0].paragraph_format.space_after = Pt(4)
|
||
number += 1
|
||
|
||
# return document
|
||
|
||
|
||
def order_by_id(order_id):
|
||
'''Подготовка документа приказа по шаблону'''
|
||
order = Orders.objects.get(pk=order_id)
|
||
contracts = Orders.objects.get(pk=order_id).contracts.all().order_by('client')
|
||
buf = io.BytesIO()
|
||
text = '' if contracts.count()==1 else 'ы'
|
||
|
||
# document.add_paragraph(f'Основание: договор{text} на обучение')
|
||
|
||
|
||
filename = order.template.file
|
||
tpl = DocxTemplate(filename)
|
||
|
||
context = {
|
||
'order': order,
|
||
'contracts': contracts,
|
||
'plural': text,
|
||
|
||
}
|
||
tpl.render(context, jinja_env)
|
||
tpl.save(buf)
|
||
buf.seek(0)
|
||
|
||
return buf
|
||
|
||
|
||
|
||
def order_on_enrollment(object, contracts):
|
||
buf = io.BytesIO()
|
||
document = Document()
|
||
|
||
order_start(document, object.number, object.registered, object.type_order)
|
||
|
||
p = document.add_paragraph()
|
||
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||
p.paragraph_format.space_before = Mm(90)
|
||
run = p.add_run('О движении контингента слушателей ИДО')
|
||
run.font.bold = True
|
||
|
||
document.add_paragraph()
|
||
|
||
p = document.add_paragraph()
|
||
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||
run = p.add_run('ПРИКАЗЫВАЮ:')
|
||
run.font.bold = True
|
||
|
||
p = document.add_paragraph(
|
||
f'Зачислить с {rus_month(object.event_date)} в число слушателей ИДО ЮРГПУ(НПИ) по дополнительной профессиональной '
|
||
'программе профессиональной переподготовки «Машины и оборудование нефтяных и газовых промыслов». Срок '
|
||
'обучения – 521 час. Форма обучения заочная с применением электронного обучения и дистанционных '
|
||
'образовательных технологий.'
|
||
)
|
||
p.paragraph_format.first_line_indent = Mm(12.5)
|
||
p.paragraph_format.space_after = Pt(12)
|
||
|
||
table = document.add_table(rows=1, cols=2)
|
||
for number, item in enumerate(contracts):
|
||
cell = table.cell(number, 0)
|
||
cell.text = f'{number+1}. {item.client.surname} {item.client.name} {item.client.patronymic}'
|
||
p = cell.paragraphs[0]
|
||
p.paragraph_format.first_line_indent = Mm(10)
|
||
|
||
cell = table.cell(number, 1)
|
||
cell.text = f'{item.number}'
|
||
|
||
table.add_row()
|
||
|
||
text = '' if contracts.count()==1 else 'ы'
|
||
|
||
document.add_paragraph(f'Основание: договор{text} на обучение')
|
||
|
||
list_proposers = {
|
||
'Директор ИДО': 'И. А. Ревин',
|
||
}
|
||
|
||
list_approvers = {
|
||
'Проректор по ОД': 'Е. М. Дьяконов',
|
||
'Начальник ЮУ': 'Т. А. Кузьменко',
|
||
'Директор ДЭиФ': 'А. П. Игнатьева',
|
||
'Директор АД': 'Р. Г. Зайцев',
|
||
}
|
||
|
||
order_footer(document, list_proposers, list_approvers, object.structure.rector)
|
||
|
||
document.save(buf)
|
||
buf.seek(0)
|
||
|
||
return buf
|
||
|
||
|
||
def order_on_theme(order, contracts):
|
||
buf = io.BytesIO()
|
||
document = Document()
|
||
|
||
order_start(document, order.number, order.registered, order.type_order)
|
||
|
||
p = document.add_paragraph()
|
||
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||
p.paragraph_format.space_before = Mm(90)
|
||
run = p.add_run('Об утверждении тем выпускных работ для слушателей ИДО')
|
||
run.font.bold = True
|
||
|
||
document.add_paragraph()
|
||
p = document.add_paragraph('В соответствии с дополнительной профессиональной программой профессиональной'
|
||
' переподготовки «Машины и оборудование нефтяных и газовых промыслов»')
|
||
p.paragraph_format.first_line_indent = Mm(12.5)
|
||
|
||
p = document.add_paragraph()
|
||
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||
run = p.add_run('ПРИКАЗЫВАЮ:')
|
||
run.font.bold = True
|
||
|
||
document.add_paragraph('1. Утвердить темы выпускных квалификационных работ слушателям по дополнительной '
|
||
'профессиональной образовательной программе профессиональной переподготовки «Машины и оборудование '
|
||
'нефтяных и газовых промыслов»:')
|
||
|
||
for number, item in enumerate(contracts):
|
||
p = document.add_paragraph(f'1.{number+1}. {item.client.surname} {item.client.name} {item.client.patronymic}')
|
||
p.paragraph_format.space_before = Pt(8)
|
||
p.paragraph_format.first_line_indent = Mm(12.5)
|
||
p.paragraph_format.keep_with_next = True
|
||
|
||
p = document.add_paragraph(f'{item.degree_work.title}. Руководитель: {item.degree_work.adviser.surname} {item.degree_work.adviser.name} {item.degree_work.adviser.patronymic} - ')
|
||
if item.degree_work.adviser.degree:
|
||
p.add_run(f'{str(item.degree_work.adviser.degree).lower()}, ')
|
||
p.add_run(f'{str(item.degree_work.adviser.post).lower()} кафедры «{order.extract.department}».')
|
||
p.add_run(f' Тема предложена кафедрой «{order.extract.department}».')
|
||
|
||
text = f'Основание: протокол заседания кафедры «{order.extract.department}» №{order.extract.number} от {rus_month(order.extract.date)}'
|
||
|
||
list_proposers = {
|
||
'Директор ИДО': 'И. А. Ревин',
|
||
}
|
||
|
||
list_approvers = {
|
||
'Проректор по ОД': 'Е. М. Дьяконов',
|
||
'Директор АД': 'Р. Г. Зайцев',
|
||
}
|
||
|
||
order_footer(document, list_proposers, list_approvers, order.structure.rector)
|
||
|
||
document.save(buf)
|
||
buf.seek(0)
|
||
|
||
return buf
|
||
|
||
def extract_department_meeting (object, contracts):
|
||
|
||
buf = io.BytesIO()
|
||
document = Document()
|
||
|
||
section = document.sections[0]
|
||
section.left_margin = Mm(20)
|
||
section.right_margin = Mm(10)
|
||
section.top_margin = Mm(10)
|
||
section.bottom_margin = Mm(10)
|
||
# Меняем стиль абзаца по умолчанию:
|
||
# получаем объект стиля `Normal`
|
||
style = document.styles['Normal']
|
||
# # изменяем настройки шрифта
|
||
style.font.name = 'Times New Roman'
|
||
style.font.size = Pt(13)
|
||
# # настраиваем красную строку абзаца
|
||
# style.paragraph_format.first_line_indent = Mm(12.5)
|
||
style.paragraph_format.first_line_indent = Mm(12.5)
|
||
style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY
|
||
style.paragraph_format.line_spacing = 1.2
|
||
style.paragraph_format.space_after = 0
|
||
|
||
text = f'Выписка из протокола №{object.extract.number} заседания кафедры\n «{object.extract.department}» от {rus_month(object.extract.date)}'
|
||
p = document.add_paragraph(text)
|
||
p.paragraph_format.first_line_indent = Mm(0)
|
||
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||
|
||
document.add_paragraph('СЛУШАЛИ:')
|
||
document.add_paragraph(
|
||
'Доцента кафедры ТМТМО, кандидата технических наук Мирного Сергея Георгиевича о рассмотрении'
|
||
' тем выпускных квалификационных работ слушателям по дополнительному профессиональному '
|
||
'образованию по направлению профессиональной переподготовки «Машины и оборудование нефтяных и '
|
||
'газовых промыслов»')
|
||
document.add_paragraph('ПОСТАНОВИЛИ:')
|
||
document.add_paragraph('Ходатайствовать об утверждении тем выпускных квалификационных работ слушателям '
|
||
'по дополнительному профессиональному образованию по направлению '
|
||
'профессиональной переподготовки «Машины и оборудование нефтяных и '
|
||
'газовых промыслов»:')
|
||
for number, item in enumerate(contracts):
|
||
p = document.add_paragraph(f'{number+1}. {item.client.surname} {item.client.name} {item.client.patronymic}')
|
||
p.paragraph_format.keep_with_next = True
|
||
p = document.add_paragraph(f'{item.degree_work.title}. Руководитель: {item.degree_work.adviser.surname} {item.degree_work.adviser.name} {item.degree_work.adviser.patronymic} - ')
|
||
if item.degree_work.adviser.degree:
|
||
p.add_run(f'{str(item.degree_work.adviser.degree).lower()}, ')
|
||
p.add_run(f'{str(item.degree_work.adviser.post).lower()} кафедры «{object.extract.department}».')
|
||
|
||
document.add_paragraph()
|
||
p = document.add_paragraph(f'Доцент кафедры «ТМТМО», \nкандидат технических наук, доцент \t\t\t\t'
|
||
f'________________ {object.extract.speaker.name[:1]}. {object.extract.speaker.patronymic[:1]}. {object.extract.speaker.surname}')
|
||
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
|
||
p.paragraph_format.first_line_indent = Mm(0)
|
||
|
||
p = document.add_paragraph(f'Секретарь \t\t\t\t\t\t\t\t'
|
||
f'________________ {object.extract.secretary.name[:1]}. {object.extract.secretary.patronymic[:1]}. {object.extract.secretary.surname}')
|
||
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
|
||
p.paragraph_format.first_line_indent = Mm(0)
|
||
p.paragraph_format.space_before = Pt(10)
|
||
|
||
document.save(buf)
|
||
buf.seek(0)
|
||
|
||
return buf
|
||
|
||
|
||
def protocol_by_order(order_id):
|
||
'''Генерация протоколов защиты по айди приказа
|
||
'''
|
||
contracts = Orders.objects.get(pk=order_id).contracts.all().order_by('degree_work__protocol__number')
|
||
buf = io.BytesIO()
|
||
|
||
last = len(contracts) - 1
|
||
for n, item in enumerate(contracts):
|
||
doc2 = Document(protocol_by_id(item.id))
|
||
if n != last:
|
||
doc2.add_page_break()
|
||
if n == 0:
|
||
composer = Composer(doc2)
|
||
else:
|
||
composer.append(doc2)
|
||
|
||
composer.save(buf)
|
||
buf.seek(0)
|
||
|
||
return buf
|
||
|
||
|
||
def memo_by_order(acces_id):
|
||
'''Генерация служебки на пропуска по айди
|
||
'''
|
||
acces = Access_lists.objects.get(pk=acces_id)
|
||
contracts = Contracts.objects.filter(access_lists__pk = acces_id).order_by('client__surname', 'client__name', 'group__graduation_date', )
|
||
|
||
buf = io.BytesIO()
|
||
|
||
filename = acces.template.file
|
||
tpl = DocxTemplate(filename)
|
||
|
||
date = acces.registration_date
|
||
number = acces.number
|
||
context = {
|
||
'contracts': contracts,
|
||
'date': date,
|
||
'number': number,
|
||
}
|
||
tpl.render(context, jinja_env)
|
||
tpl.save(buf)
|
||
buf.seek(0)
|
||
|
||
return buf
|
||
|
||
|
||
def protocol_by_id(contract_id):
|
||
'''Генерация протокола защиты ВКР по айди договора
|
||
'''
|
||
contract = Contracts.objects.get(pk=contract_id)
|
||
questions = Protocols.objects.get(pk=contract.degree_work.protocol.pk).questions.all()
|
||
|
||
buf = io.BytesIO()
|
||
|
||
filename = contract.degree_work.protocol.template.file
|
||
tpl = DocxTemplate(filename)
|
||
|
||
dt = contract.degree_work.protocol.date_time
|
||
dte = dt + timedelta(minutes=25)
|
||
date_time = f'{rus_month(dt)}г. c {dt:%H} час. {dt:%M} мин. до {dte:%H} час. {dte:%M} мин.'
|
||
|
||
context = {
|
||
'contract': contract,
|
||
'title': contract.degree_work.title,
|
||
'date_time': date_time,
|
||
'questions': questions,
|
||
'fio_genitive': f'{contract.client.surname_cases.genitive} {contract.client.name_cases.genitive} {contract.client.patronymic_cases.genitive}',
|
||
'fio_dative': f'{contract.client.surname_cases.dative} {contract.client.name_cases.dative[:1]}. {contract.client.patronymic_cases.dative[:1]}.'
|
||
}
|
||
tpl.render(context)
|
||
tpl.save(buf)
|
||
buf.seek(0)
|
||
|
||
return buf
|
||
|
||
def filefor_registry(order_id):
|
||
'''генерация файла с данными для внесения в базу по дипломам'''
|
||
order = Orders.objects.get(pk=order_id)
|
||
contracts = Orders.objects.get(pk=order_id).contracts.all().order_by('client')
|
||
|
||
filename = os.path.join(settings.MEDIA_ROOT, 'templates\for_registry1.xlsx' )
|
||
wb = Workbook()
|
||
buf = io.BytesIO()
|
||
|
||
ws = wb.active
|
||
# ws.append(['Фамилия', 'Имя', 'Отчество', 'Дата рождения', 'СНИЛС', 'Диплом серия/номер', 'Начало обучения', 'Конец обучения'])
|
||
string_stub = ''
|
||
for item in contracts:
|
||
print(item.client.diploma)
|
||
ws.append([
|
||
'Диплом о профессиональной переподготовке',
|
||
'Оригинал',
|
||
'Нет',
|
||
'Нет',
|
||
'Нет',
|
||
'Нет',
|
||
'',
|
||
f'{item.end_date:%d.%m.%Y}',
|
||
# '05/07/2024',
|
||
'',
|
||
'Профессиональная переподготовка',
|
||
'Машины и оборудование нефтяных и газовых промыслов',
|
||
'Добыча, переработка, транспортировка нефти и газа',
|
||
'Бурение скважин, добыча нефти и газа',
|
||
'Образование',
|
||
'Высшее образование',
|
||
item.client.surname,
|
||
f'{item.client.diploma.series if item.client.diploma else string_stub}',
|
||
f'{item.client.diploma.number if item.client.diploma else string_stub}',
|
||
f'{item.start_date:%Y}',
|
||
f'{item.end_date:%Y}',
|
||
'521',
|
||
item.client.surname,
|
||
item.client.name,
|
||
item.client.patronymic,
|
||
f'{item.client.birthdate:%d.%m.%Y}',
|
||
f'{"Муж" if item.client.gender=="муж." else "Жен"}',
|
||
item.client.snils,
|
||
'Заочная',
|
||
'Платное обучение',
|
||
'в образовательной организации',
|
||
'643',
|
||
# f'{item.start_date:%d.%m.%Y}',
|
||
# f'{item.end_date:%d.%m.%Y}',
|
||
])
|
||
|
||
wb.save(buf)
|
||
buf.seek(0)
|
||
|
||
return buf
|
||
|
||
def gen_diploma(contract, form:bool):
|
||
|
||
buf = io.BytesIO()
|
||
document_name = 'templates\diploma_form.docx' if form else 'templates\diploma_supplement.docx'
|
||
filename = os.path.join(settings.MEDIA_ROOT, document_name)
|
||
tpl = DocxTemplate(filename)
|
||
|
||
context = {
|
||
'surname': contract.client.surname,
|
||
'name': contract.client.name,
|
||
'patronymic': contract.client.patronymic,
|
||
'diploma_number': contract.degree_work.diploma_number,
|
||
'registration_number': contract.degree_work.registration_number,
|
||
'start_date': rus_month(contract.start_date),
|
||
'end_date': rus_month(contract.end_date),
|
||
'protocol_date': f'{contract.degree_work.protocol.date_time:%d.%m.%Y}',
|
||
'protocol_number': contract.degree_work.protocol.number,
|
||
}
|
||
|
||
tpl.render(context)
|
||
tpl.save(buf)
|
||
buf.seek(0)
|
||
|
||
return buf
|