Browse Source

Gerador de minuta em DOCx

pull/159/head
Sesostris Vieira 3 years ago
parent
commit
69a058913c
  1. 23
      sigi/apps/convenios/migrations/0022_remove_projeto_texto_minuta_projeto_modelo_minuta.py
  2. 11
      sigi/apps/convenios/models.py
  3. 2
      sigi/apps/eventos/admin.py
  4. 19
      sigi/apps/eventos/migrations/0020_anexo_convite.py
  5. 3
      sigi/apps/eventos/models.py
  6. 2
      sigi/apps/eventos/templates/eventos/convida_casa.html
  7. 18
      sigi/apps/eventos/templates/eventos/evento.html
  8. 77
      sigi/apps/eventos/templates/eventos/minuta_pdf.html
  9. 45
      sigi/apps/eventos/views.py

23
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:<ul><li>{{ casa.nome }} para o nome da Casa Legislativa / órgão</li><li>{{ casa.municipio.uf.sigla }} para a sigla da UF da Casa legislativa</li><li>{{ presidente.nome }} para o nome do presidente</li><li>{{ contato.nome }} para o nome do contato Interlegis</li></ul>', upload_to='convenios/minutas/', validators=[django.core.validators.FileExtensionValidator], verbose_name='Modelo de minuta'),
),
]

11
sigi/apps/convenios/models.py

@ -4,6 +4,7 @@ from datetime import datetime, date
from django.db import models from django.db import models
from django.db.models import Q, fields from django.db.models import Q, fields
from django.core.mail import send_mail from django.core.mail import send_mail
from django.core.validators import FileExtensionValidator
from django.urls import reverse from django.urls import reverse
from django.utils.formats import date_format from django.utils.formats import date_format
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
@ -27,8 +28,14 @@ class Projeto(models.Model):
texto_oficio = HTMLField( texto_oficio = HTMLField(
_("texto do ofício"), blank=True, help_text=MARKUP_HELP _("texto do ofício"), blank=True, help_text=MARKUP_HELP
) )
texto_minuta = HTMLField( modelo_minuta = models.FileField(
_("texto da minuta"), blank=True, help_text=MARKUP_HELP _("Modelo de minuta"),
blank=True,
help_text=MARKUP_HELP,
upload_to="convenios/minutas/",
validators=[
FileExtensionValidator,
],
) )
def __str__(self): def __str__(self):

2
sigi/apps/eventos/admin.py

@ -122,7 +122,7 @@ class ModuloInline(admin.StackedInline):
class AnexoInline(admin.StackedInline): class AnexoInline(admin.StackedInline):
model = Anexo model = Anexo
exclude = ("data_pub",) exclude = ("data_pub", "convite")
@admin.register(Evento) @admin.register(Evento)

19
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'),
),
]

3
sigi/apps/eventos/models.py

@ -319,6 +319,9 @@ class Anexo(models.Model):
data_pub = models.DateTimeField( data_pub = models.DateTimeField(
_("data da publicação do anexo"), default=datetime.now _("data da publicação do anexo"), default=datetime.now
) )
convite = models.ForeignKey(
Convite, blank=True, null=True, on_delete=models.SET_NULL
)
class Meta: class Meta:
ordering = ("-data_pub",) ordering = ("-data_pub",)

2
sigi/apps/eventos/templates/eventos/convida_casa.html

@ -69,7 +69,7 @@
</button> </button>
{% for proj in projetos %} {% for proj in projetos %}
<button class="btn waves-effect waves-light" type="submit" name="save" value="{{ proj.id }}"> <button class="btn waves-effect waves-light" type="submit" name="save" value="{{ proj.id }}">
{% blocktrans with sigla=proj.sigla %}Gerar minuta de {{ sigla}}{% endblocktrans %} {% blocktrans with sigla=proj.sigla %}Salvar e gerar minuta de {{ sigla}}{% endblocktrans %}
<i class="material-icons right">picture_as_pdf</i> <i class="material-icons right">picture_as_pdf</i>
</button> </button>
{% endfor %} {% endfor %}

18
sigi/apps/eventos/templates/eventos/evento.html

