Browse Source

Fix #2342 (#2354)

* Fix #2432

Insere verificação de serviço de email configurado. Assume que
EMAIL_HOST vazio é serviço desativado não enviando, assim, email na
edição/adição de autor, bem como desativando acesso via get/post e
por link de "Acompanhar Matéria" na lista de resultados da
pesquisa de matéria e na tela de detalhes de matérias.
Comportamento análogo para Documentos Administrativos.

* impl test de conexão

* Corrige tipo de remetente

rementente de um email é único e seu envio não é feito através de uma
lista... estudando a execução do send_mail descobri a RFC 2822 que
define rementente da seguinte forma:

From: "Joe Q. Public" <john.q.public@example.com>

portanto,

ou se envia uma string neste formato, o que faz com que mais execução
deva ser feita para um padrão interno de processamento, ou envia-se uma
tupla e não uma lista da seguinte forma

("Joe Q. Public", "john.q.public@exemple.com")

então por que com um servidor configurado o remetente estava
funcionando?

possivelmente ninguem ainda tinha seguindo o formato completo acima
apresentado na definição de EMAIL_SEND_USER...

fazendo isso:
EMAIL_SEND_USER = john.q.public@example.com

em vez disso:
EMAIL_SEND_USER = Joe Q. Public <john.q.public@example.com>

ocorre que esta segunda forma (a correta), melhor apresenta o email ao
usuário, colocando em sua caixa de entrada de email um nome
significativo e não o username.

* faz teste de conexão de email apenas no início do sapl
pull/2365/head
Leandro Roberto da Silva 6 years ago
committed by Edward
parent
commit
ca038b9805
  1. 20
      sapl/base/email_utils.py
  2. 31
      sapl/base/templatetags/common_tags.py
  3. 57
      sapl/base/views.py
  4. 15
      sapl/context_processors.py
  5. 301
      sapl/materia/views.py
  6. 104
      sapl/protocoloadm/views.py
  7. 11
      sapl/settings.py
  8. 2
      sapl/templates/materia/materialegislativa_detail.html
  9. 2
      sapl/templates/materia/materialegislativa_filter.html
  10. 2
      sapl/templates/protocoloadm/documentoadministrativo_filter.html
  11. 19
      sapl/utils.py

20
sapl/base/email_utils.py

