Browse Source

Merge branch 'stable/2.2' of https://github.com/interlegis/sigi into new_sigi

new_sigi^2
Lude Ribeiro 3 years ago
parent
commit
0722046345
  1. 1
      requirements/requirements.txt
  2. 27
      sigi/apps/eventos/admin.py
  3. 32
      sigi/apps/eventos/forms.py
  4. 30
      sigi/apps/eventos/migrations/0013_modelodeclaracao.py
  5. 43
      sigi/apps/eventos/models.py
  6. 10
      sigi/apps/eventos/templates/admin/eventos/evento/change_form.html
  7. 0
      sigi/apps/eventos/templates/admin/eventos/evento/change_list.html
  8. 24
      sigi/apps/eventos/templates/eventos/declaracao_pdf.html
  9. 25
      sigi/apps/eventos/templates/eventos/seleciona_modelo.html
  10. 3
      sigi/apps/eventos/urls.py
  11. 54
      sigi/apps/eventos/views.py
  12. 2
      sigi/apps/home/templatetags/menu_conf.yaml
  13. 10
      sigi/settings/base.py
  14. 14
      sigi/shortcuts.py
  15. 1
      sigi/urls.py
  16. 14
      templates/base_report.html

1
requirements/requirements.txt

@ -21,3 +21,4 @@ requests==2.8.1
six==1.10.0 six==1.10.0
djangorestframework==2.4.8 djangorestframework==2.4.8
django-ipware==1.1.6 django-ipware==1.1.6
django-tinymce==2.6.0

27
sigi/apps/eventos/admin.py

@ -23,28 +23,9 @@ from django.contrib import admin
from django.db import models from django.db import models
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from sigi.apps.eventos.models import Modulo, TipoEvento, Funcao, Evento, Equipe, Convite from sigi.apps.eventos.models import ModeloDeclaracao, Modulo, TipoEvento, Funcao, Evento, Equipe, Convite
from sigi.apps.eventos.views import adicionar_eventos_carrinho from sigi.apps.eventos.views import adicionar_eventos_carrinho
from sigi.apps.eventos.forms import EventoAdminForm
class EventoAdminForm(forms.ModelForm):
class Meta:
model = Evento
fields = ('tipo_evento', 'nome', 'descricao', 'virtual', 'solicitante',
'data_inicio', 'data_termino', 'carga_horaria',
'casa_anfitria', 'municipio', 'local', 'publico_alvo',
'total_participantes', 'status', 'data_cancelamento',
'motivo_cancelamento', )
def clean(self):
cleaned_data = super(EventoAdminForm, self).clean()
data_inicio = cleaned_data.get("data_inicio")
data_termino = cleaned_data.get("data_termino")
if data_inicio > data_termino:
raise forms.ValidationError(
_(u"Data término deve ser posterior à data inicio"),
code="invalid_period"
)
@admin.register(TipoEvento) @admin.register(TipoEvento)
class TipoEventAdmin(admin.ModelAdmin): class TipoEventAdmin(admin.ModelAdmin):
@ -55,6 +36,10 @@ class FuncaoAdmin(admin.ModelAdmin):
list_display = ('nome', 'descricao',) list_display = ('nome', 'descricao',)
search_fields = ('nome', 'descricao',) search_fields = ('nome', 'descricao',)
@admin.register(ModeloDeclaracao)
class ModeloDeclaracaoAdmin(admin.ModelAdmin):
list_display = ('nome', 'formato')
class EquipeInline(admin.TabularInline): class EquipeInline(admin.TabularInline):
model = Equipe model = Equipe

