Browse Source

Adiciona suporte ao envio de email para confirmação e alteração de

tramitação

Adiciona testes e refatora funções de envio de email
pull/222/head
Edward Ribeiro 10 years ago
parent
commit
3de6022da8
  1. 2
      materia/models.py
  2. 4
      materia/urls.py
  3. 265
      materia/views.py
  4. 9
      sapl/utils.py
  5. 27
      templates/email/acompanhar.html
  6. 16
      templates/email/acompanhar.txt
  7. 1
      templates/email/test_tramitacao.html
  8. 38
      templates/email/tramitacao.html
  9. 27
      templates/email/tramitacao.txt
  10. 1
      templates/materia/acompanhamento_materia.html
  11. 74
      templates/materia/test_email_templates.py

2
materia/models.py

@ -138,7 +138,7 @@ class AcompanhamentoMateria(models.Model):
email = models.CharField(
max_length=100, verbose_name=_('Endereço de E-mail'))
data_cadastro = models.DateField(auto_now_add=True)
hash = models.CharField(max_length=8)
hash = models.CharField(max_length=8) # TODO LOL isso não é um HASH!!!!
confirmado = models.BooleanField(default=False)
class Meta:

4
materia/urls.py

@ -1,12 +1,8 @@
from django.conf.urls import include, url
<<<<<<< HEAD
from materia.views import (AcompanhamentoConfirmarView,
AcompanhamentoExcluirView,
AcompanhamentoMateriaView, AutoriaEditView,
=======
from materia.views import (AcompanhamentoMateriaView, AutoriaEditView,
>>>>>>> Move acompanhamento de matéria para a app de matéria.
AutoriaView, DespachoInicialEditView,
DespachoInicialView, DocumentoAcessorioEditView,
DocumentoAcessorioView, FormularioCadastroView,

265
materia/views.py

@ -10,6 +10,7 @@ from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.http.response import HttpResponseRedirect
from django.shortcuts import redirect
from django.template import Context, loader
from django.utils.html import strip_tags
from django.utils.translation import ugettext_lazy as _
from django.views.generic import ListView, TemplateView
@ -23,6 +24,8 @@ from crud import build_crud, make_pagination
from norma.models import LegislacaoCitada, NormaJuridica, TipoNormaJuridica
from parlamentares.models import Partido
from sapl.utils import get_base_url
from .forms import (AcompanhamentoMateriaForm, AutoriaForm,
DespachoInicialForm, DocumentoAcessorioForm,
FormularioCadastroForm, FormularioSimplificadoForm,
@ -769,11 +772,10 @@ class AcompanhamentoConfirmarView(TemplateView):
def get(self, request, *args, **kwargs):
materia_id = kwargs['pk']
hash_txt = request.GET.get('hash', '')
hash_txt = request.GET.get('hash_txt', '')
acompanhar = AcompanhamentoMateria.objects.get(materia_id=materia_id,
hash=hash_txt)
acompanhar.confirmado = True
acompanhar.save()
@ -787,10 +789,13 @@ class AcompanhamentoExcluirView(TemplateView):
def get(self, request, *args, **kwargs):
materia_id = kwargs['pk']
hash_txt = request.GET.get('hash', '')
hash_txt = request.GET.get('hash_txt', '')
AcompanhamentoMateria.objects.get(materia_id=materia_id,
try:
AcompanhamentoMateria.objects.get(materia_id=materia_id,
hash=hash_txt).delete()
except ObjectDoesNotExist:
pass
return HttpResponseRedirect(self.get_redirect_url())
@ -1004,84 +1009,190 @@ class RelatoriaView(FormMixin, GenericView):
'parlamentares': parlamentares})
def criar_html_email(materia, hash_txt):
html_tpl = Template('''
<html>
<head></head>
<body bgcolor='#ffffff'>
<p align='center'>
<img src="$image" width='81' height='77'>
</p>
<h2 align='center'><b>$casa_legislativa</b><br/>
Sistema de Apoio ao Processo Legislativo
</h2>
<p>
A seguinte mat&eacute;ria de seu interesse
sofreu tramita&ccedil;&atilde;o registrada
$data_registro
</p>
<h4>
<a href='context.consultas.absolute_url()
/materia/materia_mostrar_proc?cod_materia=
$cod_materia'><b>$descricao_materia</b></a>
<br/><br/>
<b>Autoria: </b>$autoria
</h4>
<p>
<b>Data da a&ccedil;&atilde;o</b>: $data<br/>
<b>Status</b>: $status<br/>
<b>Texto da a&ccedil;&atilde;o</b>: $texto_acao</p>
<hr>
<p>
<a href='$url?hash_txt=$hash_txt'>
Clique aqui para excluir seu e-mail da lista
de envio</a>
<p>
<p>Esta &eacute; uma mensagem autom&aacute;tica.
Por favor, n&atilde;o a responda.</p>
</body>
</html>''')
def load_email_templates(templates, context = {}):
emails = []
for t in templates:
tpl = loader.get_template(t)
email = tpl.render(Context(context))
if t.endswith(".html"):
email = email.replace('\n', '').replace('\r', '')
emails.append(email)
return emails
def criar_email_confirmacao(request, casa_legislativa, materia, hash_txt=''):
if not casa_legislativa:
raise ValueError("Casa Legislativa é obrigatória")
if not materia:
raise ValueError("Matéria é obrigatória")
casa_nome = (casa_legislativa.nome + ' de ' + \
casa_legislativa.municipio + '-' + \
casa_legislativa.uf)
base_url = get_base_url(request)
materia_url = reverse('acompanhar_materia', kwargs={'pk': materia.id})
confirmacao_url = reverse('acompanhar_confirmar', kwargs={'pk': materia.id})
autores = []
for autoria in materia.autoria_set.all():
autores.append(autoria.autor.nome)
templates = load_email_templates(['email/acompanhar.txt',
'email/acompanhar.html'],
{"casa_legislativa":casa_nome,
"logotipo": casa_legislativa.logotipo,
"descricao_materia":materia.ementa,
"autoria": autores,
"hash_txt":hash_txt,
"base_url": base_url,
"materia": str(materia),
"materia_url": materia_url,
"confirmacao_url":confirmacao_url,})
return templates
casa = CasaLegislativa.objects.first()
casa_nome = (casa.nome + ' de ' + casa.municipio + '-' + casa.uf)
url = reverse('acompanhar_excluir', kwargs={'pk': materia.id})
def criar_email_tramitacao(request, casa_legislativa, materia, hash_txt=''):
if not casa_legislativa:
raise ValueError("Casa Legislativa é obrigatória")
if not materia:
raise ValueError("Matéria é obrigatória")
casa_nome = (casa_legislativa.nome + ' de ' + \
casa_legislativa.municipio + '-' + \
casa_legislativa.uf)
base_url = get_base_url(request)
url_materia = reverse('acompanhar_materia', kwargs={'pk': materia.id})
url_excluir = reverse('acompanhar_excluir', kwargs={'pk': materia.id})
autores = []
for autoria in materia.autoria_set.all():
autoria_html += autoria.autor.nome + "<br/> "
html_body = html_tpl.substitute(image=static('img/logo.png'),
casa_legislativa=casa_nome,
data_registro=datetime.now().strftime(
"%d/%m/%Y"),
cod_materia=materia.id,
descricao_materia=materia.ementa,
autoria=autoria_html,
data=materia.tramitacao_set.last(
autores.append(autoria.autor.nome)
templates = load_email_templates(['email/tramitacao.txt',
'email/tramitacao.html'],
{"casa_legislativa":casa_nome,
"data_registro":datetime.now().strftime(
"%d/%m/%Y"),
"cod_materia":materia.id,
"logotipo": casa_legislativa.logotipo,
"descricao_materia":materia.ementa,
"autoria": autores,
"data":materia.tramitacao_set.last(
).data_tramitacao,
status=materia.tramitacao_set.last(
"status":materia.tramitacao_set.last(
).status,
texto_acao=materia.tramitacao_set.last(
"texto_acao":materia.tramitacao_set.last(
).texto,
hash_txt=hash_txt,
url=url,)
return html_body
def enviar_emails(materia):
"hash_txt":hash_txt,
"materia": str(materia),
"base_url": base_url,
"materia_url": url_materia,
"excluir_url":url_excluir,})
return templates
def enviar_emails(sender, recipients, messages):
'''
Recipients is a string list of email addresses
Messages is an array of dicts of the form:
{'recipient': 'address', # useless????
'subject': 'subject text',
'txt_message': 'text message',
'html_message': 'html message'
}
'''
if len(messages) == 1:
# sends an email simultaneously to all recipients
send_mail(messages[0]['subject'],
messages[0]['txt_message'],
sender,
recipients,
html_message = messages[0]['html_message'],
fail_silently=False)
elif len(recipients) > len(messages):
raise ValueError("Message list should have size 1 \
or equal recipient list size. \
recipients: %s, messages: %s" % (recipients, messages))
else:
# sends an email simultaneously to all reciepients
for (d, m) in zip(recipients, messages):
send_mail(m['subject'],
m['txt_message'],
sender,
[d],
html_message = m['html_message'],
fail_silently=False)
return None
def do_envia_email_confirmacao(request, materia, email):
#
# Envia email de confirmacao para atualizações de tramitação
#
destinatario = AcompanhamentoMateria.objects.get(materia=materia,
email=email,
confirmado=False)
casa = CasaLegislativa.objects.first()
destinatarios = AcompanhamentoMateria.objects.filter(
materia=materia,
confirmado=True)
sender = 'sapl-test@interlegis.leg.br'
subject = "[SAPL] "+ str(materia) +" - Ative o Acompanhamento da Materia"
messages = []
recipients = []
email_texts = criar_email_confirmacao(request,
casa,
materia,
destinatario.hash,)
recipients.append(destinatario.email)
messages.append({
'recipient': destinatario.email,
'subject': subject,
'txt_message': email_texts[0],
'html_message': email_texts[1]
})
enviar_emails(sender, recipients, messages)
return None
def do_envia_email_tramitacao(request, materia):
#
# Envia email de tramitacao para usuarios cadastrados
#
destinatarios = AcompanhamentoMateria.objects.filter(materia=materia,
confirmado=True)
casa = CasaLegislativa.objects.first()
sender = 'sapl-test@interlegis.leg.br'
subject = "[SAPL] "+ str(materia) +" - Acompanhamento de Materia Legislativa"
messages = []
recipients = []
for destinatario in destinatarios:
corpo_email_html = criar_html_email(materia, destinatario.hash_txt)
send_mail('Mudança de Tramitação',
corpo_email_html,
'sapl-test@interlegis.leg.br',
destinatario,
fail_silently=True)
email_texts = criar_email_tramitacao(request,
casa,
materia,
destinatario.hash,)
recipients.append(destinatario.email)
messages.append({
'recipient': destinatario.email,
'subject': subject,
'txt_message': email_texts[0],
'html_message': email_texts[1]
})
enviar_emails(sender, recipients, messages)
return None
class TramitacaoView(FormMixin, GenericView):
@ -1123,9 +1234,8 @@ class TramitacaoView(FormMixin, GenericView):
'object': materia,
'tramitacoes': tramitacoes_list})
# Manda por parametro para 'enviar_emails' ?
img_url = request.get_host() + static('img/logo.png')
self.enviar_emails(materia)
do_envia_email_tramitacao(request, materia)
return self.form_valid(form)
else:
return self.render_to_response({'form': form,
@ -1136,7 +1246,6 @@ class TramitacaoView(FormMixin, GenericView):
pk = self.kwargs['pk']
return reverse('tramitacao_materia', kwargs={'pk': pk})
class TramitacaoEditView(FormMixin, GenericView):
template_name = "materia/tramitacao_edit.html"
@ -1615,6 +1724,7 @@ class AcompanhamentoMateriaView(FormMixin,
def get(self, request, *args, **kwargs):
pk = self.kwargs['pk']
materia = MateriaLegislativa.objects.get(id=pk)
return self.render_to_response(
{'form': AcompanhamentoMateriaForm(),
'materia': materia})
@ -1644,6 +1754,9 @@ class AcompanhamentoMateriaView(FormMixin,
acompanhar.usuario = usuario.username
acompanhar.confirmado = False
acompanhar.save()
do_envia_email_confirmacao(request, materia, email)
else:
return self.render_to_response(
{'form': form,

9
sapl/utils.py

@ -21,6 +21,15 @@ def xstr(s):
return '' if s is None else str(s)
def get_base_url(request):
# TODO substituir por Site.objects.get_current().domain
# from django.contrib.sites.models import Site
current_domain = request.get_host()
protocol = 'https' if request.is_secure() else 'http'
return "{0}://{1}".format(protocol, current_domain)
def create_barcode(value):
'''
creates a base64 encoded barcode PNG image

27
templates/email/acompanhar.html

@ -0,0 +1,27 @@
{% load i18n %}
{% load static %}
<html><head></head><body bgcolor='#ffffff'>
<p align='center'>
<img src="{{base_url}}{% if logotipo %}{{ MEDIA_URL }}{{ logotipo }}{% else %}{% static 'img/logo.png' %}{% endif %}"
alt="Logo" class="img-responsive visible-lg-inline-block vcenter" >
</p>
<h2 align='center'><b>{{casa_legislativa}}</b>
<br/>
Sistema de Apoio ao Processo Legislativo
</h2>
<p>Registramos seu pedido para acompanhamento por e-mail da matéria legislativa identificada a seguir:</p>
<a href="{{base_url}}{{materia_url}}">{{materia}}<b> - {{descricao_materia}}</b></a><br/>
{{ementa}}<br/>
</h4>
<p></p>
<p>Para garantia de sua privacidade, solicitamos que ative o recebimento das futuras mensagens clicando no link:</p>
<h4>
<a href="{{base_url}}{{confirmacao_url}}?hash_txt={{hash_txt}}">{{base_url}}{{confirmacao_url}}?hash_txt={{hash_txt}}</a>
</h4>
<br/>
<hr>
<p>Caso não tenha realizado o cadastramento em nosso sistema, favor desconsiderar a presente mensagem<br/>
Esta é uma mensagem automática. Por favor, não responda.</p>
</body>
</html>

16
templates/email/acompanhar.txt

@ -0,0 +1,16 @@
{{casa_legislativa}}
Sistema de Apoio ao Processo Legislativo
>Registramos seu pedido para acompanhamento por e-mail da matéria legislativa identificada a seguir:
{{base_url}}{{materia_url}} - {{materia}} - {{descricao_materia}}
{{ementa}}
Para garantia de sua privacidade, solicitamos que ative o recebimento das futuras mensagens acessando no link:
{{base_url}}{{url_confirmar}}?hash_txt={{hash_txt}}
Caso não tenha realizado o cadastramento em nosso sistema, favor desconsiderar a presente mensagem
Esta é uma mensagem automática. Por favor, não responda.

1
templates/email/test_tramitacao.html

@ -0,0 +1 @@
<html><body>Hello {{name}}</body></html>

38
templates/email/tramitacao.html

@ -0,0 +1,38 @@
{% load i18n %}
{% load static %}
<html>
<head></head>
<body bgcolor='#ffffff'>
<p align='center'>
<img src="{{base_url}}{% if logotipo %}{{ MEDIA_URL }}{{ logotipo }}{% else %}{% static 'img/logo.png' %}{% endif %}"
alt="Logo" class="img-responsive visible-lg-inline-block vcenter" >
</p>
<h2 align='center'><b>{{casa_legislativa}}</b>
<br/>
Sistema de Apoio ao Processo Legislativo
</h2>
<p>A seguinte mat&eacute;ria de seu interesse sofreu
tramita&ccedil;&atilde;o registrada em {{data_registro}}
</p>
<h4>
<a href="{{base_url}}{{materia_url}}"><b>{{materia}} - {{descricao_materia}}</b></a>
<br/><br/>
<b>Autoria:</b></br>
{% for autor in autoria %}
{{ autor }}</br>
{% endfor %}
</h4>
<p></p>
<p>
<b>Data da a&ccedil;&atilde;o</b>: {{data}}<br/>
<b>Status</b>: {{status}}<br/>
<b>Texto da a&ccedil;&atilde;o</b>: {{texto_acao}}</p>
<hr>
<p>
<a href="{{base_url}}{{excluir_url}}?hash_txt={{hash_txt}}">
Clique aqui para excluir seu e-mail da lista de envio</a>
<p>
<p>Esta &eacute; uma mensagem autom&aacute;tica.
Por favor, n&atilde;o a responda.</p>
</body>
</html>

27
templates/email/tramitacao.txt

@ -0,0 +1,27 @@
{{casa_legislativa}}
Sistema de Apoio ao Processo Legislativo
-----------------------------------------
A seguinte matéria de seu interesse sofreu tramitação registrada em {{data_registro}}
Matéria: {{materia}} - {{descricao_materia}}
{{url_materia}}
Autoria:
{% for autor in autoria %}
{{ autor }}
{% endfor %}
Data da ação: {{data}}
Status: {{status}}
Texto da ação: {{texto_acao}}
Acesse o link abaixo para excluir seu e-mail da lista de envio
{{url_excluir_acompanhamento}}?hash_txt={{hash_txt}}
Esta é uma mensagem automática. Por favor, não a responda.

1
templates/materia/acompanhamento_materia.html

@ -18,5 +18,4 @@
{% if error %} <h5 align="center"><font color="#FF0000">{{ error }}</font></h5> {% endif %}
{% crispy form %}
{% endblock %}

74
templates/materia/test_email_templates.py

@ -0,0 +1,74 @@
import pytest
from base.models import CasaLegislativa
from django.core import mail
from model_mommy import mommy
from materia.views import load_email_templates, enviar_email, criar_email_tramitacao
from materia.models import MateriaLegislativa, TipoMateriaLegislativa
def test_email_template_loading():
expected = "<html><body>Hello Django</body></html>"
emails = load_email_templates(['email/test_tramitacao.html'],
context={"name": "Django"})
# strip \n and \r to compare with expected
actual = emails[0].replace('\n', '').replace('\r', '')
assert actual == expected
@pytest.mark.django_db(transaction=False)
def test_email_body_creation_with_empty_materia():
casa = CasaLegislativa.objects.create()
with pytest.raises(ValueError):
criar_email_tramitacao(casa, materia=None)
def test_html_email_body_with_materia():
templates = load_email_templates(['email/tramitacao.txt',
'email/tramitacao.html'],
{"image":'img/logo.png',
"casa_legislativa":"Assembléia Parlamentar",
"data_registro":"25/02/2016",
"cod_materia":"1",
"descricao_materia":"Ementa de teste",
"autoria": ["Autor1", "Autor2"],
"data":"25/02/2016",
"status":"Arquivado",
"texto_acao":"Deliberado",
"hash_txt":"abc01f",
"materia_id": "794",
"base_url": "http://localhost:8000",
"materia_url": "/materia/764/acompanhar-materia",
"excluir_url": "/materia/764/acompanhar-excluir",})
assert len(templates) == 2
def test_enviar_email_distintos():
NUM_MESSAGES = 10
messages = [{'recipient': 'user-' + str(i) + '@test.com',
'subject': 'subject: ' + str(i),
'txt_message': 'txt: ' + str(i),
'html_message': '<html></html>',
} for i in range(NUM_MESSAGES)]
recipients = [m['recipient'] for m in messages]
enviar_email('test@sapl.com', recipients, messages)
assert len(mail.outbox) == NUM_MESSAGES
def test_enviar_same_email():
NUM_MESSAGES = 10
messages = [{'recipient': 'user-' + str(i) + '@test.com',
'subject': 'subject: ' + str(i),
'txt_message': 'txt: ' + str(i),
'html_message': '<html></html>',
} for i in range(NUM_MESSAGES)]
recipients = [m['recipient'] for m in messages]
enviar_email('test@sapl.com', recipients, [messages[0]])
assert len(mail.outbox) == 1
Loading…
Cancel
Save