@ -96,7 +96,15 @@
{% for convite in evento.convite_set.all %} {% for convite in evento.convite_set.all %}
<tr> <tr>
{% for field_name in convite_fields %} {% for field_name in convite_fields %}
<td>{{ convite|field_value:field_name }}</td> <td>
{% if forloop.first %}
<a href="{% url 'eventos-evento-convida' evento.id convite.casa_id %}">
{{ convite|field_value:field_name }}
</a>
{% else %}
{{ convite|field_value:field_name }}
{% endif %}
</td>
{% endfor %} {% endfor %}
</tr> </tr>
{% endfor %} {% endfor %}
@ -135,7 +143,13 @@
<td>{{ anexo.data_pub|date:"SHORT_DATE_FORMAT" }}</td> <td>{{ anexo.data_pub|date:"SHORT_DATE_FORMAT" }}</td>
<td> <td>
<a href="{{ anexo.arquivo.url }}" target="_blank"> <a href="{{ anexo.arquivo.url }}" target="_blank">
<i class="material-icons">picture_as_pdf</i> <i class="material-icons">
{% if 'pdf' in anexo.arquivo.path %}
picture_as_pdf
{% else %}
file_download
{% endif %}
</i>
</a> </a>
</td> </td>
</tr> </tr>

77
sigi/apps/eventos/templates/eventos/minuta_pdf.html

@ -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 %}
<img src="{% static 'img/logo-senado.png' %}">
<p class="header-title">SENADO FEDERAL</p>
<p class="header-subtitle">Instituto Legislativo Brasileiro - ILB</p>
<p class="header-subtitle">Programa Interlegis</p>
{% endblock %}
{% block main_content %}
<div class="content">
{% block text_body %}{% endblock %}
</div>
{% endblock %}
{% block footer %}
<img class="barra" src="{% static 'img/brasil-barra.jpg' %}"/>
<p>Instituto Legislativo Brasileiro - ILB - Av. N2 - Bloco 12 - CEP 70165-900 – Brasília DF</p>
<p>Telefone: +55 (61) 3303-2599 – interlegis@senado.leg.br – www.interlegis.leg.br</p>
<p class="strong">MINUTA-PADRÃO aprovada pela Diretoria-Geral do Senado Federal em 01/setembro/2021, conforme processo 00200.006818/2021-12.</p>
{% endblock %}

45
sigi/apps/eventos/views.py

@ -7,10 +7,12 @@ from django.contrib.auth.decorators import login_required
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import redirect, render, get_object_or_404 from django.shortcuts import redirect, render, get_object_or_404
from django.template import Template, Context from django.template import Template, Context
from django.template.exceptions import TemplateSyntaxError
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import to_locale, get_language, gettext as _ from django.utils.translation import to_locale, get_language, gettext as _
from django.urls import reverse from django.urls import reverse
from django_weasyprint.utils import django_url_fetcher from django_weasyprint.utils import django_url_fetcher
from docx import Document
from weasyprint import HTML from weasyprint import HTML
from sigi.apps.casas.models import Funcionario, Orgao, Presidente from sigi.apps.casas.models import Funcionario, Orgao, Presidente
from sigi.apps.convenios.models import Projeto 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) evento = get_object_or_404(Evento, id=evento_id)
casa = get_object_or_404(Orgao, id=casa_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(): if evento.convite_set.filter(casa=casa).exists():
convite = evento.convite_set.get(casa=casa) 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", "") proj_id = request.POST.get("save", "")
if proj_id: if proj_id:
convite.anexo_set.all().delete()
query_str = "" query_str = ""
projeto = get_object_or_404(Projeto, id=proj_id) projeto = get_object_or_404(Projeto, id=proj_id)
if projeto.texto_oficio: if projeto.texto_oficio:
@ -162,17 +165,37 @@ def convida_casa(request, evento_id, casa_id):
oficio.evento = evento oficio.evento = evento
oficio.save() oficio.save()
query_str += f"anexo_id={oficio.id}&" query_str += f"anexo_id={oficio.id}&"
if projeto.texto_minuta: if projeto.modelo_minuta:
minuta = gerar_anexo( doc = Document(projeto.modelo_minuta.path)
casa, doc_context = Context(
presidente, {
contato, "evento": evento,
path=request.build_absolute_uri("/"), "casa": casa,
nome=f"Minuta de {projeto.sigla}", "presidente": presidente,
modelo="minuta_pdf.html", "contato": contato,
texto=projeto.texto_minuta, "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() minuta.save()
query_str += f"anexo_id={minuta.id}" query_str += f"anexo_id={minuta.id}"

Loading…
Cancel
Save