32
sigi/apps/eventos/forms.py

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
from django import forms
from django.utils.translation import ugettext as _
from sigi.apps.eventos.models import ModeloDeclaracao, Evento
class EventoAdminForm(forms.ModelForm):
class Meta:
model = Evento
fields = ('tipo_evento', 'nome', 'descricao', 'virtual', 'solicitante',
'data_inicio', 'data_termino', 'carga_horaria',
'casa_anfitria', 'municipio', 'local', 'publico_alvo',
'total_participantes', 'status', 'data_cancelamento',
'motivo_cancelamento', )
def clean(self):
cleaned_data = super(EventoAdminForm, self).clean()
data_inicio = cleaned_data.get("data_inicio")
data_termino = cleaned_data.get("data_termino")
if data_inicio > data_termino:
raise forms.ValidationError(
_(u"Data término deve ser posterior à data inicio"),
code="invalid_period"
)
class SelecionaModeloForm(forms.Form):
modelo = forms.ModelChoiceField(
queryset=ModeloDeclaracao.objects.all(),
required=True,
label=_(u"Modelo de declaração"),
)

30
sigi/apps/eventos/migrations/0013_modelodeclaracao.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import tinymce.models
class Migration(migrations.Migration):
dependencies = [
('eventos', '0012_auto_20211117_0657'),
]
operations = [
migrations.CreateModel(
name='ModeloDeclaracao',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('nome', models.CharField(max_length=100, verbose_name='Nome do modelo')),
('formato', models.CharField(default=b'A4 portrait', max_length=30, verbose_name='Formato da p\xe1gina', choices=[(b'A4 portrait', 'A4 retrato'), (b'A4 landscape', 'A4 paisagem'), (b'letter portrait', 'Carta retrato'), (b'letter landscape', 'Carta paisagem')])),
('margem', models.PositiveIntegerField(default=4, help_text='Margem da p\xe1gina em cent\xedmetros', verbose_name='Margem')),
('texto', tinymce.models.HTMLField(help_text='Use as seguintes marca\xe7\xf5es:<ul><li>{{ casa }} para o nome da Casa Legislativa / \xf3rg\xe3o</li><li>{{ nome }} para o nome do visitante</li><li>{{ data }} para a data de emiss\xe3o da declara\xe7\xe3o</li><li>{{ evento.data_inicio }} para a data/hora do in\xedcio da visita</li><li>{{ evento.data_termino }} para a data/hora do t\xe9rmino da visita</li><li>{{ evento.nome }} para o nome do evento</li><li>{{ evento.descricao }} para a descri\xe7\xe3o do evento</li></ul>', verbose_name='Texto da declara\xe7\xe3o')),
],
options={
'verbose_name': 'modelo de declara\xe7\xe3o',
'verbose_name_plural': 'modelos de declara\xe7\xe3o',
},
bases=(models.Model,),
),
]

43
sigi/apps/eventos/models.py

@ -10,6 +10,7 @@ from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import Municipio from sigi.apps.contatos.models import Municipio
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from tinymce.models import HTMLField
class TipoEvento(models.Model): class TipoEvento(models.Model):
CATEGORIA_CHOICES = ( CATEGORIA_CHOICES = (
@ -239,3 +240,45 @@ class Modulo(models.Model):
nome=self.nome, nome=self.nome,
tipo=self.get_tipo_display() tipo=self.get_tipo_display()
) )
class ModeloDeclaracao(models.Model):
FORMATO_CHOICES = (
('A4 portrait', _(u"A4 retrato")),
('A4 landscape', _(u"A4 paisagem")),
('letter portrait', _(u"Carta retrato")),
('letter landscape', _(u"Carta paisagem"))
)
nome = models.CharField(_(u"Nome do modelo"), max_length=100)
formato = models.CharField(
_(u"Formato da página"),
max_length=30,
choices=FORMATO_CHOICES,
default=FORMATO_CHOICES[0][0]
)
margem = models.PositiveIntegerField(
_(u"Margem"),
help_text=_(u"Margem da página em centímetros"),
default=4
)
texto = HTMLField(
_(u"Texto da declaração"),
help_text=_(u"Use as seguintes marcações:<ul><li>{{ casa }} para o "
u"nome da Casa Legislativa / órgão</li><li>{{ nome }} "
u"para o nome do visitante</li><li>{{ data }} para a data "
u"de emissão da declaração</li><li>{{ evento.data_inicio }}"
u" para a data/hora do início da visita</li>"
u"<li>{{ evento.data_termino }} para a data/hora do "
u"término da visita</li><li>{{ evento.nome }} para o nome "
u"do evento</li><li>{{ evento.descricao }} para a descrição"
u" do evento</li></ul>")
)
class Meta:
verbose_name = _(u"modelo de declaração")
verbose_name_plural = _(u"modelos de declaração")
def __unicode__(self):
return _(u"{nome} ({formato})").format(
nome=self.nome,
formato=self.get_formato_display()
)

