From 69a058913c79ea7a05412e92c03f4210bed51415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ses=C3=B3stris=20Vieira?= Date: Thu, 5 May 2022 15:38:33 -0300 Subject: [PATCH] Gerador de minuta em DOCx --- ...jeto_texto_minuta_projeto_modelo_minuta.py | 23 ++++++ sigi/apps/convenios/models.py | 11 ++- sigi/apps/eventos/admin.py | 2 +- .../eventos/migrations/0020_anexo_convite.py | 19 +++++ sigi/apps/eventos/models.py | 3 + .../templates/eventos/convida_casa.html | 2 +- .../eventos/templates/eventos/evento.html | 18 ++++- .../eventos/templates/eventos/minuta_pdf.html | 77 ------------------- sigi/apps/eventos/views.py | 45 ++++++++--- 9 files changed, 106 insertions(+), 94 deletions(-) create mode 100644 sigi/apps/convenios/migrations/0022_remove_projeto_texto_minuta_projeto_modelo_minuta.py create mode 100644 sigi/apps/eventos/migrations/0020_anexo_convite.py delete mode 100644 sigi/apps/eventos/templates/eventos/minuta_pdf.html diff --git a/sigi/apps/convenios/migrations/0022_remove_projeto_texto_minuta_projeto_modelo_minuta.py b/sigi/apps/convenios/migrations/0022_remove_projeto_texto_minuta_projeto_modelo_minuta.py new file mode 100644 index 0000000..6dfea4c --- /dev/null +++ b/sigi/apps/convenios/migrations/0022_remove_projeto_texto_minuta_projeto_modelo_minuta.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.4 on 2022-05-05 13:17 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('convenios', '0021_projeto_texto_minuta_projeto_texto_oficio'), + ] + + operations = [ + migrations.RemoveField( + model_name='projeto', + name='texto_minuta', + ), + migrations.AddField( + model_name='projeto', + name='modelo_minuta', + field=models.FileField(blank=True, help_text='Use as seguintes marcações:', upload_to='convenios/minutas/', validators=[django.core.validators.FileExtensionValidator], verbose_name='Modelo de minuta'), + ), + ] diff --git a/sigi/apps/convenios/models.py b/sigi/apps/convenios/models.py index cc60452..a2f3313 100644 --- a/sigi/apps/convenios/models.py +++ b/sigi/apps/convenios/models.py @@ -4,6 +4,7 @@ from datetime import datetime, date from django.db import models from django.db.models import Q, fields from django.core.mail import send_mail +from django.core.validators import FileExtensionValidator from django.urls import reverse from django.utils.formats import date_format from django.utils.translation import gettext as _ @@ -27,8 +28,14 @@ class Projeto(models.Model): texto_oficio = HTMLField( _("texto do ofício"), blank=True, help_text=MARKUP_HELP ) - texto_minuta = HTMLField( - _("texto da minuta"), blank=True, help_text=MARKUP_HELP + modelo_minuta = models.FileField( + _("Modelo de minuta"), + blank=True, + help_text=MARKUP_HELP, + upload_to="convenios/minutas/", + validators=[ + FileExtensionValidator, + ], ) def __str__(self): diff --git a/sigi/apps/eventos/admin.py b/sigi/apps/eventos/admin.py index 4fce631..08a2af6 100644 --- a/sigi/apps/eventos/admin.py +++ b/sigi/apps/eventos/admin.py @@ -122,7 +122,7 @@ class ModuloInline(admin.StackedInline): class AnexoInline(admin.StackedInline): model = Anexo - exclude = ("data_pub",) + exclude = ("data_pub", "convite") @admin.register(Evento) diff --git a/sigi/apps/eventos/migrations/0020_anexo_convite.py b/sigi/apps/eventos/migrations/0020_anexo_convite.py new file mode 100644 index 0000000..0d8bbce --- /dev/null +++ b/sigi/apps/eventos/migrations/0020_anexo_convite.py @@ -0,0 +1,19 @@ +# Generated by Django 4.0.4 on 2022-05-05 14:35 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('eventos', '0019_alter_evento_status'), + ] + + operations = [ + migrations.AddField( + model_name='anexo', + name='convite', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='eventos.convite'), + ), + ] diff --git a/sigi/apps/eventos/models.py b/sigi/apps/eventos/models.py index 9f980db..23cacee 100644 --- a/sigi/apps/eventos/models.py +++ b/sigi/apps/eventos/models.py @@ -319,6 +319,9 @@ class Anexo(models.Model): data_pub = models.DateTimeField( _("data da publicação do anexo"), default=datetime.now ) + convite = models.ForeignKey( + Convite, blank=True, null=True, on_delete=models.SET_NULL + ) class Meta: ordering = ("-data_pub",) diff --git a/sigi/apps/eventos/templates/eventos/convida_casa.html b/sigi/apps/eventos/templates/eventos/convida_casa.html index 5c290a1..077c737 100644 --- a/sigi/apps/eventos/templates/eventos/convida_casa.html +++ b/sigi/apps/eventos/templates/eventos/convida_casa.html @@ -69,7 +69,7 @@ {% for proj in projetos %} {% endfor %} diff --git a/sigi/apps/eventos/templates/eventos/evento.html b/sigi/apps/eventos/templates/eventos/evento.html index 04e852d..c767349 100644 --- a/sigi/apps/eventos/templates/eventos/evento.html +++ b/sigi/apps/eventos/templates/eventos/evento.html @@ -96,7 +96,15 @@ {% for convite in evento.convite_set.all %} {% for field_name in convite_fields %} - {{ convite|field_value:field_name }} + + {% if forloop.first %} + + {{ convite|field_value:field_name }} + + {% else %} + {{ convite|field_value:field_name }} + {% endif %} + {% endfor %} {% endfor %} @@ -135,7 +143,13 @@ {{ anexo.data_pub|date:"SHORT_DATE_FORMAT" }} - picture_as_pdf + + {% if 'pdf' in anexo.arquivo.path %} + picture_as_pdf + {% else %} + file_download + {% endif %} + diff --git a/sigi/apps/eventos/templates/eventos/minuta_pdf.html b/sigi/apps/eventos/templates/eventos/minuta_pdf.html deleted file mode 100644 index 7561dcd..0000000 --- a/sigi/apps/eventos/templates/eventos/minuta_pdf.html +++ /dev/null @@ -1,77 +0,0 @@ -{% extends 'pdf/base_report.html' %} -{% load i18n static %} - -{% block page_margin %}4cm 2cm{% endblock page_margin %} - -{% block page-header-settings %} -@top-center { content: element(header);} -{% endblock %} - -{% block page-footer-settings %} -@bottom-center { content: element(footer); } -{% endblock %} - - -{% block extra_style %} - h1 {font-size: 1.2em;} - h2 {font-size: 1.1em;} - h3,h4,h5,h6 {font-size: 1em;} - - header { - font-size: 1em; - text-align: center; - } - - header p { - margin: 0 0 5px 0; - } - - .strong { - font-weight: bold; - } - - .header-title { - font-weight: bold; - font-size: 1.2em; - } - - .header-subtitle { - font-weight: bold; - font-size: 1em; - } - - .content { - font-size: 1.2em; - line-height: 1.4em; - padding-bottom: 5px; - } - - footer { - width: 100%; - text-align: center; - } - - .barra { - height: 15px; - } -{% endblock %} - -{% block header %} - -

SENADO FEDERAL

-

Instituto Legislativo Brasileiro - ILB

-

Programa Interlegis

-{% endblock %} - -{% block main_content %} -
- {% block text_body %}{% endblock %} -
-{% endblock %} - -{% block footer %} - -

Instituto Legislativo Brasileiro - ILB - Av. N2 - Bloco 12 - CEP 70165-900 – Brasília DF

-

Telefone: +55 (61) 3303-2599 – interlegis@senado.leg.br – www.interlegis.leg.br

-

MINUTA-PADRÃO aprovada pela Diretoria-Geral do Senado Federal em 01/setembro/2021, conforme processo 00200.006818/2021-12.

-{% endblock %} \ No newline at end of file diff --git a/sigi/apps/eventos/views.py b/sigi/apps/eventos/views.py index 0365343..422a87e 100644 --- a/sigi/apps/eventos/views.py +++ b/sigi/apps/eventos/views.py @@ -7,10 +7,12 @@ from django.contrib.auth.decorators import login_required from django.http import HttpResponse from django.shortcuts import redirect, render, get_object_or_404 from django.template import Template, Context +from django.template.exceptions import TemplateSyntaxError from django.utils.text import slugify from django.utils.translation import to_locale, get_language, gettext as _ from django.urls import reverse from django_weasyprint.utils import django_url_fetcher +from docx import Document from weasyprint import HTML from sigi.apps.casas.models import Funcionario, Orgao, Presidente from sigi.apps.convenios.models import Projeto @@ -102,7 +104,7 @@ def convida_casa(request, evento_id, casa_id): evento = get_object_or_404(Evento, id=evento_id) casa = get_object_or_404(Orgao, id=casa_id) - projetos = Projeto.objects.exclude(texto_minuta="") + projetos = Projeto.objects.exclude(modelo_minuta="") if evento.convite_set.filter(casa=casa).exists(): convite = evento.convite_set.get(casa=casa) @@ -147,6 +149,7 @@ def convida_casa(request, evento_id, casa_id): proj_id = request.POST.get("save", "") if proj_id: + convite.anexo_set.all().delete() query_str = "" projeto = get_object_or_404(Projeto, id=proj_id) if projeto.texto_oficio: @@ -162,17 +165,37 @@ def convida_casa(request, evento_id, casa_id): oficio.evento = evento oficio.save() query_str += f"anexo_id={oficio.id}&" - if projeto.texto_minuta: - minuta = gerar_anexo( - casa, - presidente, - contato, - path=request.build_absolute_uri("/"), - nome=f"Minuta de {projeto.sigla}", - modelo="minuta_pdf.html", - texto=projeto.texto_minuta, + if projeto.modelo_minuta: + doc = Document(projeto.modelo_minuta.path) + doc_context = Context( + { + "evento": evento, + "casa": casa, + "presidente": presidente, + "contato": contato, + "data": datetime.date.today(), + "doravante": casa.tipo.nome.split(" ")[0], + } ) - minuta.evento = evento + for paragrafo in doc.paragraphs: + run_final = None + for run in paragrafo.runs: + if run_final is None: + run_final = run + else: + run_final.text += run.text + run.text = "" + try: + run_final.text = Template( + run_final.text + ).render(doc_context) + run_final = None + except TemplateSyntaxError: + pass + nome = f"Minuta de {projeto.sigla} da {casa.nome}"[:70] + minuta = Anexo(descricao=nome, evento=evento) + minuta.arquivo.name = slugify(nome) + ".docx" + doc.save(minuta.arquivo.path) minuta.save() query_str += f"anexo_id={minuta.id}"