@ -1,4 +1,5 @@
from datetime import datetime as dt
import logging
from django.core.mail import EmailMultiAlternatives, get_connection, send_mail
from django.core.urlresolvers import reverse
@ -6,10 +7,10 @@ from django.template import Context, loader
from django.utils import timezone
from sapl.base.models import CasaLegislativa
from sapl.settings import EMAIL_SEND_USER
from sapl.materia.models import AcompanhamentoMateria
from sapl.protocoloadm.models import AcompanhamentoDocumento
from sapl.settings import EMAIL_SEND_USER
from sapl.utils import mail_service_configured
def load_email_templates(templates, context={}):
@ -94,8 +95,6 @@ def criar_email_confirmacao(base_url, casa_legislativa, doc_mat, tipo, hash_txt=
ementa = doc_mat.assunto
autores = ""
templates = load_email_templates(['email/acompanhar.txt',
'email/acompanhar.html'],
{"casa_legislativa": casa_nome,
@ -115,6 +114,11 @@ def do_envia_email_confirmacao(base_url, casa, tipo, doc_mat, destinatario):
# Envia email de confirmacao para atualizações de tramitação
#
if not mail_service_configured():
logger = logging.getLogger(__name__)
logger.warning(_('Servidor de email não configurado.'))
return
sender = EMAIL_SEND_USER
# FIXME i18n
if tipo == "materia":
@ -203,12 +207,18 @@ def do_envia_email_tramitacao(base_url, tipo, doc_mat, status, unidade_destino):
#
# Envia email de tramitacao para usuarios cadastrados
#
if not mail_service_configured():
logger = logging.getLogger(__name__)
logger.warning(_('Servidor de email não configurado.'))
return
if tipo == "materia":
destinatarios = AcompanhamentoMateria.objects.filter(materia=doc_mat,
confirmado=True)
else:
destinatarios = AcompanhamentoDocumento.objects.filter(documento=doc_mat,
confirmado=True)
confirmado=True)
casa = CasaLegislativa.objects.first()

31
sapl/base/templatetags/common_tags.py

@ -1,5 +1,8 @@
import logging
from compressor.utils import get_class
from django import template
from django.conf import settings
from django.template.defaultfilters import stringfilter
from sapl.base.models import AppConfig
@ -8,12 +11,13 @@ from sapl.norma.models import NormaJuridica
from sapl.parlamentares.models import Filiacao
from sapl.utils import filiacao_data, SEPARADOR_HASH_PROPOSICAO
register = template.Library()
@register.simple_tag
def define(arg):
return arg
return arg
@register.simple_tag
@ -48,8 +52,9 @@ def split(value, arg):
def to_str(arg):
return str(arg)
@register.filter
def get_last_item_from_list(list,arg):
def get_last_item_from_list(list, arg):
return list[arg]
@ -59,14 +64,14 @@ def sort_by_keys(value, key):
id_props = [x.id for x in value]
qs = Proposicao.objects.filter(pk__in=id_props)
key_descricao = {'1': 'data_envio',
'-1': '-data_envio',
'2': 'tipo',
'-2': '-tipo',
'3': 'descricao',
'-3': '-descricao',
'4': 'autor',
'-4': '-autor'
}
'-1': '-data_envio',
'2': 'tipo',
'-2': '-tipo',
'3': 'descricao',
'-3': '-descricao',
'4': 'autor',
'-4': '-autor'
}
transformed = qs.order_by(key_descricao[key])
return transformed
@ -74,7 +79,7 @@ def sort_by_keys(value, key):
@register.filter
def paginacao_limite_inferior(pagina):
return (int(pagina) - 1) * 10
return (int(pagina) - 1) * 10
@register.filter
@ -103,7 +108,6 @@ def strip_hash(value):
return value.split(SEPARADOR_HASH_PROPOSICAO)[0][1:]
@register.filter
def get_add_perm(value, arg):
perm = value
@ -203,6 +207,7 @@ def url(value):
return True
return False
@register.filter
def audio_url(value):
return True if url(value) and value.endswith("mp3") else False
@ -212,11 +217,13 @@ def audio_url(value):
def video_url(value):
return True if url(value) and value.endswith("mp4") else False
@register.filter
def file_extension(value):
import pathlib
return pathlib.Path(value).suffix.replace('.', '')
@register.filter
def cronometro_to_seconds(value):
if not AppConfig.attr('cronometro_' + value):

57
sapl/base/views.py

@ -1,5 +1,5 @@
import os
import logging
import os
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import PermissionRequiredMixin
@ -33,7 +33,7 @@ from sapl.materia.models import (Autoria, MateriaLegislativa,
from sapl.sessao.models import (PresencaOrdemDia, SessaoPlenaria,
SessaoPlenariaPresenca)
from sapl.utils import (parlamentares_ativos,
show_results_filter_set)
show_results_filter_set, mail_service_configured)
from .forms import (AlterarSenhaForm, CasaLegislativaForm,
ConfiguracoesAppForm, RelatorioAtasFilterSet,
@ -170,9 +170,15 @@ class AutorCrud(CrudAux):
pk_autor = self.object.id
url_reverse = reverse('sapl.base:autor_detail',
kwargs={'pk': pk_autor})
if not mail_service_configured():
self.logger.warning(_('Registro de Autor sem envio de email. '
'Servidor de email não configurado.'))
return url_reverse
try:
self.logger.debug('user=' + username + '. Enviando email na edição de Autores.')
self.logger.debug('user={}. Enviando email na edição '
'de Autores.'.format(username))
kwargs = {}
user = self.object.user
@ -195,13 +201,14 @@ class AutorCrud(CrudAux):
"ignore esta mensagem. Caso tenha, clique " +
"no link abaixo\n" + url_base +
reverse('sapl.base:confirmar_email', kwargs=kwargs))
remetente = [settings.EMAIL_SEND_USER]
remetente = settings.EMAIL_SEND_USER
destinatario = [user.email]
send_mail(assunto, mensagem, remetente, destinatario,
fail_silently=False)
except Exception as e:
self.logger.error('user=' + username + '. Erro no envio de email na edição de Autores. ' + str(e))
self.logger.error('user={}. Erro no envio de email na edição de'
' Autores. {}'.format(username, str(e)))
return url_reverse
class CreateView(CrudAux.CreateView):
@ -224,9 +231,15 @@ class AutorCrud(CrudAux):
pk_autor = self.object.id
url_reverse = reverse('sapl.base:autor_detail',
kwargs={'pk': pk_autor})
if not mail_service_configured():
self.logger.warning(_('Registro de Autor sem envio de email. '
'Servidor de email não configurado.'))
return url_reverse
try:
self.logger.debug('user=' + username + '. Enviando email na criação de Autores.')
self.logger.debug('user=' + username +
'. Enviando email na criação de Autores.')
kwargs = {}
user = self.object.user
@ -250,15 +263,16 @@ class AutorCrud(CrudAux):
"ignore esta mensagem. Caso tenha, clique " +
"no link abaixo\n" + url_base +
reverse('sapl.base:confirmar_email', kwargs=kwargs))
remetente = [settings.EMAIL_SEND_USER]
remetente = settings.EMAIL_SEND_USER
destinatario = [user.email]
send_mail(assunto, mensagem, remetente, destinatario,
fail_silently=False)
except Exception as e:
print(
_('Erro no envio de email na criação de Autores.'))
self.logger.error('user=' + username + '. Erro no envio de email na criação de Autores. ' + str(e))
self.logger.error(
'user=' + username + '. Erro no envio de email na criação de Autores. ' + str(e))
return url_reverse
@ -347,18 +361,21 @@ class RelatorioPresencaSessaoView(FilterView):
'ordemdia_porc': 0
})
try:
self.logger.debug('user=' + username + '. Tentando obter presença do parlamentar (pk={}).'.format(p.id))
self.logger.debug(
'user=' + username + '. Tentando obter presença do parlamentar (pk={}).'.format(p.id))
sessao_count = presenca_sessao.get(parlamentar_id=p.id)[1]
except ObjectDoesNotExist as e:
self.logger.error('user=' + username + '. Erro ao obter presença do parlamentar (pk={}). Definido como 0. '.format(p.id) + str(e))
self.logger.error(
'user=' + username + '. Erro ao obter presença do parlamentar (pk={}). Definido como 0. '.format(p.id) + str(e))
sessao_count = 0
try:
# Presenças de cada Ordem do Dia
self.logger.info('user=' + username + '. Tentando obter PresencaOrdemDia para o parlamentar pk={}.'.format(p.id))
self.logger.info(
'user=' + username + '. Tentando obter PresencaOrdemDia para o parlamentar pk={}.'.format(p.id))
ordemdia_count = presenca_ordem.get(parlamentar_id=p.id)[1]
except ObjectDoesNotExist:
self.logger.error('user=' + username + '. Erro ao obter PresencaOrdemDia para o parlamentar pk={}. '
'Definido como 0.'.format(p.id))
'Definido como 0.'.format(p.id))
ordemdia_count = 0
parlamentares_presencas[i].update({
@ -871,14 +888,16 @@ class HelpTopicView(TemplateView):
logger = logging.getLogger(__name__)
def get_template_names(self):
username = self.request.user.username
topico = self.kwargs['topic']
try:
self.logger.debug('user=' + username + '. Tentando obter template %s.html.' % topico)
self.logger.debug('user=' + username +
'. Tentando obter template %s.html.' % topico)
get_template('ajuda/%s.html' % topico)
except TemplateDoesNotExist as e:
self.logger.error('user=' + username + '. Erro ao obter template {}.html. Template não existe. '.format(topico) + str(e))
self.logger.error(
'user=' + username + '. Erro ao obter template {}.html. Template não existe. '.format(topico) + str(e))
raise Http404()
return ['ajuda/%s.html' % topico]

15
sapl/context_processors.py

@ -1,4 +1,10 @@
import logging
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from sapl.base.views import get_casalegislativa
from sapl.utils import mail_service_configured as mail_service_configured_utils
def parliament_info(request):
@ -7,3 +13,12 @@ def parliament_info(request):
return casa.__dict__
else:
return {}
def mail_service_configured(request):
if not mail_service_configured_utils(request):
logger = logging.getLogger(__name__)
logger.warning(_('Servidor de email não configurado.'))
return {'mail_service_configured': False}
return {'mail_service_configured': True}

301
sapl/materia/views.py

@ -1,9 +1,11 @@
from datetime import datetime
import logging
from random import choice
from string import ascii_letters, digits
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin
@ -21,10 +23,11 @@ from django.views.generic.base import RedirectView
from django.views.generic.edit import FormView
from django_filters.views import FilterView
import weasyprint
import logging
import sapl
from sapl.base.email_utils import do_envia_email_confirmacao
from sapl.base.models import Autor, CasaLegislativa
from sapl.base.signals import tramitacao_signal
from sapl.comissoes.models import Comissao, Participacao
from sapl.compilacao.models import (STATUS_TA_IMMUTABLE_RESTRICT,
STATUS_TA_PRIVATE)
@ -45,9 +48,8 @@ from sapl.protocoloadm.models import Protocolo
from sapl.utils import (YES_NO_CHOICES, autor_label, autor_modal, SEPARADOR_HASH_PROPOSICAO,
gerar_hash_arquivo, get_base_url,
get_mime_type_from_file_extension, montar_row_autor,
show_results_filter_set)
show_results_filter_set, mail_service_configured)
from sapl.base.email_utils import do_envia_email_confirmacao
from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm,
AdicionarVariasAutoriasFilterSet, DespachoInicialForm,
DocumentoAcessorioForm, EtiquetaPesquisaForm,
@ -66,7 +68,6 @@ from .models import (AcompanhamentoMateria, Anexada, AssuntoMateria, Autoria,
RegimeTramitacao, Relatoria, StatusTramitacao,
TipoDocumento, TipoFimRelatoria, TipoMateriaLegislativa,
TipoProposicao, Tramitacao, UnidadeTramitacao)
from sapl.base.signals import tramitacao_signal
AssuntoMateriaCrud = CrudAux.build(AssuntoMateria, 'assunto_materia')
@ -94,15 +95,16 @@ def autores_ja_adicionados(materia_pk):
def proposicao_texto(request, pk):
logger = logging.getLogger(__name__)
username = request.user.username.replace("'","")
logger.debug('user=' + username + '. Tentando obter objeto Proposicao com pk = {}.'.format(pk))
username = request.user.username.replace("'", "")
logger.debug('user=' + username +
'. Tentando obter objeto Proposicao com pk = {}.'.format(pk))
proposicao = Proposicao.objects.get(pk=pk)
if proposicao.texto_original:
if (not proposicao.data_recebimento and
proposicao.autor.user_id != request.user.id):
logger.error("user=" + username + ". Usuário ({}) não tem permissão para acessar o texto original."
.format(request.user.id))
.format(request.user.id))
messages.error(request, _(
'Você não tem permissão para acessar o texto original.'))
return redirect(reverse('sapl.materia:proposicao_detail',
@ -119,7 +121,8 @@ def proposicao_texto(request, pk):
response['Content-Disposition'] = (
'inline; filename="%s"' % arquivo.name.split('/')[-1])
return response
logger.error('user=' + username + '. Objeto Proposicao com pk={} não encontrado.'.format(pk))
logger.error('user=' + username +
'. Objeto Proposicao com pk={} não encontrado.'.format(pk))
raise Http404
@ -181,25 +184,28 @@ class CriarProtocoloMateriaView(CreateView):
def get_context_data(self, **kwargs):
context = super(
CriarProtocoloMateriaView, self).get_context_data(**kwargs)
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
try:
self.logger.debug("user=" + username + ". Tentando obter objeto Protocolo.")
self.logger.debug("user=" + username +
". Tentando obter objeto Protocolo.")
protocolo = Protocolo.objects.get(pk=self.kwargs['pk'])
except ObjectDoesNotExist as e:
self.logger.error("user=" + username + ". Objeto Protocolo com pk={} não encontrado. ".format(self.kwargs['pk']) + str(e))
self.logger.error(
"user=" + username + ". Objeto Protocolo com pk={} não encontrado. ".format(self.kwargs['pk']) + str(e))
raise Http404()
numero = 1
try:
self.logger.debug("user=" + username + ". Tentando obter materias do último ano.")
self.logger.debug("user=" + username +
". Tentando obter materias do último ano.")
materias_ano = MateriaLegislativa.objects.filter(
ano=protocolo.ano,
tipo=protocolo.tipo_materia).latest('numero')
numero = materias_ano.numero + 1
except ObjectDoesNotExist:
self.logger.error("user=" + username + ". Não foram encontradas matérias no último ano ({}). "
"Definido 1 como padrão.".format(protocolo.ano))
"Definido 1 como padrão.".format(protocolo.ano))
pass # numero ficou com o valor padrão 1 acima
context['form'].fields['tipo'].initial = protocolo.tipo_materia
@ -213,13 +219,15 @@ class CriarProtocoloMateriaView(CreateView):
def form_valid(self, form):
materia = form.save()
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
try:
self.logger.info("user=" + username + ". Tentando obter objeto Procolo com pk={}.".format(self.kwargs['pk']))
self.logger.info(
"user=" + username + ". Tentando obter objeto Procolo com pk={}.".format(self.kwargs['pk']))
protocolo = Protocolo.objects.get(pk=self.kwargs['pk'])
except ObjectDoesNotExist:
self.logger.error('user=' + username + '. Objeto Protocolo com pk={} não encontrado.'.format(self.kwargs['pk']))
self.logger.error(
'user=' + username + '. Objeto Protocolo com pk={} não encontrado.'.format(self.kwargs['pk']))
raise Http404()
if protocolo.autor:
@ -304,17 +312,19 @@ class ProposicaoTaView(IntegracaoTaView):
@permission_required('materia.detail_materialegislativa')
def recuperar_materia(request):
logger = logging.getLogger(__name__)
username = request.user.username.replace("'","")
username = request.user.username.replace("'", "")
tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo'])
ano = request.GET.get('ano', '')
numeracao = None
try:
logger.debug("user=" + username + ". Tentando obter numeração da matéria.")
logger.debug("user=" + username +
". Tentando obter numeração da matéria.")
numeracao = sapl.base.models.AppConfig.objects.last(
).sequencia_numeracao
except AttributeError as e:
logger.error("user=" + username + ". " + str(e) + " Numeracao da matéria definida como None.")
logger.error("user=" + username + ". " + str(e) +
" Numeracao da matéria definida como None.")
pass
if tipo.sequencia_numeracao:
@ -531,7 +541,8 @@ class ReceberProposicao(PermissionRequiredForAppCrudMixin, FormView):
except IndexError:
messages.error(request, _('Código de recibo mal formado!'))
except IOError:
messages.error(request, _('Erro abrindo texto original de proposição'))
messages.error(request, _(
'Erro abrindo texto original de proposição'))
return self.form_invalid(form)
def get_success_url(self):
@ -547,25 +558,28 @@ class RetornarProposicao(UpdateView):
app_label = sapl.protocoloadm.apps.AppConfig.label
template_name = "materia/proposicao_confirm_return.html"
model = Proposicao
fields = ['data_envio', 'descricao' ]
fields = ['data_envio', 'descricao']
permission_required = ('materia.detail_proposicao_enviada', )
logger = logging.getLogger(__name__)
def dispatch(self, request, *args, **kwargs):
username = request.user.username.replace("'","")
username = request.user.username.replace("'", "")
try:
self.logger.info("user=" + username + ". Tentando obter objeto Proposicao com id={}.".format(kwargs['pk']))
self.logger.info(
"user=" + username + ". Tentando obter objeto Proposicao com id={}.".format(kwargs['pk']))
p = Proposicao.objects.get(id=kwargs['pk'])
except:
self.logger.error("user=" + username + ". Objeto Proposicao com id={} não encontrado.".format(kwargs['pk']))
self.logger.error(
"user=" + username + ". Objeto Proposicao com id={} não encontrado.".format(kwargs['pk']))
raise Http404()
if p.autor.user != request.user:
self.logger.error("user=" + username + ". Usuário ({}) sem acesso a esta opção.".format(request.user))
self.logger.error(
"user=" + username + ". Usuário ({}) sem acesso a esta opção.".format(request.user))
messages.error(
request,
'Usuário sem acesso a esta opção.' %
request.user)
request,
'Usuário sem acesso a esta opção.' %
request.user)
return redirect('/')
return super(RetornarProposicao, self).dispatch(
@ -589,7 +603,7 @@ class ConfirmarProposicao(PermissionRequiredForAppCrudMixin, UpdateView):
return self.object.results['url']
def get_object(self, queryset=None):
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
try:
"""
@ -597,7 +611,8 @@ class ConfirmarProposicao(PermissionRequiredForAppCrudMixin, UpdateView):
recebidas -> data_recebimento != None
não enviadas -> data_envio == None
"""
self.logger.debug("user=" + username + ". Tentando obter objeto Proposicao.")
self.logger.debug("user=" + username +
". Tentando obter objeto Proposicao.")
proposicao = Proposicao.objects.get(pk=self.kwargs['pk'],
data_envio__isnull=False,
data_recebimento__isnull=True)
@ -615,7 +630,7 @@ class ConfirmarProposicao(PermissionRequiredForAppCrudMixin, UpdateView):
self.object = proposicao
except Exception as e:
self.logger.error("user=" + username + ". Objeto Proposicao com atributos (pk={}, data_envio=Not Null, "
"data_recebimento=Null) não encontrado. ".format(self.kwargs['pk']) + str(e))
"data_recebimento=Null) não encontrado. ".format(self.kwargs['pk']) + str(e))
raise Http404()
if not self.object:
@ -736,6 +751,7 @@ class ProposicaoCrud(Crud):
'materia.detail_proposicao_incorporada')
logger = logging.getLogger(__name__)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['subnav_template_name'] = ''
@ -746,9 +762,9 @@ class ProposicaoCrud(Crud):
return context
def get(self, request, *args, **kwargs):
action = request.GET.get('action', '')
username = request.user.username.replace("'","")
username = request.user.username.replace("'", "")
if not action:
return Crud.DetailView.get(self, request, *args, **kwargs)
@ -781,8 +797,8 @@ class ProposicaoCrud(Crud):
'Proposição enviada com sucesso.'))
try:
self.logger.debug("user=" + username + ". Tentando obter número do objeto MateriaLegislativa com "
"atributos tipo={} e ano={}."
.format(p.tipo.tipo_conteudo_related, p.ano))
"atributos tipo={} e ano={}."
.format(p.tipo.tipo_conteudo_related, p.ano))
numero = MateriaLegislativa.objects.filter(tipo=p.tipo.tipo_conteudo_related,
ano=p.ano).last().numero + 1
messages.success(request, _(
@ -790,22 +806,26 @@ class ProposicaoCrud(Crud):
'número que pode não corresponder com a realidade'
% (p.tipo, numero, p.ano)))
except ValueError as e:
self.logger.error("user=" + username + "." + str(e))
self.logger.error(
"user=" + username + "." + str(e))
pass
except AttributeError as e:
self.logger.error("user=" + username + "." + str(e))
self.logger.error(
"user=" + username + "." + str(e))
pass
except TypeError as e:
self.logger.error("user=" + username + "." + str(e))
self.logger.error(
"user=" + username + "." + str(e))
pass
elif action == 'return':
if not p.data_envio:
self.logger.error("user=" + username + ". Proposição (numero={}) ainda não foi enviada.".format(p.numero_proposicao))
self.logger.error(
"user=" + username + ". Proposição (numero={}) ainda não foi enviada.".format(p.numero_proposicao))
msg_error = _('Proposição ainda não foi enviada.')
elif p.data_recebimento:
self.logger.error("user=" + username + ". Proposição (numero={}) já foi recebida, não é "
"possível retorná-la.".format(p.numero_proposicao))
"possível retorná-la.".format(p.numero_proposicao))
msg_error = _('Proposição já foi recebida, não é '
'possível retorná-la.')
else:
@ -816,7 +836,8 @@ class ProposicaoCrud(Crud):
ta.privacidade = STATUS_TA_PRIVATE
ta.editing_locked = False
ta.save()
self.logger.info("user=" + username + ". Proposição (numero={}) Retornada com sucesso.".format(p.numero_proposicao))
self.logger.info(
"user=" + username + ". Proposição (numero={}) Retornada com sucesso.".format(p.numero_proposicao))
messages.success(request, _(
'Proposição Retornada com sucesso.'))
@ -828,12 +849,14 @@ class ProposicaoCrud(Crud):
kwargs={'pk': kwargs['pk']}))
def dispatch(self, request, *args, **kwargs):
username = request.user.username.replace("'","")
username = request.user.username.replace("'", "")
try:
self.logger.debug("user=" + username + ". Tentando obter objeto Proposicao com pk={}".format(kwargs['pk']))
self.logger.debug(
"user=" + username + ". Tentando obter objeto Proposicao com pk={}".format(kwargs['pk']))
p = Proposicao.objects.get(id=kwargs['pk'])
except Exception as e:
self.logger.error("user=" + username + ". Erro ao obter proposicao com pk={}. Retornando 404. ".format(kwargs['pk']) + str(e))
self.logger.error(
"user=" + username + ". Erro ao obter proposicao com pk={}. Retornando 404. ".format(kwargs['pk']) + str(e))
raise Http404()
if not self.has_permission():
@ -869,18 +892,18 @@ class ProposicaoCrud(Crud):
id=kwargs['pk']).values_list(
'data_envio', 'data_recebimento')
username = request.user.username.replace("'","")
username = request.user.username.replace("'", "")
if proposicao:
if proposicao[0][0] and proposicao[0][1]:
self.logger.error("user=" + username + ". Proposição (id={}) já foi enviada e recebida."
"Não pode mais ser excluida.".format(kwargs['pk']))
"Não pode mais ser excluida.".format(kwargs['pk']))
msg = _('Proposição já foi enviada e recebida.'
'Não pode mais ser excluida.')
elif proposicao[0][0] and not proposicao[0][1]:
self.logger.error("user=" + username + ". Proposição (id={}) já foi enviada mas ainda não recebida "
"pelo protocolo. Use a opção Recuperar Proposição "
"para depois excluí-la.".format(kwargs['pk']))
"pelo protocolo. Use a opção Recuperar Proposição "
"para depois excluí-la.".format(kwargs['pk']))
msg = _('Proposição já foi enviada mas ainda não recebida '
'pelo protocolo. Use a opção Recuperar Proposição '
'para depois excluí-la.')
@ -899,19 +922,19 @@ class ProposicaoCrud(Crud):
proposicao = Proposicao.objects.filter(
id=kwargs['pk']).values_list(
'data_envio', 'data_recebimento')
username = request.user.username.replace("'","")
username = request.user.username.replace("'", "")
if proposicao:
if proposicao[0][0] and proposicao[0][1]:
self.logger.error('user=' + username + '. Proposição (id={}) já foi enviada e recebida.'
'Não pode mais ser editada'.format(kwargs['pk']))
'Não pode mais ser editada'.format(kwargs['pk']))
msg = _('Proposição já foi enviada e recebida.'
'Não pode mais ser editada')
elif proposicao[0][0] and not proposicao[0][1]:
self.logger.error('user=' + username + '. Proposição (id={}) já foi enviada mas ainda não recebida '
'pelo protocolo. Use a opção Recuperar Proposição '
'para voltar para edição.'.format(kwargs['pk']))
'pelo protocolo. Use a opção Recuperar Proposição '
'para voltar para edição.'.format(kwargs['pk']))
msg = _('Proposição já foi enviada mas ainda não recebida '
'pelo protocolo. Use a opção Recuperar Proposição '
'para voltar para edição.')
@ -924,7 +947,7 @@ class ProposicaoCrud(Crud):
def get_success_url(self):
tipo_texto = self.request.POST.get('tipo_texto', '')
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
if tipo_texto == 'T':
messages.info(self.request,
@ -933,9 +956,9 @@ class ProposicaoCrud(Crud):
'marcada, você será redirecionado para a '
'edição do Texto Eletrônico.'))
self.logger.debug('user=' + username + '. Sempre que uma Proposição é inclusa ou '
'alterada e a opção "Texto Articulado " for '
'marcada, você será redirecionado para a '
'edição do Texto Eletrônico.')
'alterada e a opção "Texto Articulado " for '
'marcada, você será redirecionado para a '
'edição do Texto Eletrônico.')
return reverse('sapl.materia:proposicao_ta',
kwargs={'pk': self.object.pk})
else:
@ -954,7 +977,7 @@ class ProposicaoCrud(Crud):
def get_success_url(self):
tipo_texto = self.request.POST.get('tipo_texto', '')
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
if tipo_texto == 'T':
messages.info(self.request,
@ -964,10 +987,10 @@ class ProposicaoCrud(Crud):
'Texto Eletrônico. Use a opção "Editar Texto" '
'para construir seu texto.'))
self.logger.debug('user=' + username + '. Sempre que uma Proposição é inclusa ou '
'alterada e a opção "Texto Articulado " for '
'marcada, você será redirecionado para o '
'Texto Eletrônico. Use a opção "Editar Texto" '
'para construir seu texto.')
'alterada e a opção "Texto Articulado " for '
'marcada, você será redirecionado para o '
'Texto Eletrônico. Use a opção "Editar Texto" '
'para construir seu texto.')
return reverse('sapl.materia:proposicao_ta',
kwargs={'pk': self.object.pk})
else:
@ -1037,18 +1060,19 @@ class ReciboProposicaoView(TemplateView):
def get(self, request, *args, **kwargs):
proposicao = Proposicao.objects.get(pk=self.kwargs['pk'])
username = request.user.username.replace("'","")
username = request.user.username.replace("'", "")
if proposicao.data_envio:
return TemplateView.get(self, request, *args, **kwargs)
if not proposicao.data_envio and not proposicao.data_devolucao:
self.logger.error('user=' + username + '. Não é possível gerar recibo para uma '
'Proposição (pk={}) ainda não enviada.'.format(self.kwargs['pk']))
'Proposição (pk={}) ainda não enviada.'.format(self.kwargs['pk']))
messages.error(request, _('Não é possível gerar recibo para uma '
'Proposição ainda não enviada.'))
elif proposicao.data_devolucao:
self.logger.error("user=" + username + ". Não é possível gerar recibo para proposicao de pk={}.".format(self.kwargs['pk']))
self.logger.error(
"user=" + username + ". Não é possível gerar recibo para proposicao de pk={}.".format(self.kwargs['pk']))
messages.error(request, _('Não é possível gerar recibo.'))
return redirect(reverse('sapl.materia:proposicao_detail',
@ -1067,18 +1091,21 @@ class RelatoriaCrud(MasterDetailCrud):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
try:
self.logger.debug("user=" + username + ". Tentando obter objeto Comissao de pk={}.".format(context['form'].initial['comissao']))
self.logger.debug("user=" + username + ". Tentando obter objeto Comissao de pk={}.".format(
context['form'].initial['comissao']))
comissao = Comissao.objects.get(
pk=context['form'].initial['comissao'])
except:
self.logger.error("user=" + username + ". Objeto Comissão de pk={} não encontrado.".format(context['form'].initial['comissao']))
self.logger.error("user=" + username + ". Objeto Comissão de pk={} não encontrado.".format(
context['form'].initial['comissao']))
pass
else:
self.logger.info("user=" + username + ". Objeto Comissao de pk={} obtido com sucesso.".format(context['form'].initial['comissao']))
self.logger.info("user=" + username + ". Objeto Comissao de pk={} obtido com sucesso.".format(
context['form'].initial['comissao']))
composicao = comissao.composicao_set.order_by(
'-periodo__data_inicio').first()
participacao = Participacao.objects.filter(
@ -1117,19 +1144,22 @@ class RelatoriaCrud(MasterDetailCrud):
logger = logging.getLogger(__name__)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
try:
self.logger.debug("user=" + username + ". Tentando obter objeto Comissao de pk={}.".format(context['form'].initial['comissao']))
self.logger.debug("user=" + username + ". Tentando obter objeto Comissao de pk={}.".format(
context['form'].initial['comissao']))
comissao = Comissao.objects.get(
pk=context['form'].initial['comissao'])
except ObjectDoesNotExist:
self.logger.error("user=" + username + ". Objeto Comissão de pk={} não encontrado.".format(context['form'].initial['comissao']))
except ObjectDoesNotExist:
self.logger.error("user=" + username + ". Objeto Comissão de pk={} não encontrado.".format(
context['form'].initial['comissao']))
pass
else:
self.logger.info("user=" + username + ". Objeto Comissao de pk={} obtido com sucesso.".format(context['form'].initial['comissao']))
else:
self.logger.info("user=" + username + ". Objeto Comissao de pk={} obtido com sucesso.".format(
context['form'].initial['comissao']))
composicao = comissao.composicao_set.order_by(
'-periodo__data_inicio').first()
participacao = Participacao.objects.filter(
@ -1180,7 +1210,7 @@ class TramitacaoCrud(MasterDetailCrud):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
ultima_tramitacao = Tramitacao.objects.filter(
materia_id=self.kwargs['pk']).order_by(
@ -1196,7 +1226,7 @@ class TramitacaoCrud(MasterDetailCrud):
ultima_tramitacao.unidade_tramitacao_destino)]
else:
self.logger.error('user=' + username + '. Unidade de tramitação destino '
'da última tramitação não pode ser vazia!')
'da última tramitação não pode ser vazia!')
msg = _('Unidade de tramitação destino '
' da última tramitação não pode ser vazia!')
messages.add_message(self.request, messages.ERROR, msg)
@ -1206,7 +1236,7 @@ class TramitacaoCrud(MasterDetailCrud):
def form_valid(self, form):
self.object = form.save()
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
if form.instance.status.indicador == 'F':
form.instance.materia.em_tramitacao = False
@ -1216,7 +1246,7 @@ class TramitacaoCrud(MasterDetailCrud):
try:
self.logger.debug("user=" + username + ". Tentando enviar Tramitacao (sender={}, post={}, request={})."
.format(Tramitacao, self.object, self.request))
.format(Tramitacao, self.object, self.request))
tramitacao_signal.send(sender=Tramitacao,
post=self.object,
request=self.request)
@ -1226,8 +1256,8 @@ class TramitacaoCrud(MasterDetailCrud):
'de matéria não enviado. Há problemas na configuração '
'do e-mail.')
self.logger.warning('user=' + username + '. Tramitação criada, mas e-mail de acompanhamento '
'de matéria não enviado. Há problemas na configuração '
'do e-mail. ' + str(e))
'de matéria não enviado. Há problemas na configuração '
'do e-mail. ' + str(e))
messages.add_message(self.request, messages.WARNING, msg)
return HttpResponseRedirect(self.get_success_url())
return super().form_valid(form)
@ -1240,7 +1270,7 @@ class TramitacaoCrud(MasterDetailCrud):
def form_valid(self, form):
self.object = form.save()
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
if form.instance.status.indicador == 'F':
form.instance.materia.em_tramitacao = False
@ -1250,7 +1280,7 @@ class TramitacaoCrud(MasterDetailCrud):
try:
self.logger.debug("user=" + username + ". Tentando enviar Tramitacao (sender={}, post={}, request={}"
.format(Tramitacao, self.object, self.request))
.format(Tramitacao, self.object, self.request))
tramitacao_signal.send(sender=Tramitacao,
post=self.object,
request=self.request)
@ -1289,13 +1319,13 @@ class TramitacaoCrud(MasterDetailCrud):
'-data_tramitacao',
'-timestamp',
'-id').first()
username = request.user.username.replace("'","")
username = request.user.username.replace("'", "")
if tramitacao.pk != ultima_tramitacao.pk:
self.logger.error("user=" + username + ". Não é possível deletar a tramitação de pk={}. "
"Somente a última tramitação (pk={}) pode ser deletada!."
.format(tramitacao.pk, ultima_tramitacao.pk))
.format(tramitacao.pk, ultima_tramitacao.pk))
msg = _('Somente a última tramitação pode ser deletada!')
messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(url)
@ -1639,8 +1669,9 @@ class AcompanhamentoConfirmarView(TemplateView):
logger = logging.getLogger(__name__)
def get_redirect_url(self, email):
username = self.request.user.username.replace("'","")
self.logger.debug('user=' + username + '. Esta matéria está sendo acompanhada pelo e-mail: %s' % (email))
username = self.request.user.username.replace("'", "")
self.logger.debug(
'user=' + username + '. Esta matéria está sendo acompanhada pelo e-mail: %s' % (email))
msg = _('Esta matéria está sendo acompanhada pelo e-mail: %s') % (
email)
messages.add_message(self.request, messages.SUCCESS, msg)
@ -1650,23 +1681,23 @@ class AcompanhamentoConfirmarView(TemplateView):
def get(self, request, *args, **kwargs):
materia_id = kwargs['pk']
hash_txt = request.GET.get('hash_txt', '')
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
try:
self.logger.info("user=" + username + ". Tentando obter objeto AcompanhamentoMateria (materia_id={}, hash={})."
.format(materia_id, hash_txt))
.format(materia_id, hash_txt))
acompanhar = AcompanhamentoMateria.objects.get(
materia_id=materia_id,
hash=hash_txt)
except ObjectDoesNotExist:
self.logger.error("user=" + username + ". Objeto AcompanhamentoMateria(materia_id={}, hash={}) não encontrado."
.format(materia_id, hash_txt))
.format(materia_id, hash_txt))
raise Http404()
except MultipleObjectsReturned as e:
# A melhor solução deve ser permitir que a exceção
# (MultipleObjectsReturned) seja lançada e vá para o log,
# pois só poderá ser causada por um erro de desenvolvimente
self.logger.error('user=' + username + '.' + str(e))
# A melhor solução deve ser permitir que a exceção
# (MultipleObjectsReturned) seja lançada e vá para o log,
# pois só poderá ser causada por um erro de desenvolvimente
self.logger.error('user=' + username + '.' + str(e))
pass
acompanhar.confirmado = True
acompanhar.save()
@ -1679,8 +1710,9 @@ class AcompanhamentoExcluirView(TemplateView):
logger = logging.getLogger(__name__)
def get_success_url(self):
username = self.request.user.username.replace("'","")
self.logger.debug("user=" + username + ". Você parou de acompanhar esta matéria.")
username = self.request.user.username.replace("'", "")
self.logger.debug("user=" + username +
". Você parou de acompanhar esta matéria.")
msg = _('Você parou de acompanhar esta matéria.')
messages.add_message(self.request, messages.INFO, msg)
return reverse('sapl.materia:materialegislativa_detail',
@ -1689,16 +1721,16 @@ class AcompanhamentoExcluirView(TemplateView):
def get(self, request, *args, **kwargs):
materia_id = kwargs['pk']
hash_txt = request.GET.get('hash_txt', '')
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
try:
self.logger.info("user=" + username + ". Tentando deletar objeto AcompanhamentoMateria (materia_id={}, hash={})."
.format(materia_id, hash_txt))
.format(materia_id, hash_txt))
AcompanhamentoMateria.objects.get(materia_id=materia_id,
hash=hash_txt).delete()
except ObjectDoesNotExist:
self.logger.error("user=" + username + ". Objeto AcompanhamentoMateria (materia_id={}, hash={}) não encontrado."
.format(materia_id, hash_txt))
.format(materia_id, hash_txt))
pass
return HttpResponseRedirect(self.get_success_url())
@ -1790,6 +1822,12 @@ class AcompanhamentoMateriaView(CreateView):
return ''.join(choice(s) for i in range(choice([6, 7])))
def get(self, request, *args, **kwargs):
if not mail_service_configured():
self.logger.warning(_('Servidor de email não configurado.'))
messages.error(request, _('Serviço de Acompanhamento de '
'Matérias não foi configurado'))
return redirect('/')
pk = self.kwargs['pk']
materia = MateriaLegislativa.objects.get(id=pk)
@ -1798,6 +1836,13 @@ class AcompanhamentoMateriaView(CreateView):
'materia': materia})
def post(self, request, *args, **kwargs):
if not settings.EMAIL_HOST:
self.logger.warning(_('Servidor de email não configurado.'))
messages.error(request, _('Serviço de Acompanhamento de '
'Matérias não foi configurado'))
return redirect('/')
form = AcompanhamentoMateriaForm(request.POST)
pk = self.kwargs['pk']
materia = MateriaLegislativa.objects.get(id=pk)
@ -1845,7 +1890,8 @@ class AcompanhamentoMateriaView(CreateView):
# Caso esse Acompanhamento já exista
# avisa ao usuário que essa matéria já está sendo acompanhada
else:
self.logger.debug("user=" + usuario.username + ". Este e-mail já está acompanhando essa matéria.")
self.logger.debug("user=" + usuario.username +
". Este e-mail já está acompanhando essa matéria.")
msg = _('Este e-mail já está acompanhando essa matéria.')
messages.add_message(request, messages.INFO, msg)
@ -1966,32 +2012,30 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
return context
def post(self, request, *args, **kwargs):
marcadas = request.POST.getlist('materia_id')
tz = timezone.get_current_timezone()
username = request.user.username.replace("'","")
username = request.user.username.replace("'", "")
if len(marcadas) == 0:
msg = _('Nenhuma máteria foi selecionada.')
messages.add_message(request, messages.ERROR, msg)
return self.get(request, self.kwargs)
obrigatorios = {'data_tramitacao':'Data da Tramitação',
'unidade_tramitacao_local':'Unidade Local',
'unidade_tramitacao_destino':'Unidade Destino',
'status':'Status',
'urgente':'Urgente',
'texto':'Texto da Ação'}
for field,nome in obrigatorios.items():
obrigatorios = {'data_tramitacao': 'Data da Tramitação',
'unidade_tramitacao_local': 'Unidade Local',
'unidade_tramitacao_destino': 'Unidade Destino',
'status': 'Status',
'urgente': 'Urgente',
'texto': 'Texto da Ação'}
for field, nome in obrigatorios.items():
if not request.POST[field]:
msg = _('Campo {} deve ser preenchido.'.format(nome))
messages.add_message(request, messages.ERROR, msg)
return self.get(request, self.kwargs)
if not request.POST['data_encaminhamento']:
data_encaminhamento = None
else:
@ -2026,15 +2070,16 @@ class PrimeiraTramitacaoEmLoteView(PermissionRequiredMixin, FilterView):
)
t.save()
try:
self.logger.debug("user=" + username + ". Tentando enviar tramitação.")
self.logger.debug("user=" + username +
". Tentando enviar tramitação.")
tramitacao_signal.send(sender=Tramitacao,
post=t,
request=self.request)
except Exception as e:
self.logger.error('user=' + username + '. Tramitação criada , mas e-mail de acompanhamento '
'de matéria não enviado. Há problemas na configuração '
'do e-mail. ' + str(e))
'de matéria não enviado. Há problemas na configuração '
'do e-mail. ' + str(e))
flag_error = True
if flag_error:
msg = _('Tramitação criada, mas e-mail de acompanhamento '
@ -2187,16 +2232,16 @@ class FichaSelecionaView(PermissionRequiredMixin, FormView):
context['form'].fields['materia'].choices = [
(m.id, str(m)) for m in materia_list]
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
if context['quantidade'] > 100:
self.logger.info('user=' + username + '. Sua pesquisa (tipo={}, data_inicial={}, data_final={}) retornou mais do que '
'100 impressos. Por questões de '
'performance, foram retornados '
'apenas os 100 primeiros. Caso '
'queira outros, tente fazer uma '
'pesquisa mais específica'.format(tipo, data_inicial, data_final))
'100 impressos. Por questões de '
'performance, foram retornados '
'apenas os 100 primeiros. Caso '
'queira outros, tente fazer uma '
'pesquisa mais específica'.format(tipo, data_inicial, data_final))
messages.info(self.request, _('Sua pesquisa retornou mais do que '
'100 impressos. Por questões de '
'performance, foram retornados '
@ -2208,14 +2253,16 @@ class FichaSelecionaView(PermissionRequiredMixin, FormView):
def form_valid(self, form):
context = {}
username = self.request.user.username.replace("'","")
username = self.request.user.username.replace("'", "")
try:
self.logger.debug("user=" + username + ". Tentando obter objeto MateriaLegislativa com id={}".format(form.data['materia']))
self.logger.debug(
"user=" + username + ". Tentando obter objeto MateriaLegislativa com id={}".format(form.data['materia']))
materia = MateriaLegislativa.objects.get(
id=form.data['materia'])
except ObjectDoesNotExist:
self.logger.error("user=" + username + ". Esta MáteriaLegislativa não existe (id={}).".format(form.data['materia']))
self.logger.error(
"user=" + username + ". Esta MáteriaLegislativa não existe (id={}).".format(form.data['materia']))
mensagem = _('Esta Máteria não existe!')
self.messages.add_message(self.request, messages.INFO, mensagem)

104
sapl/protocoloadm/views.py

@ -1,8 +1,10 @@
from datetime import datetime
import logging
from random import choice
from string import ascii_letters, digits
from braces.views import FormValidMessageMixin
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin
@ -21,17 +23,18 @@ from django.views.generic.edit import FormView
from django_filters.views import FilterView
import sapl
import logging
from sapl.comissoes.models import Comissao
from sapl.base.email_utils import do_envia_email_confirmacao
from sapl.base.models import Autor, CasaLegislativa
from sapl.base.signals import tramitacao_signal
from sapl.comissoes.models import Comissao
from sapl.crud.base import Crud, CrudAux, MasterDetailCrud, make_pagination
from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa
from sapl.parlamentares.models import Legislatura, Parlamentar
from sapl.protocoloadm.models import Protocolo
from sapl.utils import (create_barcode, get_base_url, get_client_ip,
get_mime_type_from_file_extension,
show_results_filter_set)
from sapl.base.email_utils import do_envia_email_confirmacao
show_results_filter_set, mail_service_configured)
from .forms import (AcompanhamentoDocumentoForm, AnularProcoloAdmForm,
DocumentoAcessorioAdministrativoForm,
DocumentoAdministrativoFilterSet,
@ -44,7 +47,6 @@ from .forms import (AcompanhamentoDocumentoForm, AnularProcoloAdmForm,
from .models import (AcompanhamentoDocumento, DocumentoAcessorioAdministrativo,
DocumentoAdministrativo, StatusTramitacaoAdministrativo,
TipoDocumentoAdministrativo, TramitacaoAdministrativo)
from sapl.base.signals import tramitacao_signal
TipoDocumentoAdministrativoCrud = CrudAux.build(
@ -63,21 +65,23 @@ def recuperar_materia_protocolo(request):
logger = logging.getLogger(__name__)
username = request.user.username
try:
logger.debug("user=" + username + ". Tentando obter matéria com tipo={}, ano={} e numero={}.".format(tipo, ano, numero))
logger.debug("user=" + username +
". Tentando obter matéria com tipo={}, ano={} e numero={}.".format(tipo, ano, numero))
materia = MateriaLegislativa.objects.get(
tipo=tipo, ano=ano,numero=numero)
tipo=tipo, ano=ano, numero=numero)
autoria = materia.autoria_set.first()
content = {'ementa': materia.ementa.strip(),
'ano':materia.ano, 'numero':materia.numero}
'ano': materia.ano, 'numero': materia.numero}
if autoria:
content.update({'autor': autoria.autor.pk,
'tipo_autor':autoria.autor.tipo.pk})
'tipo_autor': autoria.autor.tipo.pk})
response = JsonResponse(content)
except Exception as e:
logger.error("user=" + username + ". " + str(e))
response = JsonResponse({'error':e})
response = JsonResponse({'error': e})
return response
def doc_texto_integral(request, pk):
can_see = True
@ -102,13 +106,15 @@ def doc_texto_integral(request, pk):
return response
raise Http404
class AcompanhamentoConfirmarView(TemplateView):
logger = logging.getLogger(__name__)
def get_redirect_url(self, email):
username = self.request.user.username
self.logger.info('user=' + username + '. Este documento está sendo acompanhado pelo e-mail: {}'.format(email))
self.logger.info(
'user=' + username + '. Este documento está sendo acompanhado pelo e-mail: {}'.format(email))
msg = _('Este documento está sendo acompanhado pelo e-mail: %s') % (
email)
messages.add_message(self.request, messages.SUCCESS, msg)
@ -116,6 +122,7 @@ class AcompanhamentoConfirmarView(TemplateView):
kwargs={'pk': self.kwargs['pk']})
def get(self, request, *args, **kwargs):
documento_id = kwargs['pk']
hash_txt = request.GET.get('hash_txt', '')
username = request.user.username
@ -146,7 +153,8 @@ class AcompanhamentoExcluirView(TemplateView):
def get_success_url(self):
username = self.request.user.username
self.logger.info("user=" + username + ". Você parou de acompanhar este Documento (pk={}).".format(self.kwargs['pk']))
self.logger.info(
"user=" + username + ". Você parou de acompanhar este Documento (pk={}).".format(self.kwargs['pk']))
msg = _('Você parou de acompanhar este Documento.')
messages.add_message(self.request, messages.INFO, msg)
return reverse('sapl.protocoloadm:documentoadministrativo_detail',
@ -160,7 +168,7 @@ class AcompanhamentoExcluirView(TemplateView):
self.logger.debug("user=" + username + ". Tentando obter AcompanhamentoDocumento com documento_id={} e hash={}."
.format(documento_id, hash_txt))
AcompanhamentoDocumento.objects.get(documento_id=documento_id,
hash=hash_txt).delete()
hash=hash_txt).delete()
except ObjectDoesNotExist:
self.logger.error("user=" + username + ". AcompanhamentoDocumento com documento_id={} e hash={} não encontrado."
.format(documento_id, hash_txt))
@ -178,6 +186,12 @@ class AcompanhamentoDocumentoView(CreateView):
return ''.join(choice(s) for i in range(choice([6, 7])))
def get(self, request, *args, **kwargs):
if not mail_service_configured():
self.logger.warning(_('Servidor de email não configurado.'))
messages.error(request, _('Serviço de Acompanhamento de '
'Documentos não foi configurado'))
return redirect('/')
pk = self.kwargs['pk']
documento = DocumentoAdministrativo.objects.get(id=pk)
@ -186,6 +200,12 @@ class AcompanhamentoDocumentoView(CreateView):
'documento': documento})
def post(self, request, *args, **kwargs):
if not mail_service_configured():
self.logger.warning(_('Servidor de email não configurado.'))
messages.error(request, _('Serviço de Acompanhamento de '
'Documentos não foi configurado'))
return redirect('/')
form = AcompanhamentoDocumentoForm(request.POST)
pk = self.kwargs['pk']
documento = DocumentoAdministrativo.objects.get(id=pk)
@ -233,7 +253,8 @@ class AcompanhamentoDocumentoView(CreateView):
# Caso esse Acompanhamento já exista
# avisa ao usuário que esse documento já está sendo acompanhado
else:
self.logger.info('user=' + request.user.username + '. Este e-mail já está acompanhando esse documento (pk={}).'.format(pk))
self.logger.info('user=' + request.user.username +
'. Este e-mail já está acompanhando esse documento (pk={}).'.format(pk))
msg = _('Este e-mail já está acompanhando esse documento.')
messages.add_message(request, messages.INFO, msg)
@ -474,7 +495,8 @@ class ProtocoloDocumentoView(PermissionRequiredMixin,
protocolo = form.save(commit=False)
username = self.request.user.username
try:
self.logger.debug("user=" + username + ". Tentando obter sequência de numeração.")
self.logger.debug("user=" + username +
". Tentando obter sequência de numeração.")
numeracao = sapl.base.models.AppConfig.objects.last(
).sequencia_numeracao
except AttributeError as e:
@ -504,10 +526,13 @@ class ProtocoloDocumentoView(PermissionRequiredMixin,
protocolo.tipo_processo = '0' # TODO validar o significado
protocolo.anulado = False
if not protocolo.numero:
protocolo.numero = (numero['numero__max'] + 1) if numero['numero__max'] else 1
protocolo.numero = (
numero['numero__max'] + 1) if numero['numero__max'] else 1
elif protocolo.numero < (numero['numero__max'] + 1) if numero['numero__max'] else 0:
msg = _('Número de protocolo deve ser maior que {}'.format(numero['numero__max']))
self.logger.error("user=" + username + ". Número de protocolo deve ser maior que {}.".format(numero['numero__max']))
msg = _('Número de protocolo deve ser maior que {}'.format(
numero['numero__max']))
self.logger.error(
"user=" + username + ". Número de protocolo deve ser maior que {}.".format(numero['numero__max']))
messages.add_message(self.request, messages.ERROR, msg)
return self.render_to_response(self.get_context_data())
protocolo.ano = timezone.now().year
@ -564,7 +589,8 @@ class ProtocoloMostrarView(PermissionRequiredMixin, TemplateView):
if protocolo.tipo_materia:
self.logger.debug(
"user=" + username + ". Tentando obter objeto MateriaLegislativa com numero_protocolo={} e ano={}."
"user=" + username +
". Tentando obter objeto MateriaLegislativa com numero_protocolo={} e ano={}."
.format(protocolo.numero, protocolo.ano))
materia = MateriaLegislativa.objects.filter(
numero_protocolo=protocolo.numero, ano=protocolo.ano)
@ -636,7 +662,8 @@ class ProtocoloMateriaView(PermissionRequiredMixin, CreateView):
protocolo = form.save(commit=False)
username = self.request.user.username
try:
self.logger.debug("user=" + username + ". Tentando obter sequência de numeração.")
self.logger.debug("user=" + username +
". Tentando obter sequência de numeração.")
numeracao = sapl.base.models.AppConfig.objects.last(
).sequencia_numeracao
except AttributeError:
@ -667,12 +694,14 @@ class ProtocoloMateriaView(PermissionRequiredMixin, CreateView):
numero['numero__max'] = 0
if not protocolo.numero:
protocolo.numero = (numero['numero__max'] + 1) if numero['numero__max'] else 1
protocolo.numero = (
numero['numero__max'] + 1) if numero['numero__max'] else 1
if numero['numero__max']:
if protocolo.numero < (numero['numero__max'] + 1):
self.logger.error("user=" + username + ". Número de protocolo ({}) é menor que {}"
.format(protocolo.numero, numero['numero__max']))
msg = _('Número de protocolo deve ser maior que {}').format(numero['numero__max'])
msg = _('Número de protocolo deve ser maior que {}').format(
numero['numero__max'])
messages.add_message(self.request, messages.ERROR, msg)
return self.render_to_response(self.get_context_data())
protocolo.ano = timezone.now().year
@ -766,11 +795,11 @@ class PesquisarDocumentoAdministrativoView(DocumentoAdministrativoMixin,
qs = self.get_queryset()
qs = qs.prefetch_related("documentoacessorioadministrativo_set",
"tramitacaoadministrativo_set",
"tipo",
"tramitacaoadministrativo_set__status",
"tramitacaoadministrativo_set__unidade_tramitacao_local",
"tramitacaoadministrativo_set__unidade_tramitacao_destino")
"tramitacaoadministrativo_set",
"tipo",
"tramitacaoadministrativo_set__status",
"tramitacaoadministrativo_set__unidade_tramitacao_local",
"tramitacaoadministrativo_set__unidade_tramitacao_destino")
if status_tramitacao and unidade_destino:
lista = filtra_tramitacao_adm_destino_and_status(status_tramitacao,
@ -788,7 +817,6 @@ class PesquisarDocumentoAdministrativoView(DocumentoAdministrativoMixin,
if 'o' in self.request.GET and not self.request.GET['o']:
qs = qs.order_by('-ano', '-numero')
kwargs.update({
'queryset': qs,
})
@ -823,14 +851,15 @@ class PesquisarDocumentoAdministrativoView(DocumentoAdministrativoMixin,
url = ''
self.filterset.form.fields['o'].label = _('Ordenação')
# é usada essa verificação anônima para quando os documentos administrativos
# estão no modo ostensivo, mas podem existir documentos administrativos restritos
# é usada essa verificação anônima para quando os documentos administrativos
# estão no modo ostensivo, mas podem existir documentos administrativos
# restritos
if request.user.is_anonymous():
length = self.object_list.filter(restrito=False).count()
else:
length = self.object_list.count()
context = self.get_context_data(filter=self.filterset,
filter_url=url,
numero_res=length
@ -864,7 +893,7 @@ class TramitacaoAdmCrud(MasterDetailCrud):
if local:
initial['unidade_tramitacao_local'
] = local.unidade_tramitacao_destino.pk
] = local.unidade_tramitacao_destino.pk
else:
initial['unidade_tramitacao_local'] = ''
initial['data_tramitacao'] = timezone.now().date()
@ -905,6 +934,7 @@ class TramitacaoAdmCrud(MasterDetailCrud):
class UpdateView(MasterDetailCrud.UpdateView):
form_class = TramitacaoAdmEditForm
logger = logging.getLogger(__name__)
def form_valid(self, form):
self.object = form.save()
username = self.request.user.username
@ -918,8 +948,8 @@ class TramitacaoAdmCrud(MasterDetailCrud):
'não enviado. A não configuração do servidor de e-mail '
'impede o envio de aviso de tramitação. ' + str(e))
msg = _('Tramitação criada, mas e-mail de acompanhamento '
'de documento não enviado. A não configuração do'
' servidor de e-mail impede o envio de aviso de tramitação')
'de documento não enviado. A não configuração do'
' servidor de e-mail impede o envio de aviso de tramitação')
messages.add_message(self.request, messages.WARNING, msg)
return HttpResponseRedirect(self.get_success_url())
return super().form_valid(form)
@ -1038,8 +1068,8 @@ class DesvincularMateriaView(PermissionRequiredMixin, FormView):
def form_valid(self, form):
materia = MateriaLegislativa.objects.get(numero=form.cleaned_data['numero'],
ano=form.cleaned_data['ano'],
tipo=form.cleaned_data['tipo'])
ano=form.cleaned_data['ano'],
tipo=form.cleaned_data['tipo'])
materia.numero_protocolo = None
materia.save()
return redirect(self.get_success_url())

11
sapl/settings.py

@ -13,8 +13,8 @@ Quick-start development settings - unsuitable for production
See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
"""
import socket
import logging
import socket
from decouple import config
from dj_database_url import parse as db_url
@ -24,6 +24,7 @@ from unipath import Path
from .temp_suppress_crispy_form_warnings import \
SUPRESS_CRISPY_FORM_WARNINGS_LOGGING
host = socket.gethostbyname_ex(socket.gethostname())[0]
BASE_DIR = Path(__file__).ancestor(1)
@ -181,6 +182,7 @@ TEMPLATES = [
"django.template.context_processors.static",
'django.contrib.messages.context_processors.messages',
'sapl.context_processors.parliament_info',
'sapl.context_processors.mail_service_configured',
],
'debug': DEBUG
},
@ -223,6 +225,7 @@ EMAIL_USE_TLS = config('EMAIL_USE_TLS', cast=bool, default=True)
EMAIL_SEND_USER = config('EMAIL_SEND_USER', cast=str, default='')
DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL', cast=str, default='')
SERVER_EMAIL = config('SERVER_EMAIL', cast=str, default='')
EMAIL_RUNNING = None
MAX_DOC_UPLOAD_SIZE = 60 * 1024 * 1024 # 60MB
MAX_IMAGE_UPLOAD_SIZE = 2 * 1024 * 1024 # 2MB
@ -314,10 +317,10 @@ LOGGING = {
'formatter': 'simple',
},
'applogfile': {
'level':'INFO',
'class':'logging.handlers.RotatingFileHandler',
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': 'sapl.log',
'maxBytes': 1024*1024*15, # 15MB
'maxBytes': 1024 * 1024 * 15, # 15MB
'backupCount': 10,
'formatter': 'verbose',
},

2
sapl/templates/materia/materialegislativa_detail.html

@ -2,7 +2,7 @@
{% load i18n %}
{% block sub_actions %}
{{ block.super }}
{% if object.em_tramitacao %}
{% if object.em_tramitacao and mail_service_configured %}
<div class="actions btn-group btn-group-sm" role="group">
<a href="{% url 'sapl.materia:acompanhar_materia' object.id %}" class="btn btn-default">Acompanhar Matéria</a>
</div>

2
sapl/templates/materia/materialegislativa_filter.html

@ -145,7 +145,7 @@
{% endfor %}
{% endif %}
<p></p>
{% if m.em_tramitacao %}
{% if m.em_tramitacao and mail_service_configured %}
<a href="{% url 'sapl.materia:acompanhar_materia' m.id %}">Acompanhar Matéria</a>
{% endif %}
</td>

2
sapl/templates/protocoloadm/documentoadministrativo_filter.html

@ -63,7 +63,7 @@
{% if d.texto_integral %}
<strong><a href="{{ d.texto_integral.url }}">Texto Integral</a></strong></br>
{% endif %}
{% if d.tramitacao %}
{% if d.tramitacao and mail_service_configured %}
<a href="{% url 'sapl.protocoloadm:acompanhar_documento' d.id %}">Acompanhar Documento</a>
{% endif %}
</td>

19
sapl/utils.py

@ -15,6 +15,7 @@ from django.contrib import admin
from django.contrib.contenttypes.fields import (GenericForeignKey, GenericRel,
GenericRelation)
from django.core.exceptions import ValidationError
from django.core.mail import get_connection
from django.db.models import Q
from django.utils import six, timezone
from django.utils.translation import ugettext_lazy as _
@ -28,11 +29,13 @@ from unipath.path import Path
from sapl.crispy_layout_mixin import SaplFormLayout, form_actions, to_row
# (26/10/2018): O separador foi mudador de '/' para 'K'
# por conta dos leitores de códigos de barra, que trocavam
# a '/' por '&' ou ';'
SEPARADOR_HASH_PROPOSICAO = 'K'
def pil_image(source, exif_orientation=False, **options):
return source_generators.pil_image(source, exif_orientation, **options)
@ -767,3 +770,19 @@ def RemoveTag(texto):
def remover_acentos(string):
return unicodedata.normalize('NFKD', string).encode('ASCII', 'ignore').decode()
def mail_service_configured(request=None):
if settings.EMAIL_RUNNING is None:
result = True
try:
connection = get_connection()
connection.open()
except Exception as e:
result = False
finally:
connection.close()
settings.EMAIL_RUNNING = result
return settings.EMAIL_RUNNING

Loading…
Cancel
Save