10
sigi/apps/eventos/templates/admin/eventos/evento/change_form.html

@ -0,0 +1,10 @@
{% extends "base_change_form.html" %}
{% load i18n %}
{% block object-tools-items %}
<li><a href="declaracao/">
<span class="glyphicon glyphicon-print"></span>
{% trans 'Declaração' %}
</a></li>
{{ block.super }}
{% endblock %}

0
sigi/apps/eventos/templates/admin/eventos/change_list.html → sigi/apps/eventos/templates/admin/eventos/evento/change_list.html

24
sigi/apps/eventos/templates/eventos/declaracao_pdf.html

@ -0,0 +1,24 @@
{% extends 'base_report.html' %}
{% load i18n %}
{% block pagesize %}{{ pagesize }}{% endblock pagesize %}
{% block pagemargin %}4cm {{ pagemargin }}cm {{ pagemargin }}cm 2cm{% endblock pagemargin %}
{% block report %}
{% for convite in evento.convite_set.all %}
{% with convite.casa.nome as casa %}
{% for nome in convite.nomes_participantes.splitlines %}
{% block text_body %}{% endblock %}
<pdf:nextpage />
{% endfor %}
{% endwith %}
{% endfor %}
{% endblock %}
{%block page_foot%}
<table>
<tr>
<td class="footer-left">{% trans 'Emissão:' %} {% now "d/m/Y H:i:s" %}</td>
</tr>
</table>
{% endblock %}

25
sigi/apps/eventos/templates/eventos/seleciona_modelo.html

@ -0,0 +1,25 @@
{% extends "admin/base_site.html" %}
{% load i18n bootstrap3 %}
{% block content_title %}
<h1 class="pull-left">{% trans 'Emitir declaração de comparecimento' %}</h1>
{% endblock %}
{% block content %}
{% if error %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endif %}
<div id="content-main">
<form action="" method="post">{% csrf_token %}
{% csrf_token %}
<div class="form-group">
{% bootstrap_form form %}
</div>
<input type="submit" value="Imprimir" class="btn btn-primary"/>
<a class="btn btn-danger" role="button" href="{% url 'admin:eventos_evento_change' evento_id %}">{% trans "Voltar" %}</a>
</form>
</div>
{% endblock %}

3
sigi/apps/eventos/urls.py

@ -15,5 +15,8 @@ urlpatterns = patterns(
url(r'^evento/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho', url(r'^evento/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho',
name='deleta-itens-carrinho-evento'), # Error name='deleta-itens-carrinho-evento'), # Error
url(r'^evento/csv/$', 'export_csv', name='evento-export-csv'), # Error url(r'^evento/csv/$', 'export_csv', name='evento-export-csv'), # Error
url(r'^evento/(?P<id>\w+)/declaracao/$', 'declaracao',
name='evento-declaracao'),
) )

54
sigi/apps/eventos/views.py

@ -21,18 +21,21 @@
import calendar import calendar
import datetime import datetime
import locale import locale
import csv
from django import template
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
from django.core.paginator import Paginator, InvalidPage, EmptyPage from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.shortcuts import render from django.shortcuts import get_object_or_404, render
from django.utils import translation from django.utils import translation
from django.utils.translation import ungettext, ugettext as _ from django.utils.translation import ungettext, ugettext as _
from django.http.response import JsonResponse, HttpResponse
from django.template import Template, Context
from sigi.apps.eventos.models import Evento, Equipe, Convite from sigi.apps.eventos.models import Evento, Equipe, Convite
from sigi.apps.eventos.forms import SelecionaModeloForm
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from sigi.shortcuts import render_to_pdf from sigi.shortcuts import render_to_pdf, pdf_renderer
import csv
from django.http.response import JsonResponse, HttpResponse
@login_required @login_required
def calendario(request): def calendario(request):
@ -84,10 +87,10 @@ def calendario(request):
for linha in linhas: for linha in linhas:
sobrepoe = False sobrepoe = False
for e in linha: for e in linha:
if (((evento['evento'].data_inicio >= e['evento'].data_inicio) and if (((evento['evento'].data_inicio.date() >= e['evento'].data_inicio.date()) and
(evento['evento'].data_inicio <= e['evento'].data_termino)) or (evento['evento'].data_inicio.date() <= e['evento'].data_termino.date())) or
((evento['evento'].data_termino >= e['evento'].data_inicio) and ((evento['evento'].data_termino.date() >= e['evento'].data_inicio.date()) and
(evento['evento'].data_termino <= e['evento'].data_termino))): (evento['evento'].data_termino.date() <= e['evento'].data_termino.date()))):
sobrepoe = True sobrepoe = True
break break
if not sobrepoe: if not sobrepoe:
@ -106,7 +109,7 @@ def calendario(request):
if anterior is None: if anterior is None:
anterior = evento anterior = evento
continue continue
anterior['close'] = (evento['evento'].data_inicio - anterior['evento'].data_termino).days-1 anterior['close'] = (evento['evento'].data_inicio.date() - anterior['evento'].data_termino.date()).days-1
evento['start'] = 0 evento['start'] = 0
anterior = evento anterior = evento
@ -376,3 +379,36 @@ def export_csv(request):
return response return response
@login_required
def declaracao(request, id):
if request.method == 'POST':
form = SelecionaModeloForm(request.POST)
if form.is_valid():
evento = get_object_or_404(Evento, id=id)
modelo = form.cleaned_data['modelo']
template_string = (
"""
{% extends "eventos/declaracao_pdf.html" %}
{% block text_body %}""" +
modelo.texto + """
{% endblock %}
"""
)
context = Context(
{'pagesize': modelo.formato,
'pagemargin': modelo.margem,
'evento': evento,
'data': datetime.date.today(),
}
)
template = Template(template_string)
# return HttpResponse(template.render(context))
return pdf_renderer(template, context, 'declaracao.pdf')
else:
form = SelecionaModeloForm()
return render(
request,
'eventos/seleciona_modelo.html',
{'form': form, 'evento_id': id}
)

2
sigi/apps/home/templatetags/menu_conf.yaml

@ -85,6 +85,8 @@ main_menu:
url: eventos/tipoevento/ url: eventos/tipoevento/
- title: Funções na equipe de eventos - title: Funções na equipe de eventos
url: eventos/funcao/ url: eventos/funcao/
- title: Modelos de declaração
url: eventos/modelodeclaracao/
# Removidos # Removidos

10
sigi/settings/base.py

@ -74,7 +74,7 @@ INSTALLED_APPS = (
'easy_thumbnails', 'easy_thumbnails',
'image_cropping', 'image_cropping',
'rest_framework', 'rest_framework',
'tinymce',
) )
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (
@ -188,3 +188,11 @@ REST_FRAMEWORK = {
WHOIS_WHITELIST = [ WHOIS_WHITELIST = [
'127.0.0.1', '127.0.0.1',
] ]
# TinyMCE configuration
TINYMCE_SPELLCHECKER = True
TINYMCE_COMPRESSOR = True
TINYMCE_DEFAULT_CONFIG = {
'theme': "advanced",
"height": 500,
}

14
sigi/shortcuts.py

@ -24,12 +24,7 @@ def fetch_resources(uri, rel):
uri.replace(settings.MEDIA_URL, "")) uri.replace(settings.MEDIA_URL, ""))
return path return path
def pdf_renderer(template, context, filename='report.pdf'):
def render_to_pdf(template_src, context_dict):
filename = template_src.replace('.html', '').replace('_pdf', '.pdf')
template = get_template(template_src)
context = Context(context_dict)
html = template.render(context) html = template.render(context)
response = HttpResponse(content_type='application/pdf') response = HttpResponse(content_type='application/pdf')
@ -41,3 +36,10 @@ def render_to_pdf(template_src, context_dict):
if pdf.err: if pdf.err:
return HttpResponse(_(u'We had some errors<pre>%s</pre>') % escape(html)) return HttpResponse(_(u'We had some errors<pre>%s</pre>') % escape(html))
return response return response
def render_to_pdf(template_src, context_dict):
filename = template_src.replace('.html', '').replace('_pdf', '.pdf')
template = get_template(template_src)
context = Context(context_dict)
return pdf_renderer(template, context,filename)

1
sigi/urls.py

@ -20,6 +20,7 @@ urlpatterns = patterns(
url(r'^ocorrencias/', include('sigi.apps.ocorrencias.urls')), url(r'^ocorrencias/', include('sigi.apps.ocorrencias.urls')),
url(r'^eventos/', include('sigi.apps.eventos.urls')), url(r'^eventos/', include('sigi.apps.eventos.urls')),
url(r'^whois/', include('sigi.apps.whois.urls')), url(r'^whois/', include('sigi.apps.whois.urls')),
url(r'^tinymce/', include('tinymce.urls')),
url(r'^', include('sigi.apps.home.urls')), url(r'^', include('sigi.apps.home.urls')),
url(r'^', include(admin.site.urls)), url(r'^', include(admin.site.urls)),

14
templates/base_report.html

@ -11,11 +11,9 @@
text-align: center; text-align: center;
} }
td.header_text p { td.header_text p {
margin: 0px; margin: 5px;
font-size: 1.4em; font-size: 1.2em;
} text-align: center;
td.header_text {
width: 550px;
} }
h1 { h1 {
font-size: 2em; font-size: 2em;
@ -58,12 +56,12 @@
} }
@page { @page {
size: {% block pagesize %}{{ pagesize }}{% endblock pagesize %}; size: {% block pagesize %}{{ pagesize }}{% endblock pagesize %};
margin: 4cm 1cm 1cm 2cm; margin: {% block pagemargin %}4cm 1cm 1cm 2cm{% endblock pagemargin %};
font-family: "Helvetica, Arial, sans-serif"; font-family: "Helvetica, Arial, sans-serif";
font-size: 2em; font-size: 2em;
@frame header { @frame header {
-pdf-frame-content: header; -pdf-frame-content: header;
top: 1cm; {% block header-settings %}top: 1cm;{% endblock header-settings %}
} }
@frame footer { @frame footer {
-pdf-frame-content: footer; -pdf-frame-content: footer;
@ -84,7 +82,7 @@
<td class="logo"><img src="{% static 'img/logo-senado.jpg' %}" /></td> <td class="logo"><img src="{% static 'img/logo-senado.jpg' %}" /></td>
<td class="header_text"> <td class="header_text">
<p><strong>{% trans 'SENADO FEDERAL' %}</strong></p> <p><strong>{% trans 'SENADO FEDERAL' %}</strong></p>
<p><strong>{% trans 'ILB - PROGRAMA INTERLEGIS' %}</strong></p> <p><strong>{% trans 'INSTITUTO LEGISLATIVO BRASILEIRO - ILB / INTERLEGIS' %}</strong></p>
<p>{% block subsecretaria %}{% endblock %}</p> <p>{% block subsecretaria %}{% endblock %}</p>
</td> </td>
<td class="logo"><img src="{% static 'img/logo-interlegis.jpg' %}" /></td> <td class="logo"><img src="{% static 'img/logo-interlegis.jpg' %}" /></td>

Loading…
Cancel
Save