Browse Source

Merge branch '3.1.x' into 3194_colocando_campo_observacao_junto_de_ementa_em_sessao_plenaria

pull/3198/head
Edward 5 years ago
committed by GitHub
parent
commit
070f5db04e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .travis.yml
  2. 2
      docker-compose-dev.yml
  3. 2
      docker-compose.yml
  4. 38
      docs/howtogit.rst
  5. 1
      requirements/requirements.txt
  6. 2
      sapl/api/serializers.py
  7. 16
      sapl/audiencia/forms.py
  8. 168
      sapl/base/forms.py
  9. 24
      sapl/base/models.py
  10. 4
      sapl/base/urls.py
  11. 105
      sapl/base/views.py
  12. 106
      sapl/comissoes/forms.py
  13. 10
      sapl/crud/base.py
  14. 38
      sapl/materia/forms.py
  15. 23
      sapl/materia/migrations/0068_configetiquetamaterialegislativa.py
  16. 20
      sapl/materia/migrations/0069_auto_20200518_1519.py
  17. 8
      sapl/materia/models.py
  18. 4
      sapl/materia/urls.py
  19. 247
      sapl/materia/views.py
  20. 2
      sapl/norma/forms.py
  21. 8
      sapl/norma/views.py
  22. 11
      sapl/parlamentares/forms.py
  23. 3
      sapl/parlamentares/views.py
  24. 21
      sapl/protocoloadm/migrations/0033_auto_20200708_1312.py
  25. 61
      sapl/protocoloadm/models.py
  26. 4
      sapl/protocoloadm/views.py
  27. 8
      sapl/relatorios/urls.py
  28. 59
      sapl/relatorios/views.py
  29. 1
      sapl/rules/map_rules.py
  30. 158
      sapl/sessao/views.py
  31. 2
      sapl/settings.py
  32. 3
      sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js
  33. BIN
      sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.LICENSE.txt.gz
  34. BIN
      sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.gz
  35. 1
      sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.map
  36. BIN
      sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.map.gz
  37. 3
      sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js
  38. 4
      sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.LICENSE.txt
  39. BIN
      sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.LICENSE.txt.gz
  40. BIN
      sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.gz
  41. 1
      sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.map
  42. BIN
      sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.map.gz
  43. 4
      sapl/static/sapl/frontend/js/parlamentar.307451cf.js
  44. BIN
      sapl/static/sapl/frontend/js/parlamentar.307451cf.js.gz
  45. 1
      sapl/static/sapl/frontend/js/parlamentar.307451cf.js.map
  46. BIN
      sapl/static/sapl/frontend/js/parlamentar.307451cf.js.map.gz
  47. BIN
      sapl/static/sapl/frontend/js/parlamentar.35e37659.js.gz
  48. 1
      sapl/static/sapl/frontend/js/parlamentar.35e37659.js.map
  49. BIN
      sapl/static/sapl/frontend/js/parlamentar.35e37659.js.map.gz
  50. 2
      sapl/templates/base.html
  51. 14
      sapl/templates/base/autor_detail.html
  52. 51
      sapl/templates/base/autor_filter.html
  53. 19
      sapl/templates/materia/config_etiqueta_materia.html
  54. 6
      sapl/templates/materia/layouts.yaml
  55. 6
      sapl/templates/materia/materialegislativa_detail.html
  56. 2
      sapl/templates/materia/materialegislativa_filter.html
  57. 38
      sapl/templates/materia/materialegislativa_form.html
  58. 2
      sapl/templates/materia/tramitacao_detail.html
  59. 10
      sapl/templates/menu_tabelas_auxiliares.yaml
  60. 104
      sapl/templates/norma/normajuridica_form.html
  61. 3
      sapl/templates/relatorios/blocos_sessao_plenaria/materias_expediente.html
  62. 3
      sapl/templates/relatorios/blocos_sessao_plenaria/materias_ordemdia.html
  63. 40
      sapl/templates/relatorios/etiqueta_materia_legislativa.html
  64. 4
      sapl/templates/relatorios/relatorio_pauta_sessao.html
  65. 3
      sapl/templates/sessao/blocos_ata/materias_expediente.html
  66. 3
      sapl/templates/sessao/blocos_ata/materias_ordem_dia.html
  67. 5
      sapl/templates/sessao/blocos_resumo/materias_expediente.html
  68. 5
      sapl/templates/sessao/blocos_resumo/materias_ordem_dia.html
  69. 17
      sapl/templates/sessao/oradores_create.html
  70. 2
      sapl/webpack-stats.json
  71. 35
      scripts/gerar_hash_proposicoes.py
  72. 2
      setup.py

2
.travis.yml

@ -1,7 +1,7 @@
language: python
python:
- 3.5
- 3.6
services:
- postgresql

2
docker-compose-dev.yml

@ -4,7 +4,6 @@ services:
sapldb-dev:
container_name: sapldb-dev
image: postgres:10.5-alpine
restart: always
environment:
POSTGRES_PASSWORD: sapl
POSTGRES_USER: sapl
@ -16,7 +15,6 @@ services:
sapl-dev:
container_name: sapl-dev
restart: always
image: sapl:dev
build:
context: .

2
docker-compose.yml

@ -26,7 +26,7 @@ services:
networks:
- sapl-net
sapl:
image: interlegis/sapl:3.1.161-RC2
image: interlegis/sapl:3.1.161-RC3
#build: .
restart: always
environment:

38
docs/howtogit.rst

@ -1,15 +1,17 @@
De forma muito simples e em linhas gerais o básico sobre GIT
====
De forma muito simples e em linhas gerais o básico sobre Git
====
Glosário
---------
Git - Sistema de controle de versão de aquivos
GitHub - É um serviço web que oferece diversas funcionalidades extras aplicadas ao git
GitHub - É um serviço web que oferece diversas funcionalidades extras aplicadas ao Git
Branch - Significa ramificar seu projeto, criar um snapshot.
Branch - Significa ramificar seu projeto, criar um snapshot
Merge - Significa incorporar seu branch no master
Merge - Significa incorporar seu branch ao master
Pode ser útil
@ -23,55 +25,49 @@ Exibir informações:
git status
Ver repositorio
Ver repositório:
git remote -v
Para definir repositorio
Definir repositório:
git remote set-url origin https://github.com/interlegis/sapl.git
Para criar um branch
Criar um branch:
git checkout -b nome_branch
git add arquivos
Para remover um branch
Remover um branch:
git branch -d nome-branch
Para comitar
Commitar:
git commit -m "Comentário"
Para enviar o branch
Enviar o branch:
git push origin nome_branch
Na base local descartar alguma alteração feita nos arquivos:
Na base local, descartar alguma alteração feita nos arquivos:
git checkout -- <arquivo>
Ao invés dissoremover todas as alterações e commits locais, recuperar o histórico mais recente do servidor e apontar para seu branch master local
Ao invés disso, remover todas as alterações e commits locais, recuperar o histórico mais recente do servidor e apontar para seu branch master local:
git fetch origin
git reset --hard origin/master
Atualizar para alguma brach especifica (ex:785-atualizar-migracao):
Atualizar para algum branch específico (ex:785-atualizar-migracao):
git checkout 785-atualizar-migracao
Voltar para a branch master
Voltar para a branch master:
git checkout master
Verificar 5 ultimos comits:
Verificar os últimos 5 commits:
git log --oneline -n 5

1
requirements/requirements.txt

@ -31,6 +31,7 @@ more-itertools==8.2.0
pysolr==3.6.0
PyPDF4==1.27.0
pyoai==2.5.0
Unidecode==1.1.1
git+https://github.com/interlegis/trml2pdf
git+https://github.com/interlegis/django-admin-bootstrapped

2
sapl/api/serializers.py

@ -139,7 +139,7 @@ class ParlamentarResumeSerializer(serializers.ModelSerializer):
# Caso não exista filiação com essas condições
except ObjectDoesNotExist:
self.logger.error("user=" + username + ". Parlamentar com (data<={} e data_desfiliacao>={}) "
self.logger.warning("user=" + username + ". Parlamentar com (data<={} e data_desfiliacao>={}) "
"ou (data<={} e data_desfiliacao=Null)) não possui filiação."
.format(legislatura.data_fim, legislatura.data_fim, legislatura.data_fim))
filiacao = 'Não possui filiação'

16
sapl/audiencia/forms.py

@ -95,8 +95,10 @@ class AudienciaForm(FileFieldCheckMixin, forms.ModelForm):
except ObjectDoesNotExist:
msg = _('A matéria %s%s/%s não existe no cadastro'
' de matérias legislativas.' % (tipo_materia, materia, ano_materia))
self.logger.error('A MateriaLegislativa %s%s/%s não existe no cadastro'
' de matérias legislativas.' % (tipo_materia, materia, ano_materia))
self.logger.warn(
'A MateriaLegislativa %s%s/%s não existe no cadastro'
' de matérias legislativas.' % (tipo_materia, materia, ano_materia)
)
raise ValidationError(msg)
else:
self.logger.info("MateriaLegislativa %s%s/%s obtida com sucesso." % (tipo_materia, materia, ano_materia))
@ -106,8 +108,10 @@ class AudienciaForm(FileFieldCheckMixin, forms.ModelForm):
campos = [materia, tipo_materia, ano_materia]
if campos.count(None) + campos.count('') < len(campos):
msg = _('Preencha todos os campos relacionados à Matéria Legislativa')
self.logger.error('Algum campo relacionado à MatériaLegislativa %s%s/%s \
não foi preenchido.' % (tipo_materia, materia, ano_materia))
self.logger.warn(
'Algum campo relacionado à MatériaLegislativa %s%s/%s \
não foi preenchido.' % (tipo_materia, materia, ano_materia)
)
raise ValidationError(msg)
if not cleaned_data['numero']:
@ -122,7 +126,9 @@ class AudienciaForm(FileFieldCheckMixin, forms.ModelForm):
if self.cleaned_data['hora_fim'] < self.cleaned_data['hora_inicio']:
msg = _('A hora de fim ({}) não pode ser anterior a hora de início({})'
.format(self.cleaned_data['hora_fim'], self.cleaned_data['hora_inicio']))
self.logger.error('Hora de fim anterior à hora de início.')
self.logger.warn(
'Hora de fim anterior à hora de início.'
)
raise ValidationError(msg)
if parlamentar_autor.autor.first() not in requerimento.autores.all():

168
sapl/base/forms.py

@ -117,8 +117,7 @@ class UsuarioCreateForm(ModelForm):
data = self.cleaned_data
if data['password1'] != data['password2']:
self.logger.error('Erro de validação. Senhas informadas ({}, {}) são diferentes.'.format(
data['password1'], data['password2']))
self.logger.warn('Erro de validação. Senhas informadas são diferentes.')
raise ValidationError('Senhas informadas são diferentes')
return data
@ -252,8 +251,7 @@ class UsuarioEditForm(ModelForm):
data = self.cleaned_data
if data['password1'] and data['password1'] != data['password2']:
self.logger.error("Erro de validação. Senhas informadas ({}, {}) são diferentes."
.format(data['password1'], data['password2']))
self.logger.warn("Erro de validação. Senhas informadas são diferentes.")
raise ValidationError('Senhas informadas são diferentes')
return data
@ -316,30 +314,37 @@ class SessaoLegislativaForm(FileFieldCheckMixin, ModelForm):
ult = 0
if numero <= ult and flag_edit:
self.logger.error('O número da SessaoLegislativa ({}) é menor ou igual '
'que o de Sessões Legislativas passadas ({})'.format(numero, ult))
self.logger.warn(
'O número da SessaoLegislativa ({}) é menor ou igual '
'que o de Sessões Legislativas passadas ({})'.format(numero, ult)
)
raise ValidationError('O número da Sessão Legislativa não pode ser menor ou igual '
'que o de Sessões Legislativas passadas')
if data_inicio < data_inicio_leg or \
data_inicio > data_fim_leg:
self.logger.error('A data de início ({}) da SessaoLegislativa está compreendida '
self.logger.warn(
'A data de início ({}) da SessaoLegislativa está compreendida '
'fora da data início ({}) e fim ({}) da Legislatura '
'selecionada'.format(data_inicio, data_inicio_leg, data_fim_leg))
'selecionada'.format(data_inicio, data_inicio_leg, data_fim_leg)
)
raise ValidationError('A data de início da Sessão Legislativa deve estar compreendida '
'entre a data início e fim da Legislatura selecionada')
if data_fim > data_fim_leg or \
data_fim < data_inicio_leg:
self.logger.error('A data de fim ({}) da SessaoLegislativa está compreendida '
self.logger.warn(
'A data de fim ({}) da SessaoLegislativa está compreendida '
'fora da data início ({}) e fim ({}) da Legislatura '
'selecionada.'.format(data_fim, data_inicio_leg, data_fim_leg))
'selecionada.'.format(data_fim, data_inicio_leg, data_fim_leg)
)
raise ValidationError('A data de fim da Sessão Legislativa deve estar compreendida '
'entre a data início e fim da Legislatura selecionada')
if data_inicio > data_fim:
self.logger.error(
'Data início ({}) superior à data fim ({}).'.format(data_inicio, data_fim))
self.logger.warn(
'Data início ({}) superior à data fim ({}).'.format(data_inicio, data_fim)
)
raise ValidationError(
'Data início não pode ser superior à data fim')
@ -348,8 +353,10 @@ class SessaoLegislativaForm(FileFieldCheckMixin, ModelForm):
if data_inicio_intervalo and data_fim_intervalo and \
data_inicio_intervalo > data_fim_intervalo:
self.logger.error('Data início de intervalo ({}) superior à '
'data fim de intervalo ({}).'.format(data_inicio_intervalo, data_fim_intervalo))
self.logger.warn(
'Data início de intervalo ({}) superior à '
'data fim de intervalo ({}).'.format(data_inicio_intervalo, data_fim_intervalo)
)
raise ValidationError('Data início de intervalo não pode ser '
'superior à data fim de intervalo')
@ -358,10 +365,13 @@ class SessaoLegislativaForm(FileFieldCheckMixin, ModelForm):
data_inicio_intervalo < data_inicio_leg or \
data_inicio_intervalo > data_fim or \
data_inicio_intervalo > data_fim_leg:
self.logger.error('A data de início do intervalo ({}) não está compreendida entre '
self.logger.warn(
'A data de início do intervalo ({}) não está compreendida entre '
'as datas de início ({}) e fim ({}) tanto da Legislatura quanto da '
'própria Sessão Legislativa ({} e {}).'
.format(data_inicio_intervalo, data_inicio_leg, data_fim_leg, data_inicio, data_fim))
'própria Sessão Legislativa ({} e {}).'.format(
data_inicio_intervalo, data_inicio_leg, data_fim_leg, data_inicio, data_fim
)
)
raise ValidationError('A data de início do intervalo deve estar compreendida entre '
'as datas de início e fim tanto da Legislatura quanto da '
'própria Sessão Legislativa')
@ -370,10 +380,13 @@ class SessaoLegislativaForm(FileFieldCheckMixin, ModelForm):
data_fim_intervalo > data_fim_leg or \
data_fim_intervalo < data_inicio or \
data_fim_intervalo < data_inicio_leg:
self.logger.error('A data de fim do intervalo ({}) não está compreendida entre '
self.logger.warn(
'A data de fim do intervalo ({}) não está compreendida entre '
'as datas de início ({}) e fim ({}) tanto da Legislatura quanto da '
'própria Sessão Legislativa ({} e {}).'
.format(data_fim_intervalo, data_inicio_leg, data_fim_leg, data_inicio, data_fim))
'própria Sessão Legislativa ({} e {}).'.format(
data_fim_intervalo, data_inicio_leg, data_fim_leg, data_inicio, data_fim
)
)
raise ValidationError('A data de fim do intervalo deve estar compreendida entre '
'as datas de início e fim tanto da Legislatura quanto da '
'própria Sessão Legislativa')
@ -567,8 +580,9 @@ class AutorForm(ModelForm):
def valida_igualdade(self, texto1, texto2, msg):
if texto1 != texto2:
self.logger.error(
'Textos diferentes. ("{}" e "{}")'.format(texto1, texto2))
self.logger.warn(
'Textos diferentes. ("{}" e "{}")'.format(texto1, texto2)
)
raise ValidationError(msg)
return True
@ -582,8 +596,10 @@ class AutorForm(ModelForm):
cd = self.cleaned_data
if 'action_user' not in cd or not cd['action_user']:
self.logger.error('Não Informado se o Autor terá usuário '
'vinculado para acesso ao Sistema.')
self.logger.warn(
'Não Informado se o Autor terá usuário '
'vinculado para acesso ao Sistema.'
)
raise ValidationError(_('Informe se o Autor terá usuário '
'vinculado para acesso ao Sistema.'))
@ -593,10 +609,13 @@ class AutorForm(ModelForm):
self.instance.user,
get_user_model().USERNAME_FIELD) != cd['username']:
if 'status_user' not in cd or not cd['status_user']:
self.logger.error('Foi trocado ou removido o usuário deste Autor ({}), '
self.logger.warn(
'Foi trocado ou removido o usuário deste Autor ({}), '
'mas não foi informado como se deve proceder '
'com o usuário que está sendo desvinculado? ({})'
.format(cd['username'], get_user_model().USERNAME_FIELD))
'com o usuário que está sendo desvinculado? ({})'.format(
cd['username'], get_user_model().USERNAME_FIELD
)
)
raise ValidationError(
_('Foi trocado ou removido o usuário deste Autor, '
'mas não foi informado como se deve proceder '
@ -613,8 +632,9 @@ class AutorForm(ModelForm):
if cd['action_user'] == 'A':
param_username = {get_user_model().USERNAME_FIELD: cd['username']}
if not User.objects.filter(**param_username).exists():
self.logger.error(
'Não existe usuário com username "%s". ' % cd['username'])
self.logger.warn(
'Não existe usuário com username "%s". ' % cd['username']
)
raise ValidationError(
_('Não existe usuário com username "%s". '
'Para utilizar esse username você deve selecionar '
@ -623,7 +643,7 @@ class AutorForm(ModelForm):
if cd['action_user'] != 'N':
if 'username' not in cd or not cd['username']:
self.logger.error('Username não informado.')
self.logger.warn('Username não informado.')
raise ValidationError(_('O username deve ser informado.'))
param_username = {
@ -634,7 +654,7 @@ class AutorForm(ModelForm):
nome = autor_vinculado[0].nome
error_msg = 'Já existe um autor para este ' \
'usuário ({}): {}'.format(cd['username'], nome)
self.logger.error(error_msg)
self.logger.warn(error_msg)
raise ValidationError(_(error_msg))
"""
@ -643,33 +663,34 @@ class AutorForm(ModelForm):
ainda assim para renderizar um message.danger no topo do form.
"""
if 'tipo' not in cd or not cd['tipo']:
self.logger.error('Tipo do Autor não selecionado.')
self.logger.warn('Tipo do Autor não selecionado.')
raise ValidationError(
_('O Tipo do Autor deve ser selecionado.'))
tipo = cd['tipo']
if 'nome' in cd and \
qs_autor.filter(nome=cd['nome']).exists():
raise ValidationError("Autor '%s' já existente!" % cd['nome'])
if not tipo.content_type:
if 'nome' not in cd or not cd['nome']:
self.logger.error('Nome do Autor não informado.')
self.logger.warn('Nome do Autor não informado.')
raise ValidationError(
_('O Nome do Autor deve ser informado.'))
elif qs_autor.filter(nome=cd['nome']).exists():
raise ValidationError("Autor '%s' já existente!" % cd['nome'])
else:
if 'autor_related' not in cd or not cd['autor_related']:
self.logger.error('Registro de %s não escolhido para ser '
'vinculado ao cadastro de Autor' % tipo.descricao)
self.logger.warn(
'Registro de %s não escolhido para ser '
'vinculado ao cadastro de Autor' % tipo.descricao
)
raise ValidationError(
_('Um registro de %s deve ser escolhido para ser '
'vinculado ao cadastro de Autor') % tipo.descricao)
if not tipo.content_type.model_class().objects.filter(
pk=cd['autor_related']).exists():
self.logger.error('O Registro definido (%s-%s) não está na base '
'de %s.' % (cd['autor_related'], cd['q'], tipo.descricao))
self.logger.warn(
'O Registro definido (%s-%s) não está na base '
'de %s.' % (cd['autor_related'], cd['q'], tipo.descricao)
)
raise ValidationError(
_('O Registro definido (%s-%s) não está na base de %s.'
) % (cd['autor_related'], cd['q'], tipo.descricao))
@ -679,8 +700,10 @@ class AutorForm(ModelForm):
content_type_id=cd['tipo'].content_type_id)
if qs_autor_selected.exists():
autor = qs_autor_selected.first()
self.logger.error('Já existe um autor Cadastrado para '
'%s' % autor.autor_related)
self.logger.warn(
'Já existe um autor Cadastrado para '
'%s' % autor.autor_related
)
raise ValidationError(
_('Já existe um autor Cadastrado para %s'
) % autor.autor_related)
@ -744,6 +767,26 @@ class AutorForm(ModelForm):
return autor
class AutorFilterSet(django_filters.FilterSet):
nome = django_filters.CharFilter(label=_('Nome do Autor'), lookup_expr='icontains')
class Meta:
model = Autor
fields = ['nome']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
row0 = to_row([('nome', 12)])
self.form.helper = SaplFormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Pesquisa de Autor'),
row0,
form_actions(label='Pesquisar')))
class AutorFormForAdmin(AutorForm):
status_user = forms.ChoiceField(
label=_('Bloqueio do Usuário Existente'),
@ -1548,12 +1591,14 @@ class ConfiguracoesAppForm(ModelForm):
casa = CasaLegislativa.objects.first()
if not casa:
self.logger.error('Não há casa legislativa relacionada.')
self.logger.warn('Não há casa legislativa relacionada.')
raise ValidationError("Não há casa legislativa relacionada.")
if not casa.logotipo and mostrar_brasao_painel:
self.logger.error('Não há logitipo configurado para esta '
'CasaLegislativa ({}).'.format(casa))
self.logger.warn(
'Não há logitipo configurado para esta '
'CasaLegislativa ({}).'.format(casa)
)
raise ValidationError("Não há logitipo configurado para esta "
"Casa legislativa.")
@ -1587,8 +1632,9 @@ class RecuperarSenhaForm(PasswordResetForm):
if not email_existente:
msg = 'Não existe nenhum usuário cadastrado com este e-mail.'
self.logger.error('Não existe nenhum usuário cadastrado com este e-mail ({}).'
.format(self.data['email']))
self.logger.warn(
'Não existe nenhum usuário cadastrado com este e-mail ({}).'.format(self.data['email'])
)
raise ValidationError(msg)
return self.cleaned_data
@ -1655,8 +1701,7 @@ class AlterarSenhaForm(Form):
new_password2 = data['new_password2']
if new_password1 != new_password2:
self.logger.error("'Nova Senha' ({}) diferente de 'Confirmar Senha' ({})".format(
new_password1, new_password2))
self.logger.warn("'Nova Senha' diferente de 'Confirmar Senha'")
raise ValidationError(
"'Nova Senha' diferente de 'Confirmar Senha'")
@ -1665,8 +1710,9 @@ class AlterarSenhaForm(Form):
# TODO: senha atual igual a senha anterior, etc
if len(new_password1) < 6:
self.logger.error(
'A senha informada ({}) não tem o mínimo de 6 caracteres.'.format(new_password1))
self.logger.warn(
'A senha informada não tem o mínimo de 6 caracteres.'
)
raise ValidationError(
"A senha informada deve ter no mínimo 6 caracteres")
@ -1675,20 +1721,24 @@ class AlterarSenhaForm(Form):
user = User.objects.get(username=username)
if user.is_anonymous():
self.logger.error(
'Não é possível alterar senha de usuário anônimo ({}).'.format(username))
self.logger.warn(
'Não é possível alterar senha de usuário anônimo ({}).'.format(username)
)
raise ValidationError(
"Não é possível alterar senha de usuário anônimo")
if not user.check_password(old_password):
self.logger.error('Senha atual informada ({}) não confere '
'com a senha armazenada.'.format(old_password))
self.logger.warn(
'Senha atual informada não confere '
'com a senha armazenada.'
)
raise ValidationError("Senha atual informada não confere "
"com a senha armazenada")
if user.check_password(new_password1):
self.logger.error(
'Nova senha ({}) igual à senha anterior.'.format(new_password1))
self.logger.warn(
'Nova senha igual à senha anterior.'
)
raise ValidationError(
"Nova senha não pode ser igual à senha anterior")

24
sapl/base/models.py

@ -231,24 +231,28 @@ class TipoAutor(models.Model):
@reversion.register()
class Autor(models.Model):
user = models.OneToOneField(get_settings_auth_user_model(),
user = models.OneToOneField(
get_settings_auth_user_model(),
on_delete=models.SET_NULL,
null=True)
tipo = models.ForeignKey(TipoAutor, verbose_name=_('Tipo do Autor'),
tipo = models.ForeignKey(
TipoAutor,
verbose_name=_('Tipo do Autor'),
on_delete=models.PROTECT)
content_type = models.ForeignKey(
ContentType,
blank=True, null=True, default=None)
blank=True,
null=True,
default=None)
object_id = models.PositiveIntegerField(
blank=True, null=True, default=None)
blank=True,
null=True,
default=None)
autor_related = GenericForeignKey('content_type', 'object_id')
nome = models.CharField(
max_length=120, blank=True, verbose_name=_('Nome do Autor'))
max_length=120,
blank=True,
verbose_name=_('Nome do Autor'))
cargo = models.CharField(max_length=50, blank=True)
class Meta:

4
sapl/base/urls.py

@ -8,7 +8,8 @@ from django.contrib.auth.views import (password_reset, password_reset_complete,
password_reset_done)
from django.views.generic.base import RedirectView, TemplateView
from sapl.base.views import AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica, DetailUsuarioView
from sapl.base.views import AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica, DetailUsuarioView, \
PesquisarAutorView
from sapl.settings import EMAIL_SEND_USER, MEDIA_URL
from .apps import AppConfig
@ -90,6 +91,7 @@ recuperar_senha = [
urlpatterns = [
url(r'^sistema/autor/tipo/', include(TipoAutorCrud.get_urls())),
url(r'^sistema/autor/', include(AutorCrud.get_urls())),
url(r'^sistema/autor/pesquisar-autor/', PesquisarAutorView.as_view(), name='pesquisar_autor'),
url(r'^sistema/ajuda/(?P<topic>\w+)$',
HelpTopicView.as_view(), name='help_topic'),

105
sapl/base/views.py

@ -41,7 +41,7 @@ from sapl.relatorios.views import (relatorio_materia_em_tramitacao, relatorio_ma
from sapl import settings
from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica
from sapl.base.models import Autor, TipoAutor
from sapl.base.forms import AutorForm, AutorFormForAdmin, TipoAutorForm
from sapl.base.forms import AutorForm, AutorFormForAdmin, TipoAutorForm, AutorFilterSet
from sapl.comissoes.models import Comissao, Reuniao
from sapl.crud.base import CrudAux, make_pagination
from sapl.materia.models import (Anexada, Autoria, DocumentoAcessorio,
@ -295,6 +295,58 @@ class AutorCrud(CrudAux):
return url_reverse
class PesquisarAutorView(FilterView):
model = Autor
filterset_class = AutorFilterSet
paginate_by = 10
def get_filterset_kwargs(self, filterset_class):
super().get_filterset_kwargs(filterset_class)
kwargs = {'data': self.request.GET or None}
qs = self.get_queryset().order_by('nome').distinct()
kwargs.update({
'queryset': qs,
})
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
paginator = context['paginator']
page_obj = context['page_obj']
context['page_range'] = make_pagination(page_obj.number, paginator.num_pages)
context['NO_ENTRIES_MSG'] = 'Nenhum Autor encontrado!'
context['title'] = _('Autores')
return context
def get(self, request, *args, **kwargs):
super().get(request)
data = self.filterset.data
url = ''
if data:
url = "&" + str(self.request.META['QUERY_STRING'])
if url.startswith("&page"):
ponto_comeco = url.find('nome=') - 1
url = url[ponto_comeco:]
context = self.get_context_data(filter=self.filterset,
object_list=self.object_list,
filter_url=url,
numero_res=len(self.object_list))
context['show_results'] = show_results_filter_set(self.request.GET.copy())
return self.render_to_response(context)
class RelatoriosListView(TemplateView):
template_name='base/relatorios_list.html'
@ -1579,32 +1631,25 @@ def mandato_sem_data_inicio():
def get_estatistica(request):
materias = MateriaLegislativa.objects.all()
normas = NormaJuridica.objects.all()
datas = [
materias.order_by('-data_ultima_atualizacao').values_list('data_ultima_atualizacao', flat=True)
.exclude(data_ultima_atualizacao__isnull=True).first(),
normas.order_by('-data_ultima_atualizacao').values_list('data_ultima_atualizacao', flat=True)
.exclude(data_ultima_atualizacao__isnull=True).first()
]
json_dict = {}
datas = [MateriaLegislativa.objects.all().
order_by('-data_ultima_atualizacao').
values_list('data_ultima_atualizacao', flat=True).
first(),
NormaJuridica.objects.all().
order_by('-data_ultima_atualizacao').
values_list('data_ultima_atualizacao', flat=True).
first()] # Retorna [None, None] se inexistem registros
max_data = ''
if datas[0] and datas[1]:
max_data = max(datas)
else:
max_data = next(iter([i for i in datas if i is not None]), '')
json_dict["data_ultima_atualizacao"] = max_data
json_dict["num_materias_legislativas"] = MateriaLegislativa.objects.all().count()
json_dict["num_normas_juridicas "] = NormaJuridica.objects.all().count()
json_dict["num_parlamentares"] = Parlamentar.objects.all().count()
json_dict["num_sessoes_plenarias"] = SessaoPlenaria.objects.all().count()
max_data = max(datas) if datas[0] and datas[1] else next(iter([i for i in datas if i is not None]), '')
return JsonResponse(json_dict)
return JsonResponse({
"data_ultima_atualizacao": max_data,
"num_materias_legislativas": materias.count(),
"num_normas_juridicas ": normas.count(),
"num_parlamentares": Parlamentar.objects.all().count(),
"num_sessoes_plenarias": SessaoPlenaria.objects.all().count()
})
class ListarMandatoSemDataInicioView(PermissionRequiredMixin, ListView):
@ -2020,17 +2065,23 @@ class AppConfigCrud(CrudAux):
recibo_prop_atual = AppConfig.objects.last().receber_recibo_proposicao
recibo_prop_novo = self.request.POST['receber_recibo_proposicao']
if recibo_prop_novo == 'False' and recibo_prop_atual:
props = Proposicao.objects.filter(hash_code='')
props = Proposicao.objects.filter(hash_code='', data_recebimento__isnull=True).exclude(data_envio__isnull=True)
for prop in props:
try:
self.gerar_hash(prop)
except ValidationError as e:
form.add_error('receber_recibo_proposicao',e)
msg = _("Não foi possível mudar a configuração porque a Proposição {} não possui texto original vinculado!".format(prop))
messages.error(self.request, msg)
return super().form_invalid(form)
return super().form_valid(form)
def gerar_hash(self, inst):
inst.save()
if inst.texto_original:
try:
inst.hash_code = gerar_hash_arquivo(
inst.texto_original.path, str(inst.pk))
inst.save()
except IOError:
raise ValidationError("Existem proposicoes com arquivos inexistentes.")
elif inst.texto_articulado.exists():

106
sapl/comissoes/forms.py

@ -61,11 +61,17 @@ class ComposicaoForm(forms.ModelForm):
if intersecao_periodo:
if periodo.data_fim:
self.logger.error('O período informado ({} a {}) choca com períodos já cadastrados para esta comissão'
.format(periodo.data_inicio, periodo.data_fim))
self.logger.warn(
'O período informado ({} a {}) choca com períodos já cadastrados para esta comissão'.format(
periodo.data_inicio, periodo.data_fim
)
)
else:
self.logger.error('O período informado ({} - ) choca com períodos já cadastrados para esta comissão'
.format(periodo.data_inicio))
self.logger.warn(
'O período informado ({} - ) choca com períodos já cadastrados para esta comissão'.format(
periodo.data_inicio
)
)
raise ValidationError('O período informado choca com períodos já cadastrados para esta comissão')
return data
@ -89,8 +95,10 @@ class PeriodoForm(forms.ModelForm):
data_fim = cleaned_data['data_fim']
if data_fim and data_fim < data_inicio:
self.logger.error('A Data Final ({}) é menor que '
'a Data Inicial({}).'.format(data_fim, data_inicio))
self.logger.warn(
'A Data Final ({}) é menor que '
'a Data Inicial({}).'.format(data_fim, data_inicio)
)
raise ValidationError('A Data Final não pode ser menor que '
'a Data Inicial')
@ -103,9 +111,11 @@ class PeriodoForm(forms.ModelForm):
)
if not legislatura:
self.logger.error('O período informado ({} a {})'
self.logger.warn(
'O período informado ({} a {})'
'não está contido em uma única '
'legislatura existente'.format(data_inicio, data_fim))
'legislatura existente'.format(data_inicio, data_fim)
)
raise ValidationError('O período informado '
'deve estar contido em uma única '
'legislatura existente')
@ -165,8 +175,10 @@ class ParticipacaoCreateForm(forms.ModelForm):
if data_desligamento and \
data_designacao > data_desligamento:
self.logger.error('Data de designação ({}) superior '
'à data de desligamento ({})'.format(data_designacao, data_desligamento))
self.logger.warn(
'Data de designação ({}) superior '
'à data de desligamento ({})'.format(data_designacao, data_desligamento)
)
raise ValidationError(_('Data de designação não pode ser superior '
'à data de desligamento'))
@ -176,8 +188,11 @@ class ParticipacaoCreateForm(forms.ModelForm):
if cleaned_data['cargo'].nome in cargos_unicos:
msg = _('Este cargo é único para esta Comissão.')
self.logger.error('Este cargo ({}) é único para esta Comissão.'.format(
cleaned_data['cargo'].nome))
self.logger.warn(
'Este cargo ({}) é único para esta Comissão.'.format(
cleaned_data['cargo'].nome
)
)
raise ValidationError(msg)
return cleaned_data
@ -253,8 +268,10 @@ class ParticipacaoEditForm(forms.ModelForm):
if data_desligamento and \
data_designacao > data_desligamento:
self.logger.error('Data de designação ({}) superior '
'à data de desligamento ({})'.format(data_designacao, data_desligamento))
self.logger.warn(
'Data de designação ({}) superior '
'à data de desligamento ({})'.format(data_designacao, data_desligamento)
)
raise ValidationError(_('Data de designação não pode ser superior '
'à data de desligamento'))
@ -266,8 +283,11 @@ class ParticipacaoEditForm(forms.ModelForm):
if cleaned_data['cargo'].nome in cargos_unicos:
msg = _('Este cargo é único para esta Comissão.')
self.logger.error('Este cargo ({}) é único para esta Comissão (id={}).'
.format(cleaned_data['cargo'].nome, composicao_id))
self.logger.warn(
'Este cargo ({}) é único para esta Comissão (id={}).'.format(
cleaned_data['cargo'].nome, composicao_id
)
)
raise ValidationError(msg)
return cleaned_data
@ -301,51 +321,70 @@ class ComissaoForm(forms.ModelForm):
if len(self.cleaned_data['nome']) > 100:
msg = _('Nome da Comissão informado ({}) tem mais de 50 caracteres.'.format(
self.cleaned_data['nome']))
self.logger.error(
'Nome da Comissão deve ter no máximo 50 caracteres.')
self.logger.warn(
'Nome da Comissão deve ter no máximo 50 caracteres.'
)
raise ValidationError(msg)
if (self.cleaned_data['data_extincao'] and
self.cleaned_data['data_extincao'] <
self.cleaned_data['data_criacao']):
msg = _('Data de extinção não pode ser menor que a de criação')
self.logger.error('Data de extinção ({}) não pode ser menor que a de criação ({}).'
.format(self.cleaned_data['data_extincao'], self.cleaned_data['data_criacao']))
self.logger.warn(
'Data de extinção ({}) não pode ser menor que a de criação ({}).'.format(
self.cleaned_data['data_extincao'], self.cleaned_data['data_criacao']
)
)
raise ValidationError(msg)
if (self.cleaned_data['data_final_prevista_temp'] and
self.cleaned_data['data_final_prevista_temp'] <
self.cleaned_data['data_criacao']):
msg = _('Data Prevista para Término não pode ser menor que a de criação')
self.logger.error('Data Prevista para Término ({}) não pode ser menor que a de criação ({}).'
.format(self.cleaned_data['data_final_prevista_temp'], self.cleaned_data['data_criacao']))
self.logger.warn(
'Data Prevista para Término ({}) não pode ser menor que a de criação ({}).'.format(
self.cleaned_data['data_final_prevista_temp'], self.cleaned_data['data_criacao']
)
)
raise ValidationError(msg)
if (self.cleaned_data['data_prorrogada_temp'] and
self.cleaned_data['data_prorrogada_temp'] <
self.cleaned_data['data_criacao']):
msg = _('Data Novo Prazo não pode ser menor que a de criação')
self.logger.error('Data Novo Prazo ({}) não pode ser menor que a de criação ({}).'
.format(self.cleaned_data['data_prorrogada_temp'], self.cleaned_data['data_criacao']))
self.logger.warn(
'Data Novo Prazo ({}) não pode ser menor que a de criação ({}).'.format(
self.cleaned_data['data_prorrogada_temp'], self.cleaned_data['data_criacao']
)
)
raise ValidationError(msg)
if (self.cleaned_data['data_instalacao_temp'] and
self.cleaned_data['data_instalacao_temp'] <
self.cleaned_data['data_criacao']):
msg = _('Data de Instalação não pode ser menor que a de criação')
self.logger.error('Data de Instalação ({}) não pode ser menor que a de criação ({}).'
.format(self.cleaned_data['data_instalacao_temp'], self.cleaned_data['data_criacao']))
self.logger.warn(
'Data de Instalação ({}) não pode ser menor que a de criação ({}).'.format(
self.cleaned_data['data_instalacao_temp'], self.cleaned_data['data_criacao']
)
)
raise ValidationError(msg)
if (self.cleaned_data['data_final_prevista_temp'] and self.cleaned_data['data_instalacao_temp'] and
self.cleaned_data['data_final_prevista_temp'] <
self.cleaned_data['data_instalacao_temp']):
msg = _(
'Data Prevista para Término não pode ser menor que a de Instalação.')
self.logger.error('Data Prevista para Término ({}) não pode ser menor que a de Instalação ({}).'
.format(self.cleaned_data['data_final_prevista_temp'], self.cleaned_data['data_instalacao_temp']))
self.logger.warn(
'Data Prevista para Término ({}) não pode ser menor que a de Instalação ({}).'.format(
self.cleaned_data['data_final_prevista_temp'], self.cleaned_data['data_instalacao_temp']
)
)
raise ValidationError(msg)
if (self.cleaned_data['data_prorrogada_temp'] and self.cleaned_data['data_instalacao_temp'] and
self.cleaned_data['data_prorrogada_temp'] <
self.cleaned_data['data_instalacao_temp']):
msg = _('Data Novo Prazo não pode ser menor que a de Instalação.')
self.logger.error('Data Novo Prazo ({}) não pode ser menor que a de Instalação ({}).'
.format(self.cleaned_data['data_prorrogada_temp'], self.cleaned_data['data_instalacao_temp']))
self.logger.warn(
'Data Novo Prazo ({}) não pode ser menor que a de Instalação ({}).'.format(
self.cleaned_data['data_prorrogada_temp'], self.cleaned_data['data_instalacao_temp']
)
)
raise ValidationError(msg)
return self.cleaned_data
@ -391,8 +430,11 @@ class ReuniaoForm(ModelForm):
self.cleaned_data['hora_inicio']):
msg = _(
'A hora de término da reunião não pode ser menor que a de início')
self.logger.error("A hora de término da reunião ({}) não pode ser menor que a de início ({})."
.format(self.cleaned_data['hora_fim'], self.cleaned_data['hora_inicio']))
self.logger.warn(
"A hora de término da reunião ({}) não pode ser menor que a de início ({}).".format(
self.cleaned_data['hora_fim'], self.cleaned_data['hora_inicio']
)
)
raise ValidationError(msg)
upload_pauta = self.cleaned_data.get('upload_pauta', False)

10
sapl/crud/base.py

@ -577,8 +577,9 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
fm = model._meta.get_field(fo)
except Exception as e:
username = self.request.user.username
self.logger.error(
"user=" + username + ". " + str(e))
self.logger.info(
"user=" + username + ". " + str(e)
)
pass
if fm and hasattr(fm, 'related_model')\
@ -607,8 +608,9 @@ class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
# print(ordering)
except Exception as e:
logger.error(string_concat(_(
'ERRO: construção da tupla de ordenação.'), str(e)))
logger.warn(
string_concat(_('ERRO: construção da tupla de ordenação.'), str(e))
)
# print(queryset.query)
if not self.request.user.is_authenticated():

38
sapl/materia/forms.py

@ -34,7 +34,7 @@ from sapl.materia.models import (AssuntoMateria, Autoria, MateriaAssunto,
MateriaLegislativa, Orgao,
RegimeTramitacao, StatusTramitacao,
TipoDocumento, TipoProposicao,
UnidadeTramitacao)
UnidadeTramitacao,ConfigEtiquetaMateriaLegislativa)
from sapl.norma.models import (LegislacaoCitada, NormaJuridica,
TipoNormaJuridica)
from sapl.parlamentares.models import Legislatura, Partido, Parlamentar
@ -211,10 +211,8 @@ class MateriaLegislativaForm(FileFieldCheckMixin, ModelForm):
if protocolo:
if not Protocolo.objects.filter(numero=protocolo, ano=ano).exists():
self.logger.error("Protocolo %s/%s não"
" existe" % (protocolo, ano))
raise ValidationError(_('Protocolo %s/%s não'
' existe' % (protocolo, ano)))
self.logger.warning("Protocolo %s/%s não existe" % (protocolo, ano))
raise ValidationError(_('Protocolo %s/%s não existe' % (protocolo, ano)))
if protocolo_antigo != protocolo:
exist_materia = MateriaLegislativa.objects.filter(
@ -517,11 +515,9 @@ class TramitacaoForm(ModelForm):
raise ValidationError(msg)
if cleaned_data['data_tramitacao'] > timezone.now().date():
self.logger.error('A data de tramitação informada ({}) não é ' +
'menor ou igual a data de hoje!'.format(cleaned_data['data_tramitacao']))
msg = _(
'A data de tramitação deve ser ' +
'menor ou igual a data de hoje!')
self.logger.warning('A data de tramitação informada ({}) não é menor ou igual a data de hoje!'
.format(cleaned_data['data_tramitacao']))
msg = _('A data de tramitação deve ser menor ou igual a data de hoje!')
raise ValidationError(msg)
if (ultima_tramitacao and
@ -535,10 +531,8 @@ class TramitacaoForm(ModelForm):
if data_enc_form:
if data_enc_form < data_tram_form:
msg = _('A data de encaminhamento deve ser ' +
'maior que a data de tramitação!')
self.logger.error("A data de encaminhamento ({}) deve ser "
"maior que a data de tramitação! ({})"
msg = _('A data de encaminhamento deve ser maior que a data de tramitação!')
self.logger.warning("A data de encaminhamento ({}) deve ser maior que a data de tramitação! ({})"
.format(data_enc_form, data_tram_form))
raise ValidationError(msg)
@ -904,8 +898,7 @@ class AnexadaForm(ModelForm):
except ObjectDoesNotExist:
msg = _('A {} {}/{} não existe no cadastro de matérias legislativas.'
.format(cleaned_data['tipo'], cleaned_data['numero'], cleaned_data['ano']))
self.logger.error("A matéria a ser anexada não existe no cadastro"
" de matérias legislativas.")
self.logger.warning("A matéria a ser anexada não existe no cadastro de matérias legislativas.")
raise ValidationError(msg)
materia_principal = self.instance.materia_principal
@ -1742,11 +1735,9 @@ class TramitacaoEmLoteForm(ModelForm):
if data_enc_form:
if data_enc_form < data_tram_form:
self.logger.error('A data de encaminhamento ({}) deve ser '
'maior que a data de tramitação ({})!'
self.logger.warning('A data de encaminhamento ({}) deve ser maior que a data de tramitação ({})!'
.format(data_enc_form, data_tram_form))
msg = _('A data de encaminhamento deve ser ' +
'maior que a data de tramitação!')
msg = _('A data de encaminhamento deve ser maior que a data de tramitação!')
raise ValidationError(msg)
if data_prazo_form:
@ -2922,3 +2913,10 @@ class MateriaPesquisaSimplesForm(forms.Form):
_('A Data Final não pode ser menor que a Data Inicial'))
return cleaned_data
class ConfigEtiquetaMateriaLegislativaForms(ModelForm):
class Meta:
model = ConfigEtiquetaMateriaLegislativa
fields = '__all__'

23
sapl/materia/migrations/0068_configetiquetamaterialegislativa.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-05-18 18:14
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('materia', '0067_auto_20200416_1538'),
]
operations = [
migrations.CreateModel(
name='ConfigEtiquetaMateriaLegislativa',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('largura', models.FloatField(default=5)),
('altura', models.FloatField(default=3)),
],
),
]

20
sapl/materia/migrations/0069_auto_20200518_1519.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-05-18 18:19
from __future__ import unicode_literals
from django.db import migrations
def create_first(apps, schema_editor):
db_alias = schema_editor.connection.alias
Type = apps.get_model("materia", "ConfigEtiquetaMateriaLegislativa")
Type.objects.using(db_alias).create()
class Migration(migrations.Migration):
dependencies = [
('materia', '0068_configetiquetamaterialegislativa'),
]
operations = [
migrations.RunPython(create_first),
]

8
sapl/materia/models.py

@ -1116,3 +1116,11 @@ class MateriaEmTramitacao(models.Model):
def __str__(self):
return '{}/{}'.format(self.materia, self.tramitacao)
class ConfigEtiquetaMateriaLegislativa(models.Model):
largura = models.FloatField(default=5)
altura = models.FloatField(default=3)
def save(self, *args, **kwargs):
self.id = 1
return super().save(*args, **kwargs)

4
sapl/materia/urls.py

@ -27,7 +27,8 @@ from sapl.materia.views import (AcompanhamentoConfirmarView,
proposicao_texto, recuperar_materia,
ExcluirTramitacaoEmLoteView, RetornarProposicao,
MateriaPesquisaSimplesView,
DespachoInicialMultiCreateView, get_zip_docacessorios, get_pdf_docacessorios)
DespachoInicialMultiCreateView, get_zip_docacessorios,
get_pdf_docacessorios, configEtiquetaMateriaLegislativaCrud)
from sapl.norma.views import NormaPesquisaSimplesView
from sapl.protocoloadm.views import (
FichaPesquisaAdmView, FichaSelecionaAdmView)
@ -172,6 +173,7 @@ urlpatterns_sistema = [
url(r'^sistema/materia/status-tramitacao/',
include(StatusTramitacaoCrud.get_urls())),
url(r'^sistema/materia/orgao/', include(OrgaoCrud.get_urls())),
url(r'^sistema/materia/config-etiqueta-materia-legislativas/',configEtiquetaMateriaLegislativaCrud, name="configEtiquetaMateriaLegislativaCrud"),
]
urlpatterns = urlpatterns_impressos + urlpatterns_materia + \

247
sapl/materia/views.py

@ -32,6 +32,8 @@ from django.utils.translation import ugettext_lazy as _
from django.views.generic import CreateView, ListView, TemplateView, UpdateView
from django.views.generic.base import RedirectView
from django.views.generic.edit import FormView
from django.shortcuts import render
from django_filters.views import FilterView
@ -48,7 +50,7 @@ from sapl.materia.forms import (AnexadaForm, AutoriaForm, AutoriaMultiCreateForm
ConfirmarProposicaoForm, DevolverProposicaoForm,
DespachoInicialCreateForm, LegislacaoCitadaForm,
MateriaPesquisaSimplesForm, OrgaoForm, ProposicaoForm,
TipoProposicaoForm, TramitacaoForm, TramitacaoUpdateForm)
TipoProposicaoForm, TramitacaoForm, TramitacaoUpdateForm,ConfigEtiquetaMateriaLegislativaForms)
from sapl.norma.models import LegislacaoCitada
from sapl.parlamentares.models import Legislatura
from sapl.protocoloadm.models import Protocolo
@ -72,7 +74,7 @@ from .models import (AcompanhamentoMateria, Anexada, AssuntoMateria, Autoria, De
DocumentoAcessorio, MateriaAssunto, MateriaLegislativa, Numeracao, Orgao,
Origem, Proposicao, RegimeTramitacao, Relatoria, StatusTramitacao,
TipoDocumento, TipoFimRelatoria, TipoMateriaLegislativa, TipoProposicao,
Tramitacao, UnidadeTramitacao)
Tramitacao, UnidadeTramitacao,ConfigEtiquetaMateriaLegislativa)
AssuntoMateriaCrud = CrudAux.build(AssuntoMateria, 'assunto_materia')
@ -736,8 +738,14 @@ class ProposicaoCrud(Crud):
container_field = 'autor__user'
class BaseMixin(Crud.BaseMixin):
list_field_names = ['data_envio', 'data_recebimento', 'descricao',
'tipo', 'conteudo_gerado_related', 'cancelado', ]
list_field_names = [
'data_envio',
'data_recebimento',
'descricao',
'tipo',
'conteudo_gerado_related',
'cancelado'
]
class BaseLocalMixin:
form_class = ProposicaoForm
@ -751,22 +759,23 @@ class ProposicaoCrud(Crud):
def get(self, request, *args, **kwargs):
if not self._action_is_valid(request, *args, **kwargs):
return redirect(reverse('sapl.materia:proposicao_detail',
kwargs={'pk': kwargs['pk']}))
return redirect(reverse('sapl.materia:proposicao_detail', kwargs={'pk': kwargs['pk']}))
return super().get(self, request, *args, **kwargs)
def post(self, request, *args, **kwargs):
if not self._action_is_valid(request, *args, **kwargs):
return redirect(reverse('sapl.materia:proposicao_detail',
kwargs={'pk': kwargs['pk']}))
return redirect(reverse('sapl.materia:proposicao_detail', kwargs={'pk': kwargs['pk']}))
return super().post(self, request, *args, **kwargs)
class DetailView(Crud.DetailView):
layout_key = 'Proposicao'
permission_required = (RP_DETAIL, 'materia.detail_proposicao_enviada',
permission_required = (
RP_DETAIL,
'materia.detail_proposicao_enviada',
'materia.detail_proposicao_devolvida',
'materia.detail_proposicao_incorporada')
'materia.detail_proposicao_incorporada'
)
logger = logging.getLogger(__name__)
@ -785,7 +794,6 @@ class ProposicaoCrud(Crud):
return context
def get(self, request, *args, **kwargs):
action = request.GET.get('action', '')
user = request.user
username = user.username
@ -802,10 +810,8 @@ class ProposicaoCrud(Crud):
msg_error = _('Proposição já foi enviada e recebida.')
elif p.data_envio:
msg_error = _('Proposição já foi enviada.')
elif not p.texto_original and\
not p.texto_articulado.exists():
msg_error = _('Proposição não possui nenhum tipo de '
'Texto associado.')
elif not p.texto_original and not p.texto_articulado.exists():
msg_error = _('Proposição não possui nenhum tipo de Texto associado.')
else:
if p.texto_articulado.exists():
ta = p.texto_articulado.first()
@ -813,8 +819,7 @@ class ProposicaoCrud(Crud):
ta.editing_locked = True
ta.save()
receber_recibo = BaseAppConfig.attr(
'receber_recibo_proposicao')
receber_recibo = BaseAppConfig.attr('receber_recibo_proposicao')
if not receber_recibo:
ta = p.texto_articulado.first()
@ -824,45 +829,39 @@ class ProposicaoCrud(Crud):
p.data_envio = timezone.now()
p.save()
messages.success(request, _(
'Proposição enviada com sucesso.'))
messages.success(request, _('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))
self.logger.debug("User={}. Tentando obter número do objeto MateriaLegislativa "
"com atributos tipo={} e ano={}."
.format(username, p.tipo.tipo_conteudo_related, p.ano))
if p.numero_materia_futuro:
numero = p.numero_materia_futuro
else:
numero = MateriaLegislativa.objects.filter(tipo=p.tipo.tipo_conteudo_related,
ano=p.ano).last().numero + 1
messages.success(request, _(
'%s : nº %s de %s <br>Atenção! Este número é apenas um provável '
'número que pode não corresponder com a realidade'
% (p.tipo, numero, p.ano)))
messages.success(request, _("{}: nº {} de {} <br>Atenção! Este número é apenas um provável "
"número que pode não corresponder com a realidade"
.format(p.tipo, numero, p.ano)))
except ValueError as e:
self.logger.error(
"user=" + username + "." + str(e))
self.logger.warning("User=" + username + ". " + str(e))
pass
except AttributeError as e:
self.logger.error(
"user=" + username + "." + str(e))
self.logger.warning("User=" + username + ". " + str(e))
pass
except TypeError as e:
self.logger.error(
"user=" + username + "." + str(e))
self.logger.warning("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.warning("User={}. Proposição (numero={}) ainda não foi enviada."
.format(username, 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))
msg_error = _('Proposição já foi recebida, não é '
'possível retorná-la.')
self.logger.warning("User={}. Proposição (numero={}) já foi recebida, "
"não é possível retorná-la.".format(username, p.numero_proposicao))
msg_error = _('Proposição já foi recebida, não é possível retorná-la.')
else:
p.data_envio = None
p.save()
@ -871,27 +870,24 @@ 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))
messages.success(request, _(
'Proposição Retornada com sucesso.'))
self.logger.info("User={}. Proposição (numero={}) Retornada com sucesso."
.format(username, p.numero_proposicao))
messages.success(request, _('Proposição Retornada com sucesso.'))
if msg_error:
messages.error(request, msg_error)
# retornar redirecionando para limpar a variavel action
return redirect(reverse('sapl.materia:proposicao_detail',
kwargs={'pk': kwargs['pk']}))
return redirect(reverse('sapl.materia:proposicao_detail', kwargs={'pk': kwargs['pk']}))
def dispatch(self, request, *args, **kwargs):
username = request.user.username
try:
self.logger.debug(
"user=" + username + ". Tentando obter objeto Proposicao com pk={}".format(kwargs['pk']))
self.logger.debug("User={}. Tentando obter objeto Proposicao com pk={}".format(username, 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.warning("User={}. Erro ao obter proposicao com pk={}. Retornando 404. {}"
.format(username, kwargs['pk'], str(e)))
raise Http404()
if not self.has_permission():
@ -901,47 +897,38 @@ class ProposicaoCrud(Crud):
if not p.data_envio and not p.data_devolucao:
raise Http404()
if p.data_devolucao and not request.user.has_perm(
'materia.detail_proposicao_devolvida'):
if p.data_devolucao and not request.user.has_perm('materia.detail_proposicao_devolvida'):
raise Http404()
if p.data_envio and not p.data_recebimento\
and not request.user.has_perm(
'materia.detail_proposicao_enviada'):
if p.data_envio and not p.data_recebimento \
and not request.user.has_perm('materia.detail_proposicao_enviada'):
raise Http404()
if p.data_envio and p.data_recebimento\
and not request.user.has_perm(
'materia.detail_proposicao_incorporada'):
if p.data_envio and p.data_recebimento \
and not request.user.has_perm('materia.detail_proposicao_incorporada'):
raise Http404()
return super(PermissionRequiredMixin, self).dispatch(
request, *args, **kwargs)
return super(PermissionRequiredMixin, self).dispatch(request, *args, **kwargs)
class DeleteView(BaseLocalMixin, Crud.DeleteView):
logger = logging.getLogger(__name__)
def _action_is_valid(self, request, *args, **kwargs):
proposicao = Proposicao.objects.filter(
id=kwargs['pk']).values_list(
'data_envio', 'data_recebimento')
proposicao = Proposicao.objects.filter(id=kwargs['pk']).values_list('data_envio', 'data_recebimento')
username = request.user.username
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']))
msg = _('Proposição já foi enviada e recebida.'
'Não pode mais ser excluida.')
self.logger.warning("User={}. Proposição (id={}) já foi enviada e recebida."
"Não pode mais ser excluida.".format(username, 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']))
msg = _('Proposição já foi enviada mas ainda não recebida '
'pelo protocolo. Use a opção Recuperar Proposição '
'para depois excluí-la.')
self.logger.warning("""\
User={}. Proposição (id={}) foi enviada, mas ainda não recebida pelo protocolo. \
Use a opção Recuperar Proposição para depois excluí-la.""".format(username, 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.")
if proposicao[0][0] or proposicao[0][1]:
messages.error(request, msg)
@ -949,20 +936,18 @@ class ProposicaoCrud(Crud):
return True
class UpdateView(BaseLocalMixin, Crud.UpdateView):
logger = logging.getLogger(__name__)
form_class = ProposicaoForm
def form_valid(self, form):
tz = timezone.get_current_timezone()
objeto_antigo = Proposicao.objects.get(
pk=self.kwargs['pk']
)
objeto_antigo = Proposicao.objects.get(pk=self.kwargs['pk'])
dict_objeto_antigo = objeto_antigo.__dict__
tipo_texto = self.request.POST.get('tipo_texto', '')
if tipo_texto=='D' and objeto_antigo.texto_articulado.exists() or tipo_texto=='T' and not objeto_antigo.texto_articulado.exists():
if tipo_texto == 'D' and objeto_antigo.texto_articulado.exists()\
or tipo_texto == 'T' and not objeto_antigo.texto_articulado.exists():
self.object.user = self.request.user
self.object.ip = get_client_ip(self.request)
self.object.ultima_edicao = tz.localize(datetime.now())
@ -972,7 +957,10 @@ class ProposicaoCrud(Crud):
dict_objeto_novo = self.object.__dict__
atributos = [
'tipo_id', 'descricao', 'observacao', 'texto_original',
'tipo_id',
'descricao',
'observacao',
'texto_original',
'materia_de_vinculo_id'
]
@ -987,27 +975,22 @@ class ProposicaoCrud(Crud):
return super().form_valid(form)
def _action_is_valid(self, request, *args, **kwargs):
proposicao = Proposicao.objects.filter(
id=kwargs['pk']).values_list(
'data_envio', 'data_recebimento')
proposicao = Proposicao.objects.filter(id=kwargs['pk']).values_list('data_envio', 'data_recebimento')
username = request.user.username
if proposicao:
msg = ''
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']))
msg = _('Proposição já foi enviada e recebida.'
'Não pode mais ser editada')
self.logger.warning('User={}. Proposição (id={}) já foi enviada e recebida. '
'Não pode mais ser editada'.format(username, 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']))
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.')
self.logger.warning("""\
User={}. Proposição (id={}) foi enviada, mas ainda não recebida pelo protocolo. \
Use a opção Recuperar Proposição para voltar para edição.""".format(username, 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.")
if proposicao[0][0] or proposicao[0][1]:
messages.error(request, msg)
@ -1015,22 +998,17 @@ class ProposicaoCrud(Crud):
return True
def get_success_url(self):
tipo_texto = self.request.POST.get('tipo_texto', '')
username = self.request.user.username
if tipo_texto == 'T':
messages.info(self.request,
_('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.'))
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.')
return reverse('sapl.materia:proposicao_ta',
kwargs={'pk': self.object.pk})
messages.info(self.request, _("""\
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."""))
self.logger.debug("""\
User={}. 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.""".format(username))
return reverse('sapl.materia:proposicao_ta', kwargs={'pk': self.object.pk})
else:
return Crud.UpdateView.get_success_url(self)
@ -1061,43 +1039,38 @@ class ProposicaoCrud(Crud):
username = self.request.user.username
if tipo_texto == 'T':
messages.info(self.request,
_('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.'))
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.')
return reverse('sapl.materia:proposicao_ta',
kwargs={'pk': self.object.pk})
messages.info(self.request, _("""\
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."""))
self.logger.debug("""\
User={}. 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.""".format(username))
return reverse('sapl.materia:proposicao_ta', kwargs={'pk': self.object.pk})
else:
return Crud.CreateView.get_success_url(self)
class ListView(Crud.ListView):
ordering = ['-data_envio', 'descricao']
ordering = [
'-data_envio',
'descricao'
]
def get_rows(self, object_list):
for obj in object_list:
if obj.data_recebimento is None:
obj.data_recebimento = 'Não recebida'\
if obj.data_envio else 'Não enviada'
obj.data_recebimento = 'Não recebida' if obj.data_envio else 'Não enviada'
else:
obj.data_recebimento = timezone.localtime(
obj.data_recebimento)
obj.data_recebimento = formats.date_format(
obj.data_recebimento, "DATETIME_FORMAT")
obj.data_recebimento = timezone.localtime(obj.data_recebimento)
obj.data_recebimento = formats.date_format(obj.data_recebimento, "DATETIME_FORMAT")
if obj.data_envio is None:
obj.data_envio = 'Em elaboração...'
else:
obj.data_envio = timezone.localtime(obj.data_envio)
obj.data_envio = formats.date_format(
obj.data_envio, "DATETIME_FORMAT")
obj.data_envio = formats.date_format(obj.data_envio, "DATETIME_FORMAT")
return [self._as_row(obj) for obj in object_list]
@ -1415,7 +1388,6 @@ class TramitacaoCrud(MasterDetailCrud):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user'] = self.request.user
return context
@ -2757,11 +2729,11 @@ def create_zip_docacessorios(materia):
def get_zip_docacessorios(request, pk):
logger = logging.getLogger(__name__)
username = request.user.username
username = 'Usuário anônimo' if request.user.is_anonymous else request.user.username
materia = get_object_or_404(MateriaLegislativa, pk=pk)
try:
external_name, zipfilename = create_zip_docacessorios(materia)
logger.info("user= {}. Gerou o zip compilado de documento acessorios")
logger.info("user= {}. Gerou o zip compilado de documento acessorios".format(username))
except FileNotFoundError:
logger.error("user= {}.Não há arquivos cadastrados".format(username))
msg=_('Não há arquivos cadastrados nesses documentos acessórios.')
@ -2822,10 +2794,10 @@ def create_pdf_docacessorios(materia):
def get_pdf_docacessorios(request, pk):
materia = get_object_or_404(MateriaLegislativa, pk=pk)
logger = logging.getLogger(__name__)
username = request.user.username
username = 'Usuário anônimo' if request.user.is_anonymous else request.user.username
try:
external_name, pdffilename = create_pdf_docacessorios(materia)
logger.info("user= {}. Gerou o pdf compilado de documento acessorios")
logger.info("user= {}. Gerou o pdf compilado de documento acessorios".format(username))
except FileNotFoundError:
logger.error("user= {}.Não há arquivos cadastrados".format(username))
msg=_('Não há arquivos cadastrados nesses documentos acessórios.')
@ -2853,3 +2825,16 @@ def get_pdf_docacessorios(request, pk):
% external_name)
return response
def configEtiquetaMateriaLegislativaCrud(request):
config = ConfigEtiquetaMateriaLegislativa.objects.last()
if request.method == "POST":
form = ConfigEtiquetaMateriaLegislativaForms(request.POST, instance=config)
if form.is_valid():
config = form.save(commit=False)
config.published_date = timezone.now()
config.save()
return redirect('materia/config_etiqueta_materia.html', {'form': form})
else:
form = ConfigEtiquetaMateriaLegislativaForms(instance=config)
return render(request, 'materia/config_etiqueta_materia.html', {'form': form})

2
sapl/norma/forms.py

@ -163,7 +163,7 @@ class NormaJuridicaForm(FileFieldCheckMixin, ModelForm):
numero=cleaned_data['numero'],
tipo=cleaned_data['tipo']).exists()
if norma:
self.logger.error("Já existe uma norma de mesmo Tipo ({}), Ano ({}) "
self.logger.warning("Já existe uma norma de mesmo Tipo ({}), Ano ({}) "
"e Número ({}) no sistema."
.format(cleaned_data['tipo'], cleaned_data['ano'], cleaned_data['numero']))
raise ValidationError("Já existe uma norma de mesmo Tipo, Ano "

8
sapl/norma/views.py

@ -258,7 +258,7 @@ class NormaCrud(Crud):
def get_initial(self):
initial = super().get_initial()
norma = NormaJuridica.objects.get(id=self.kwargs['pk'])
norma = NormaJuridica.objects.select_related("materia").get(id=self.kwargs['pk'])
if norma.materia:
initial['tipo_materia'] = norma.materia.tipo
initial['ano_materia'] = norma.materia.ano
@ -267,9 +267,7 @@ class NormaCrud(Crud):
return initial
def form_valid(self, form):
norma_antiga = NormaJuridica.objects.get(
pk=self.kwargs['pk']
)
norma_antiga = NormaJuridica.objects.get(pk=self.kwargs['pk'])
# Feito desta forma para que sejam materializados os assuntos
# antigos
@ -329,7 +327,7 @@ def recuperar_norma(request):
response = JsonResponse({'ementa': norma.ementa,
'id': norma.id})
except ObjectDoesNotExist:
logger.error('user=' + username + '. NormaJuridica buscada (tipo={}, ano={}, numero={}) não existe. '
logger.warning('user=' + username + '. NormaJuridica buscada (tipo={}, ano={}, numero={}) não existe. '
'Definida com ementa vazia e id 0.'.format(tipo, ano, numero))
response = JsonResponse({'ementa': '', 'id': 0})

11
sapl/parlamentares/forms.py

@ -216,6 +216,17 @@ class ParlamentarForm(FileFieldCheckMixin, ModelForm):
'biografia': forms.Textarea(
attrs={'id': 'texto-rico'})}
def save(self, commit=True):
parlamentar = super().save()
autor = parlamentar.autor.first()
usuario = autor.user if autor else None
if autor and usuario:
usuario.is_active = parlamentar.ativo
usuario.save()
return parlamentar
class ParlamentarFilterSet(django_filters.FilterSet):
nome_parlamentar = django_filters.CharFilter(

3
sapl/parlamentares/views.py

@ -585,8 +585,7 @@ class ParlamentarCrud(Crud):
". Tentando obter id da legislatura.")
return int(self.request.GET['pk'])
except:
self.logger.error(
"user=" + username + ". Legislatura não possui ID. Buscando em todas as entradas.")
self.logger.warning("User=" + username + ". Legislatura não possui ID. Buscando em todas as entradas.")
legislaturas = Legislatura.objects.all()
for l in legislaturas:
if l.atual():

21
sapl/protocoloadm/migrations/0033_auto_20200708_1312.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2020-07-08 16:12
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('protocoloadm', '0032_auto_20200416_1538'),
]
operations = [
migrations.AlterField(
model_name='protocolo',
name='autor',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='base.Autor'),
),
]

61
sapl/protocoloadm/models.py

@ -53,43 +53,55 @@ def texto_upload_path(instance, filename):
@reversion.register()
class Protocolo(models.Model):
numero = models.PositiveIntegerField(
blank=False, null=False, verbose_name=_('Número de Protocolo'))
ano = models.PositiveSmallIntegerField(blank=False,
blank=False,
null=False,
verbose_name=_('Número de Protocolo'))
ano = models.PositiveSmallIntegerField(
blank=False,
null=False,
choices=RANGE_ANOS,
verbose_name=_('Ano do Protocolo'))
data = models.DateField(null=True, blank=True,
data = models.DateField(
null=True,
blank=True,
verbose_name=_('Data do Protocolo'),
help_text=_('Informado manualmente'))
hora = models.TimeField(null=True, blank=True,
hora = models.TimeField(
null=True,
blank=True,
verbose_name=_('Hora do Protocolo'),
help_text=_('Informado manualmente'))
timestamp_data_hora_manual = models.DateTimeField(default=timezone.now)
user_data_hora_manual = models.CharField(
max_length=256, blank=True,
max_length=256,
blank=True,
verbose_name=_('IP'),
help_text=_('Usuário que está realizando Protocolo e informando '
'data e hora manualmente.'))
help_text=_('Usuário que está realizando Protocolo e informando data e hora manualmente.'))
ip_data_hora_manual = models.CharField(
max_length=256, blank=True,
max_length=256,
blank=True,
verbose_name=_('IP'),
help_text=_('Endereço IP da estação de trabalho '
'do usuário que está realizando Protocolo e informando '
'data e hora manualmente.'))
# Não foi utilizado auto_now_add=True em timestamp porque
# ele usa datetime.now que não é timezone aware.
help_text=_('Endereço IP da estação de trabalho do usuário que está realizando Protocolo e '
'informando data e hora manualmente.'))
# Não foi utilizado auto_now_add=True em timestamp porque ele usa datetime.now que não é timezone aware.
timestamp = models.DateTimeField(
default=timezone.now, null=True, blank=True)
null=True,
blank=True,
default=timezone.now)
tipo_protocolo = models.PositiveIntegerField(
blank=True, null=True, verbose_name=_('Tipo de Protocolo'))
blank=True,
null=True,
verbose_name=_('Tipo de Protocolo'))
tipo_processo = models.PositiveIntegerField()
interessado = models.CharField(
max_length=200, blank=True, verbose_name=_('Interessado'))
autor = models.ForeignKey(Autor,
max_length=200,
blank=True,
verbose_name=_('Interessado'))
autor = models.ForeignKey(
Autor,
blank=True,
null=True,
on_delete=models.PROTECT)
on_delete=models.SET_NULL)
assunto_ementa = models.TextField(blank=True)
tipo_documento = models.ForeignKey(
TipoDocumentoAdministrativo,
@ -104,14 +116,17 @@ class Protocolo(models.Model):
on_delete=models.PROTECT,
verbose_name=_('Tipo de Matéria'))
numero_paginas = models.PositiveIntegerField(
blank=True, null=True, verbose_name=_('Número de Páginas'))
observacao = models.TextField(
blank=True, verbose_name=_('Observação'))
blank=True,
null=True,
verbose_name=_('Número de Páginas'))
observacao = models.TextField(blank=True, verbose_name=_('Observação'))
anulado = models.BooleanField(default=False)
user_anulacao = models.CharField(max_length=20, blank=True)
ip_anulacao = models.CharField(max_length=15, blank=True)
justificativa_anulacao = models.CharField(
max_length=260, blank=True, verbose_name=_('Motivo'))
max_length=260,
blank=True,
verbose_name=_('Motivo'))
timestamp_anulacao = models.DateTimeField(blank=True, null=True)
class Meta:

4
sapl/protocoloadm/views.py

@ -1368,9 +1368,9 @@ class TramitacaoAdmCrud(MasterDetailCrud):
if tramitacao.pk != ultima_tramitacao.pk:
username = request.user.username
self.logger.error("user=" + username + ". Não é possível deletar a tramitação de pk={}. "
self.logger.warning("User={}. 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(username, tramitacao.pk, ultima_tramitacao.pk))
msg = _('Somente a última tramitação pode ser deletada!')
messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(url)

8
sapl/relatorios/urls.py

@ -6,7 +6,7 @@ from .views import (relatorio_capa_processo,
relatorio_etiqueta_protocolo, relatorio_materia,
relatorio_ordem_dia, relatorio_pauta_sessao,
relatorio_protocolo, relatorio_sessao_plenaria,
resumo_ata_pdf, relatorio_sessao_plenaria_pdf)
resumo_ata_pdf, relatorio_sessao_plenaria_pdf, etiqueta_materia_legislativa)
app_name = AppConfig.name
@ -21,8 +21,8 @@ urlpatterns = [
name='relatorio_documento_administrativo'),
url(r'^relatorios/espelho$', relatorio_espelho,
name='relatorio_espelho'),
url(r'^relatorios/(?P<pk>\d+)/sessao-plenaria$',
relatorio_sessao_plenaria, name='relatorio_sessao_plenaria'),
#url(r'^relatorios/(?P<pk>\d+)/sessao-plenaria$',
# relatorio_sessao_plenaria, name='relatorio_sessao_plenaria'),
url(r'^relatorios/protocolo$',
relatorio_protocolo, name='relatorio_protocolo'),
url(r'^relatorios/(?P<nro>\d+)/(?P<ano>\d+)/etiqueta-protocolo$',
@ -33,4 +33,6 @@ urlpatterns = [
resumo_ata_pdf, name='resumo_ata_pdf'),
url(r'^relatorios/(?P<pk>\d+)/sessao-plenaria-pdf$',
relatorio_sessao_plenaria_pdf, name='relatorio_sessao_plenaria_pdf'),
url(r'^relatorios/(?P<pk>\d+)/etiqueta-materia-legislativa$',
etiqueta_materia_legislativa, name='etiqueta_materia_legislativa'),
]

59
sapl/relatorios/views.py

@ -3,6 +3,7 @@ import html
import logging
import re
import tempfile
import unidecode
from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404, HttpResponse
@ -15,7 +16,7 @@ from sapl.settings import MEDIA_URL
from sapl.base.models import Autor, CasaLegislativa
from sapl.comissoes.models import Comissao
from sapl.materia.models import (Autoria, MateriaLegislativa, Numeracao,
Tramitacao, UnidadeTramitacao)
Tramitacao, UnidadeTramitacao, ConfigEtiquetaMateriaLegislativa)
from sapl.parlamentares.models import CargoMesa, Filiacao, Parlamentar
from sapl.protocoloadm.models import (DocumentoAdministrativo, Protocolo,
TramitacaoAdministrativo)
@ -26,7 +27,7 @@ from sapl.sessao.models import (ExpedienteMateria, ExpedienteSessao,
SessaoPlenariaPresenca, OcorrenciaSessao,
RegistroVotacao, VotoParlamentar, OradorOrdemDia, TipoExpediente, ResumoOrdenacao)
from sapl.settings import STATIC_ROOT
from sapl.utils import LISTA_DE_UFS, TrocaTag, filiacao_data
from sapl.utils import LISTA_DE_UFS, TrocaTag, filiacao_data, create_barcode
from sapl.sessao.views import (get_identificacao_basica, get_mesa_diretora,
get_presenca_sessao, get_expedientes,
@ -601,6 +602,7 @@ def get_sessao_plenaria(sessao, casa):
str(materia.ano)),
"des_numeracao": ' ',
"des_turno": get_turno(materia)[0],
"situacao": materia.materiaemtramitacao_set.first().tramitacao.status,
"txt_ementa": str(materia.ementa),
"materia_observacao": materia.observacao,
"ordem_observacao": expediente_materia.observacao,
@ -705,7 +707,8 @@ def get_sessao_plenaria(sessao, casa):
"txt_ementa": html.unescape(materia.ementa),
"materia_observacao": materia.observacao,
"ordem_observacao": html.unescape(votacao.observacao),
"nom_autor": ''
"nom_autor": '',
"situacao": materia.materiaemtramitacao_set.first().tramitacao.status
})
autoria = materia.autoria_set.all()
@ -1005,6 +1008,8 @@ def relatorio_etiqueta_protocolo(request, nro, ano):
protocolo = Protocolo.objects.filter(numero=nro, ano=ano)
m = MateriaLegislativa.objects.filter(numero_protocolo=nro,ano=ano)
protocolo_data = get_etiqueta_protocolos(protocolo)
pdf = pdf_etiqueta_protocolo_gerar.principal(imagem,
@ -1502,3 +1507,51 @@ def relatorio_sessao_plenaria_pdf(request, pk):
response.write(pdf_file)
return response
def gera_etiqueta_ml(materia_legislativa, base_url):
confg = ConfigEtiquetaMateriaLegislativa.objects.first()
ml_info = unidecode.unidecode("{}/{}-{}".format(materia_legislativa.numero,
materia_legislativa.ano,
materia_legislativa.tipo.sigla))
base64_data = create_barcode(ml_info, 100, 500)
barcode = 'data:image/png;base64,{0}'.format(base64_data)
max_ementa_size = 240
ementa = materia_legislativa.ementa
ementa = ementa if len(ementa) < max_ementa_size else ementa[:max_ementa_size]+"..."
context = {
'numero': materia_legislativa.numero,
'ano': materia_legislativa.ano,
'tipo': materia_legislativa.tipo,
'data_apresentacao':materia_legislativa.data_apresentacao,
'autores': materia_legislativa.autores.all(),
'ementa':ementa,
'largura': confg.largura,
'altura':confg.largura,
'barcode': barcode
}
main_template = render_to_string('relatorios/etiqueta_materia_legislativa.html', context)
html = HTML(base_url=base_url, string=main_template)
main_doc = html.render(stylesheets=[CSS(string="@page {{size: {}cm {}cm;}}".format(confg.largura,confg.altura))])
pdf_file = main_doc.write_pdf()
return pdf_file
def etiqueta_materia_legislativa(request, pk):
base_url = request.build_absolute_uri()
materia_legislativa = MateriaLegislativa.objects.get(pk=pk)
pdf_file = gera_etiqueta_ml(materia_legislativa, base_url)
response = HttpResponse(content_type='application/pdf;')
response['Content-Disposition'] = 'inline; filename=etiqueta.pdf'
response['Content-Transfer-Encoding'] = 'binary'
response.write(pdf_file)
return response

1
sapl/rules/map_rules.py

@ -258,6 +258,7 @@ rules_group_geral = {
(materia.Parecer, __base__, __perms_publicas__),
(materia.StatusTramitacao, __base__, __perms_publicas__),
(materia.UnidadeTramitacao, __base__, __perms_publicas__),
(materia.ConfigEtiquetaMateriaLegislativa, __base__, set()),
(norma.AssuntoNorma, __base__, __perms_publicas__),

158
sapl/sessao/views.py

@ -29,7 +29,7 @@ from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux,
PermissionRequiredForAppCrudMixin, make_pagination)
from sapl.materia.forms import filtra_tramitacao_status
from sapl.materia.models import (Autoria, TipoMateriaLegislativa,
Tramitacao)
Tramitacao, MateriaEmTramitacao)
from sapl.materia.views import MateriaLegislativaPesquisaView
from sapl.parlamentares.models import (Filiacao, Legislatura, Mandato,
Parlamentar, SessaoLegislativa)
@ -228,19 +228,23 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
if t[0] == tramitacao.turno:
turno = t[1]
break
situacao = MateriaEmTramitacao.objects.select_related("materia", "tramitacao")\
.filter(materia=materia).first().tramitacao.status
title_materia = """<a id=id%s href=%s>%s</a> </br>
<b>Processo:</b> %s </br>
<b>Autor:</b> %s </br>
<b>Protocolo:</b> %s </br>
<b>Turno:</b> %s </br>
<b>Situação:</b> %s </br>
""" % (obj.materia.id,
url_materia,
row[1][0],
numeracao if numeracao else '',
autor if autor else '',
num_protocolo if num_protocolo else '',
turno)
turno,
situacao if situacao else '')
# Na linha abaixo, o segundo argumento é None para não colocar
# url em toda a string de title_materia
@ -706,6 +710,8 @@ class OradorCrud(MasterDetailCrud):
class CreateView(MasterDetailCrud.CreateView):
form_class = OradorForm
template_name = 'sessao/oradores_create.html'
def get_initial(self):
return {'id_sessao': self.kwargs['pk']}
@ -718,6 +724,8 @@ class OradorCrud(MasterDetailCrud):
if tipo_sessao.nome == "Solene":
context.update(
{'subnav_template_name': 'sessao/subnav-solene.yaml'})
ultimo_orador = Orador.objects.filter(sessao_plenaria=kwargs['root_pk']).order_by("-numero_ordem").first()
context["ultima_ordem"] = ultimo_orador.numero_ordem if ultimo_orador else 0
return context
def get_success_url(self):
@ -775,6 +783,7 @@ class OradorExpedienteCrud(OradorCrud):
class CreateView(MasterDetailCrud.CreateView):
form_class = OradorExpedienteForm
template_name = 'sessao/oradores_create.html'
def get_initial(self):
return {'id_sessao': self.kwargs['pk']}
@ -787,6 +796,8 @@ class OradorExpedienteCrud(OradorCrud):
if tipo_sessao.nome == "Solene":
context.update(
{'subnav_template_name': 'sessao/subnav-solene.yaml'})
ultimo_orador = OradorExpediente.objects.filter(sessao_plenaria=kwargs['root_pk']).order_by("-numero_ordem").first()
context["ultima_ordem"] = ultimo_orador.numero_ordem if ultimo_orador else 0
return context
def get_success_url(self):
@ -850,9 +861,9 @@ class OradorExpedienteCrud(OradorCrud):
class OradorOrdemDiaCrud(OradorCrud):
model = OradorOrdemDia
class CreateView(MasterDetailCrud.CreateView):
form_class = OradorOrdemDiaForm
template_name = 'sessao/oradores_create.html'
def get_initial(self):
return {'id_sessao': self.kwargs['pk']}
@ -861,6 +872,12 @@ class OradorOrdemDiaCrud(OradorCrud):
return reverse('sapl.sessao:oradorordemdia_list',
kwargs={'pk': self.kwargs['pk']})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
ultimo_orador = OradorOrdemDia.objects.filter(sessao_plenaria=kwargs['root_pk']).order_by("-numero_ordem").first()
context["ultima_ordem"] = ultimo_orador.numero_ordem if ultimo_orador else 0
return context
class UpdateView(MasterDetailCrud.UpdateView):
form_class = OradorOrdemDiaForm
@ -1689,28 +1706,14 @@ def get_expedientes(sessao_plenaria):
def get_materias_expediente(sessao_plenaria):
materias = ExpedienteMateria.objects.filter(
sessao_plenaria_id=sessao_plenaria.id)
materias_expediente = []
for m in materias:
ementa = m.materia.ementa
titulo = m.materia
numero = m.numero_ordem
for m in ExpedienteMateria.objects.select_related("materia").filter(sessao_plenaria_id=sessao_plenaria.id):
tramitacao = ''
tramitacoes = Tramitacao.objects.filter(
materia=m.materia).order_by('-pk')
for aux_tramitacao in tramitacoes:
for aux_tramitacao in Tramitacao.objects.filter(materia=m.materia).order_by('-pk'):
if aux_tramitacao.turno:
tramitacao = aux_tramitacao
break
turno = None
if tramitacao:
turno = get_turno(tramitacao.turno)
rv = m.registrovotacao_set.first()
rp = m.retiradapauta_set.filter(materia=m.materia).first()
if rv:
@ -1720,31 +1723,26 @@ def get_materias_expediente(sessao_plenaria):
resultado = rp.tipo_de_retirada.descricao
resultado_observacao = rp.observacao
else:
if m.tipo_votacao == 4:
resultado = _('Matéria lida')
else:
resultado = _('Matéria não votada')
resultado = _('Matéria lida') if m.tipo_votacao == 4 else _('Matéria não votada')
resultado_observacao = _(' ')
autoria = Autoria.objects.filter(materia_id=m.materia_id)
autor = [str(x.autor) for x in autoria]
mat = {'ementa': ementa,
'titulo': titulo,
'numero': numero,
'turno': turno,
materias_expediente.append({
'ementa': m.materia.ementa,
'titulo': m.materia,
'numero': m.numero_ordem,
'turno': get_turno(tramitacao.turno) if tramitacao else None,
'situacao': m.materia.materiaemtramitacao_set.first().tramitacao.status,
'resultado': resultado,
'resultado_observacao': resultado_observacao,
'autor': autor,
'autor': [str(x.autor) for x in Autoria.objects.select_related("autor").filter(materia_id=m.materia_id)],
'numero_protocolo': m.materia.numero_protocolo,
'numero_processo': m.materia.numeracao_set.last(),
'observacao_materia': m.materia.observacao,
'observacao': m.observacao
}
materias_expediente.append(mat)
})
context = {'materia_expediente': materias_expediente}
return context
return {'materia_expediente': materias_expediente}
def get_oradores_expediente(sessao_plenaria):
@ -1812,26 +1810,14 @@ def get_assinaturas(sessao_plenaria):
def get_materias_ordem_do_dia(sessao_plenaria):
ordem = OrdemDia.objects.filter(sessao_plenaria_id=sessao_plenaria.id)
materias_ordem = []
for o in ordem:
ementa = o.materia.ementa
ementa_observacao = o.observacao
titulo = o.materia
numero = o.numero_ordem
for o in OrdemDia.objects.filter(sessao_plenaria_id=sessao_plenaria.id):
tramitacao = ''
tramitacoes = Tramitacao.objects.filter(
materia=o.materia).order_by('-pk')
for aux_tramitacao in tramitacoes:
for aux_tramitacao in Tramitacao.objects.filter(materia=o.materia).order_by('-pk'):
if aux_tramitacao.turno:
tramitacao = aux_tramitacao
break
turno = None
if tramitacao:
turno = get_turno(tramitacao.turno)
# Verificar resultado
rv = o.registrovotacao_set.filter(materia=o.materia).first()
rp = o.retiradapauta_set.filter(materia=o.materia).first()
@ -1842,43 +1828,35 @@ def get_materias_ordem_do_dia(sessao_plenaria):
resultado = rp.tipo_de_retirada.descricao
resultado_observacao = rp.observacao
else:
if o.tipo_votacao == 4:
resultado = _('Matéria lida')
else:
resultado = _('Matéria não votada')
resultado = _('Matéria lida') if o.tipo_votacao == 4 else _('Matéria não votada')
resultado_observacao = _(' ')
voto_sim = ""
voto_nao = ""
voto_abstencoes = ""
voto_nominal = []
if o.tipo_votacao == 2:
votos = VotoParlamentar.objects.filter(ordem=o.id)
for voto in votos:
aux_voto = (voto.parlamentar.nome_completo, voto.voto)
voto_nominal.append(aux_voto)
try:
for voto in VotoParlamentar.objects.filter(ordem=o.id):
voto_nominal.append((voto.parlamentar.nome_completo, voto.voto))
voto = RegistroVotacao.objects.filter(ordem=o.id).last()
if voto:
voto_sim = voto.numero_votos_sim
voto_nao = voto.numero_votos_nao
voto_abstencoes = voto.numero_abstencoes
except AttributeError:
else:
voto_sim = " Não Informado"
voto_nao = " Não Informado"
voto_abstencoes = " Não Informado"
autoria = Autoria.objects.filter(
materia_id=o.materia_id)
autor = [str(x.autor) for x in autoria]
mat = {'ementa': ementa,
'ementa_observacao': ementa_observacao,
'titulo': titulo,
'numero': numero,
'turno': turno,
materias_ordem.append({
'ementa': o.materia.ementa,
'ementa_observacao': o.observacao,
'titulo': o.materia,
'numero': o.numero_ordem,
'turno': get_turno(tramitacao.turno) if tramitacao else None,
'situacao': o.materia.materiaemtramitacao_set.first().tramitacao.status,
'resultado': resultado,
'resultado_observacao': resultado_observacao,
'autor': autor,
'autor': [str(x.autor) for x in Autoria.objects.select_related("autor").filter(materia_id=o.materia_id)],
'numero_protocolo': o.materia.numero_protocolo,
'numero_processo': o.materia.numeracao_set.last(),
'tipo_votacao': o.TIPO_VOTACAO_CHOICES[o.tipo_votacao],
@ -1887,11 +1865,9 @@ def get_materias_ordem_do_dia(sessao_plenaria):
'voto_abstencoes': voto_abstencoes,
'voto_nominal': voto_nominal,
'observacao': o.observacao
}
materias_ordem.append(mat)
})
context = {'materias_ordem': materias_ordem}
return context
return {'materias_ordem': materias_ordem}
def get_oradores_ordemdia(sessao_plenaria):
@ -1959,13 +1935,9 @@ class ResumoView(DetailView):
context = self.get_context_data(object=self.object)
# Votos de Votação Nominal de Matérias Expediente
materias_expediente_votacao_nominal = ExpedienteMateria.objects.filter(
sessao_plenaria_id=self.object.id,
tipo_votacao=2).order_by('-materia')
votacoes = []
for mevn in materias_expediente_votacao_nominal:
for mevn in ExpedienteMateria.objects.filter(sessao_plenaria_id=self.object.id, tipo_votacao=2)\
.order_by('-materia'):
votos_materia = []
titulo_materia = mevn.materia
registro = RegistroVotacao.objects.filter(expediente=mevn)
@ -1973,11 +1945,10 @@ class ResumoView(DetailView):
for vp in VotoParlamentar.objects.filter(votacao=registro).order_by('parlamentar'):
votos_materia.append(vp)
dados_votacao = {
votacoes.append({
'titulo': titulo_materia,
'votos': votos_materia
}
votacoes.append(dados_votacao)
})
context.update({'votos_nominais_materia_expediente': votacoes})
@ -2011,12 +1982,8 @@ class ResumoView(DetailView):
# =====================================================================
# Matérias Ordem do Dia
# Votos de Votação Nominal de Matérias Ordem do Dia
materias_ordem_dia_votacao_nominal = OrdemDia.objects.filter(
sessao_plenaria_id=self.object.id,
tipo_votacao=2).order_by('-materia')
votacoes_od = []
for modvn in materias_ordem_dia_votacao_nominal:
for modvn in OrdemDia.objects.filter(sessao_plenaria_id=self.object.id, tipo_votacao=2).order_by('-materia'):
votos_materia_od = []
t_materia = modvn.materia
registro_od = RegistroVotacao.objects.filter(ordem=modvn)
@ -2024,11 +1991,10 @@ class ResumoView(DetailView):
for vp_od in VotoParlamentar.objects.filter(votacao=registro_od).order_by('parlamentar'):
votos_materia_od.append(vp_od)
dados_votacao_od = {
votacoes_od.append({
'titulo': t_materia,
'votos': votos_materia_od
}
votacoes_od.append(dados_votacao_od)
})
context.update({'votos_nominais_materia_ordem_dia': votacoes_od})
@ -2803,8 +2769,8 @@ class VotacaoNominalAbstract(SessaoPermissionMixin):
parlamentar=parlamentar)
except ObjectDoesNotExist:
username = self.request.user.username
self.logger.error('user=' + username + '. Objeto voto_parlamentar do ' +
'parlamentar de id={} não existe.'.format(parlamentar.pk))
self.logger.warning('User={}. Objeto voto_parlamentar do parlamentar de id={} não existe.'
.format(username, parlamentar.pk))
yield [parlamentar, None]
else:
yield [parlamentar, voto.voto]
@ -4400,8 +4366,8 @@ class VotacaoEmBlocoNominalView(PermissionRequiredForAppCrudMixin, TemplateView)
parlamentar=parlamentar)
except ObjectDoesNotExist:
username = self.request.user.username
self.logger.error('user=' + username + '. Objeto voto_parlamentar do ' +
'parlamentar de id={} não existe.'.format(parlamentar.pk))
self.logger.warning('User={}. Objeto voto_parlamentar do parlamentar de id={} não existe.'
.format(username, parlamentar.pk))
yield [parlamentar, None]
else:
yield [parlamentar, voto.voto]

2
sapl/settings.py

@ -41,7 +41,7 @@ ALLOWED_HOSTS = ['*']
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login/?next='
SAPL_VERSION = '3.1.161-RC2'
SAPL_VERSION = '3.1.161-RC3'
if DEBUG:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

3
sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js

File diff suppressed because one or more lines are too long

BIN
sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.LICENSE.txt.gz

Binary file not shown.

BIN
sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.gz

Binary file not shown.

1
sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.map

File diff suppressed because one or more lines are too long

BIN
sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.map.gz

Binary file not shown.

3
sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js

File diff suppressed because one or more lines are too long

4
sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.LICENSE.txt → sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.LICENSE.txt

@ -60,7 +60,7 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*!
* jQuery JavaScript Library v3.5.0
* jQuery JavaScript Library v3.5.1
* https://jquery.com/
*
* Includes Sizzle.js
@ -70,7 +70,7 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2020-04-10T15:07Z
* Date: 2020-05-04T22:49Z
*/
/*!

BIN
sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.LICENSE.txt.gz

Binary file not shown.

BIN
sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.gz

Binary file not shown.

1
sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.map

File diff suppressed because one or more lines are too long

BIN
sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.map.gz

Binary file not shown.

4
sapl/static/sapl/frontend/js/parlamentar.35e37659.js → sapl/static/sapl/frontend/js/parlamentar.307451cf.js

@ -1,2 +1,2 @@
(function(e){function a(a){for(var r,s,l=a[0],o=a[1],u=a[2],c=0,f=[];c<l.length;c++)s=l[c],Object.prototype.hasOwnProperty.call(n,s)&&n[s]&&f.push(n[s][0]),n[s]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(e[r]=o[r]);p&&p(a);while(f.length)f.shift()();return i.push.apply(i,u||[]),t()}function t(){for(var e,a=0;a<i.length;a++){for(var t=i[a],r=!0,l=1;l<t.length;l++){var o=t[l];0!==n[o]&&(r=!1)}r&&(i.splice(a--,1),e=s(s.s=t[0]))}return e}var r={},n={parlamentar:0},i=[];function s(a){if(r[a])return r[a].exports;var t=r[a]={i:a,l:!1,exports:{}};return e[a].call(t.exports,t,t.exports,s),t.l=!0,t.exports}s.m=e,s.c=r,s.d=function(e,a,t){s.o(e,a)||Object.defineProperty(e,a,{enumerable:!0,get:t})},s.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.t=function(e,a){if(1&a&&(e=s(e)),8&a)return e;if(4&a&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(s.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&a&&"string"!=typeof e)for(var r in e)s.d(t,r,function(a){return e[a]}.bind(null,r));return t},s.n=function(e){var a=e&&e.__esModule?function(){return e["default"]}:function(){return e};return s.d(a,"a",a),a},s.o=function(e,a){return Object.prototype.hasOwnProperty.call(e,a)},s.p="/static/sapl/frontend/";var l=window["webpackJsonp"]=window["webpackJsonp"]||[],o=l.push.bind(l);l.push=a,l=l.slice();for(var u=0;u<l.length;u++)a(l[u]);var p=o;i.push([3,"chunk-vendors"]),t()})({3:function(e,a,t){e.exports=t("71e4")},"49c2":function(e,a,t){},"71e4":function(e,a,t){"use strict";t.r(a),function(e){t("4de4"),t("e260"),t("e6cf"),t("cca6"),t("a79d"),t("49c2");var a=t("a026"),r=t("44d4"),n=t("bc3a"),i=t.n(n);i.a.defaults.xsrfCookieName="csrftoken",i.a.defaults.xsrfHeaderName="X-CSRFToken",a["a"].use(r["a"]);new a["a"]({delimiters:["[[","]]"],el:"#app2",data:function(){return{nome_pesquisa:"",is_pesquisa:!1,legislatura_selecionada:"",legislaturas:[],parlamentares:[],visible_parlamentares:[],size_parlamentares:0,filter_ativo:"",filter_titular:""}},watch:{nome_pesquisa:function(e){this.debouncepesquisaParlamentar()}},created:function(){this.debouncepesquisaParlamentar=e.debounce(this.pesquisaParlamentar,500)},methods:{getParlamentares:function(e){var a=this;this.legislatura_selecionada&&i.a.get("/api/parlamentares/parlamentar/"+this.legislatura_selecionada+"/parlamentares_by_legislatura/").then((function(e){a.parlamentares=e.data,a.visible_parlamentares=a.parlamentares,a.size_parlamentares=a.visible_parlamentares.length})).catch((function(e){}))},pesquisaParlamentar:function(e){var a=this;i.a.get("/api/parlamentares/parlamentar/search_parlamentares/",{params:{nome_parlamentar:this.nome_pesquisa}}).then((function(e){a.parlamentares=e.data,a.visible_parlamentares=a.parlamentares,a.size_parlamentares=a.visible_parlamentares.length})).catch((function(e){}))},checkTitularAtivo:function(e){this.visible_parlamentares=this.parlamentares,this.filter_ativo&&(this.visible_parlamentares=this.visible_parlamentares.filter((function(e){return e.ativo}))),this.filter_titular&&(this.visible_parlamentares=this.visible_parlamentares.filter((function(e){return"Sim"===e.titular}))),this.size_parlamentares=this.visible_parlamentares.length},pesquisaChange:function(e){this.is_pesquisa=!this.is_pesquisa,this.filter_ativo=!1,this.is_pesquisa?this.parlamentares=[]:this.getParlamentares()}},mounted:function(){var e=this;i.a.get("/api/parlamentares/legislatura/?get_all=true").then((function(a){e.legislaturas=a.data,e.legislatura_selecionada=a.data[0].id})).then((function(a){e.getParlamentares()})).catch((function(e){}))}})}.call(this,t("2ef0"))}});
//# sourceMappingURL=parlamentar.35e37659.js.map
(function(e){function a(a){for(var r,s,l=a[0],o=a[1],u=a[2],c=0,f=[];c<l.length;c++)s=l[c],Object.prototype.hasOwnProperty.call(n,s)&&n[s]&&f.push(n[s][0]),n[s]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(e[r]=o[r]);p&&p(a);while(f.length)f.shift()();return i.push.apply(i,u||[]),t()}function t(){for(var e,a=0;a<i.length;a++){for(var t=i[a],r=!0,l=1;l<t.length;l++){var o=t[l];0!==n[o]&&(r=!1)}r&&(i.splice(a--,1),e=s(s.s=t[0]))}return e}var r={},n={parlamentar:0},i=[];function s(a){if(r[a])return r[a].exports;var t=r[a]={i:a,l:!1,exports:{}};return e[a].call(t.exports,t,t.exports,s),t.l=!0,t.exports}s.m=e,s.c=r,s.d=function(e,a,t){s.o(e,a)||Object.defineProperty(e,a,{enumerable:!0,get:t})},s.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.t=function(e,a){if(1&a&&(e=s(e)),8&a)return e;if(4&a&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(s.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&a&&"string"!=typeof e)for(var r in e)s.d(t,r,function(a){return e[a]}.bind(null,r));return t},s.n=function(e){var a=e&&e.__esModule?function(){return e["default"]}:function(){return e};return s.d(a,"a",a),a},s.o=function(e,a){return Object.prototype.hasOwnProperty.call(e,a)},s.p="/static/sapl/frontend/";var l=window["webpackJsonp"]=window["webpackJsonp"]||[],o=l.push.bind(l);l.push=a,l=l.slice();for(var u=0;u<l.length;u++)a(l[u]);var p=o;i.push([3,"chunk-vendors"]),t()})({3:function(e,a,t){e.exports=t("71e4")},"49c2":function(e,a,t){},"71e4":function(e,a,t){"use strict";t.r(a),function(e){t("4de4"),t("e260"),t("e6cf"),t("cca6"),t("a79d"),t("49c2");var a=t("a026"),r=t("44d4"),n=t("bc3a"),i=t.n(n);i.a.defaults.xsrfCookieName="csrftoken",i.a.defaults.xsrfHeaderName="X-CSRFToken",a["a"].use(r["a"]);new a["a"]({delimiters:["[[","]]"],el:"#app2",data:function(){return{nome_pesquisa:"",is_pesquisa:!1,legislatura_selecionada:"",legislaturas:[],parlamentares:[],visible_parlamentares:[],size_parlamentares:0,filter_ativo:!0,filter_titular:""}},watch:{nome_pesquisa:function(e){this.debouncepesquisaParlamentar()}},created:function(){this.debouncepesquisaParlamentar=e.debounce(this.pesquisaParlamentar,500)},methods:{getParlamentares:function(e){var a=this;this.legislatura_selecionada&&i.a.get("/api/parlamentares/parlamentar/"+this.legislatura_selecionada+"/parlamentares_by_legislatura/").then((function(e){a.parlamentares=e.data,a.visible_parlamentares=a.parlamentares,a.size_parlamentares=a.visible_parlamentares.length,a.checkTitularAtivo()})).catch((function(e){}))},pesquisaParlamentar:function(e){var a=this;i.a.get("/api/parlamentares/parlamentar/search_parlamentares/",{params:{nome_parlamentar:this.nome_pesquisa}}).then((function(e){a.parlamentares=e.data,a.visible_parlamentares=a.parlamentares,a.size_parlamentares=a.visible_parlamentares.length})).catch((function(e){}))},checkTitularAtivo:function(e){this.visible_parlamentares=this.parlamentares,this.filter_ativo&&(this.visible_parlamentares=this.visible_parlamentares.filter((function(e){return e.ativo}))),this.filter_titular&&(this.visible_parlamentares=this.visible_parlamentares.filter((function(e){return"Sim"===e.titular}))),this.size_parlamentares=this.visible_parlamentares.length},pesquisaChange:function(e){this.is_pesquisa=!this.is_pesquisa,this.filter_ativo=!1,this.is_pesquisa?this.parlamentares=[]:this.getParlamentares()}},mounted:function(){var e=this;i.a.get("/api/parlamentares/legislatura/?get_all=true").then((function(a){e.legislaturas=a.data,e.legislatura_selecionada=a.data[0].id})).then((function(a){e.getParlamentares()})).catch((function(e){}))}})}.call(this,t("2ef0"))}});
//# sourceMappingURL=parlamentar.307451cf.js.map

BIN
sapl/static/sapl/frontend/js/parlamentar.307451cf.js.gz

Binary file not shown.

1
sapl/static/sapl/frontend/js/parlamentar.307451cf.js.map

File diff suppressed because one or more lines are too long

BIN
sapl/static/sapl/frontend/js/parlamentar.307451cf.js.map.gz

Binary file not shown.

BIN
sapl/static/sapl/frontend/js/parlamentar.35e37659.js.gz

Binary file not shown.

1
sapl/static/sapl/frontend/js/parlamentar.35e37659.js.map

File diff suppressed because one or more lines are too long

BIN
sapl/static/sapl/frontend/js/parlamentar.35e37659.js.map.gz

Binary file not shown.

2
sapl/templates/base.html

@ -179,7 +179,7 @@
<small>
Desenvolvido pelo <a href="http://www.interlegis.leg.br/">Interlegis</a> em software livre e aberto.
</small>
<span>Release: 3.1.161-RC2</span>
<span>Release: 3.1.161-RC3</span>
</p>
</div>
<div class="col-md-4">

14
sapl/templates/base/autor_detail.html

@ -0,0 +1,14 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load crispy_forms_tags staticfiles %}
{% block sub_actions %}
<div class="actions btn-group btn-group-sm" role="group">
<a href="{% url 'sapl.base:pesquisar_autor' %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Pesquisar {{ verbose_name }} {% endblocktrans %}
</a>
<a href="{{ view.create_url }}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %}
</a>
</div>
{% endblock sub_actions %}

51
sapl/templates/base/autor_filter.html

@ -0,0 +1,51 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load crispy_forms_tags staticfiles %}
{% block base_content %}
{% if not show_results %}
{% crispy filter.form %}
{% else %}
<div class="actions btn-group float-right btn-group-sm" role="group">
<a href="{% url 'sapl.base:pesquisar_autor' %}" class="btn btn-outline-primary">{% trans 'Fazer nova pesquisa' %}</a>
{% if not request.user.is_anonymous %}
<a href="{% url 'sapl.base:autor_create' %}"class="btn btn-outline-primary">Cadastrar Autor</a>
{% endif %}
</div>
<br>
{% if numero_res > 0 %}
{% if numero_res == 1 %}
<p>Foi encontrado {{ numero_res }} resultado</p>
{% else %}
<p>Foram encontrados {{ numero_res }} resultados</p>
{% endif %}
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Tipo do Autor</th>
<th>Nome do Autor</th>
<th>Usuário</th>
</tr>
</thead>
<tbody>
{% for autor in page_obj %}
<tr>
<td>{{ autor.tipo }}</td>
<td>
<a href="{% url 'sapl.base:autor_detail' autor.pk %}">
{% if autor.nome %} {{ autor.nome }} {% else %} - {% endif %}
</a>
</td>
<td>{% if autor.user %} {{ autor.user }} {% else %} - {% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<font size="4"><p align="center">{{ NO_ENTRIES_MSG }}</p></font>
{% endif %}
{% endif %}
<br/>
{% include 'paginacao.html'%}
<br /><br /><br />
{% endblock base_content %}

19
sapl/templates/materia/config_etiqueta_materia.html

@ -0,0 +1,19 @@
{% extends "crud/form.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block base_content %}
<h1>Configuração Etiqueta Materia Legislativa</h1>
<form action="." method="post">
{% csrf_token %}
{{ form|crispy }}
<div class="row">
<div class="col-md-12">
<div class="form-group row justify-content-between">
<a href="{% url 'sapl.base:sistema' %}" class="btn btn-dark">Cancelar</a>
<input type="submit" name="salvar" value="Salvar" class="btn btn-primary float-right" id="submit-id-salvar" onclick="this.form.submit();this.disabled=true;">
</div>
</div>
</div>
</form>
{% endblock base_content %}

6
sapl/templates/materia/layouts.yaml

@ -157,3 +157,9 @@ MateriaLegislativaDetail:
- ementa
- indexacao
- observacao
ConfigEtiquetaMateriaLegislativa:
{% trans 'Configurações de Etiqueta' %}:
- largura
- altura
- mostrar_em_arquivo

6
sapl/templates/materia/materialegislativa_detail.html

@ -10,6 +10,12 @@
{% endif %}
{% endblock sub_actions %}
{% block editions %}
{{ block.super }}
<a href="{% url 'sapl.relatorios:etiqueta_materia_legislativa' object.pk %}" class="btn btn-outline-primary">{% trans 'Etiqueta' %}</a>
{% endblock editions %}
{% block detail_content %}
{{ block.super }}
{% if object.registrovotacao_set.exists %}

2
sapl/templates/materia/materialegislativa_filter.html

@ -1,6 +1,7 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load crispy_forms_tags common_tags%}
{% load webpack_static from webpack_loader %}
{% block actions %}
@ -47,6 +48,7 @@
<tr>
<td>
<strong><a href="{% url 'sapl.materia:materialegislativa_detail' m.id %}">{{m.tipo.sigla}} {{m.numero}}/{{m.ano}} - {{m.tipo}}</strong></a>
<a href="{% url 'sapl.relatorios:etiqueta_materia_legislativa' m.pk %}"><img src="{% webpack_static 'img/etiqueta.png' %}" alt="Etiqueta Individual"></a>
</br>
<strong>Ementa:</strong>&nbsp;{{ m.ementa|dont_break_out }}
</br>

38
sapl/templates/materia/materialegislativa_form.html

@ -1,23 +1,20 @@
{% extends "crud/form.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load common_tags %}
{% block extra_js %}
<script language="Javascript">
<script language="Javascript">
function recuperar_numero_ano() {
var tipo = $("#id_tipo").val()
var ano = $("#id_ano").val()
if (tipo) {
$.get("/materia/recuperar-materia",{tipo: tipo, ano: ano},
function(data, status) {
if (tipo){
$.get("/materia/recuperar-materia", { tipo: tipo, ano: ano },
function (data, status) {
$("#id_numero").val(data.numero);
$("#id_ano").val(data.ano);
console.log(data)
console.log(data);
});
}
}
@ -55,27 +52,29 @@
+'Compreendo e quero continuar</button>'
+'</div></div>';
function verifica_ano(){
function verifica_ano() {
let ano = $("select#id_ano.select").val();
let data_apresentacao = $("input#id_data_apresentacao.dateinput").val();
let ano_apresentacao = data_apresentacao.substr(data_apresentacao.length - 4);
if(ano && ano_apresentacao && ano_apresentacao != ano){
if (ano && ano_apresentacao && ano_apresentacao != ano){
$('#fundo_modal').fadeIn();
}
}
$(document).ready(function() {
$("#id_tipo_autor").change(function() {
$(document).ready( function() {
$("#id_tipo_autor, #id_data_apresentacao").change( function() {
var tipo_selecionado = $("#id_tipo_autor").val();
var autor_selecionado = $("#id_autor").val();
$("#id_autor option").remove()
if (tipo_selecionado !== undefined && tipo_selecionado !== null) {
if (tipo_selecionado !== undefined && tipo_selecionado !== null){
var json_data = {
tipo : tipo_selecionado,
data_relativa : $("#id_data_apresentacao").val()
}
$.getJSON("/api/autor/possiveis", json_data, function(data){
$.getJSON("/api/autor/possiveis", json_data, function(data) {
if (data) {
var results = data.sort(compare);
if (results.length > 1) {
@ -96,16 +95,15 @@
$("body").append(meu_modal);
$("#fundo_modal, #close_model_btn").click(function(){ $("#fundo_modal").hide(); });
$("#meu_modal").click(function(e){ e.stopPropagation(); });
$("#fundo_modal, #close_model_btn").click( function() { $("#fundo_modal").hide(); });
$("#meu_modal").click( function(e) { e.stopPropagation(); });
$("select#id_ano.select.form-control").change(function(){
$("select#id_ano.select.form-control").change( function() {
verifica_ano();
});
$("input#id_data_apresentacao.dateinput.form-control").change(function(){
$("input#id_data_apresentacao.dateinput.form-control").change( function() {
verifica_ano();
});
});
</script>
</script>
{% endblock %}

2
sapl/templates/materia/tramitacao_detail.html

@ -3,7 +3,7 @@
{% block detail_content %}
{{ block.super }}
{% if user.is_superuser %}
{% if 'materia.detail_tramitacao' in request.user.get_all_permissions %}
<div class="row">
{% if tramitacao.user %}
<div class="col-sm-4">

10
sapl/templates/menu_tabelas_auxiliares.yaml

@ -8,8 +8,11 @@
- title: {% trans 'Configurações da Aplicação' %}
url: sapl.base:appconfig_list
css_class: btn btn-link
- title: {% trans 'Autor' %}
url: sapl.base:autor_list
- title: {% trans 'Pesquisar Autor' %}
url: sapl.base:pesquisar_autor
css_class: btn btn-link
- title: {% trans 'Adicionar Autor' %}
url: sapl.base:autor_create
css_class: btn btn-link
- title: {% trans 'Tipo de Autor' %}
url: sapl.base:tipoautor_list
@ -116,6 +119,9 @@
- title: {% trans 'Assunto Matéria' %}
url: sapl.materia:assuntomateria_list
css_class: btn btn-link
- title: {% trans 'Configuração Etiqueta Materia Legislativa' %}
url: sapl.materia:configEtiquetaMateriaLegislativaCrud
css_class: btn btn-link
- title: {% trans 'Módulo Normas Jurídicas' %}
css_class: head_title
children:

104
sapl/templates/norma/normajuridica_form.html

@ -10,20 +10,23 @@
var tipo_materia = $("#id_tipo_materia").val();
var numero_materia = $("#id_numero_materia").val();
var ano_materia = $("#id_ano_materia").val();
var tipo = $('#id_tipo').val();
var ano = $('#id_ano').val();
var numero = $('#id_numero').val();
var ementa = $('#id_ementa').val();
if (tipo_materia && numero_materia && ano_materia) {
$.get("/sessao/recuperar-materia",
{tipo_materia: tipo_materia,
$.get("/sessao/recuperar-materia", {
tipo_materia: tipo_materia,
numero_materia: numero_materia,
ano_materia: ano_materia},
function(data, status) {
ano_materia: ano_materia
}, (data, status) => {
$("#id_fundo_confirmacao_mudanca_ementa_indexacao").fadeIn();
$("#id_sim_mudanca_ementa_indexacao").click(() => {
$("#id_ementa").val(data.ementa);
$("#id_indexacao").val(data.indexacao);
}
);
$("#id_fundo_confirmacao_mudanca_ementa_indexacao").hide();
});
$("#id_nao_mudanca_ementa_indexacao").click(() => {
$("#id_fundo_confirmacao_mudanca_ementa_indexacao").hide();
});
});
}
}
var fields = ["#id_tipo_materia", "#id_numero_materia", "#id_ano_materia"]
@ -36,9 +39,8 @@
var ano = $("#id_ano").val();
if (tipo) {
$.get("/norma/recuperar-numero-norma",{tipo: tipo,
ano: ano},
function(data, status) {
$.get("/norma/recuperar-numero-norma", { tipo: tipo, ano: ano },
(data, status) => {
$("#id_numero").val(data.numero);
$("#id_ano").val(data.ano);
});
@ -58,29 +60,57 @@
}
});
var modal_estilos = 'display: block;'
+'width: 85%; max-width: 600px;'
+'background: #fff; padding: 15px;'
+'border-radius: 5px;'
+'-webkit-box-shadow: 0px 6px 14px -2px rgba(0,0,0,0.75);'
+'-moz-box-shadow: 0px 6px 14px -2px rgba(0,0,0,0.75);'
+'box-shadow: 0px 6px 14px -2px rgba(0,0,0,0.75);'
+'position: fixed;'
+'top: 50%; left: 50%;'
+'transform: translate(-50%,-50%);'
+'z-index: 99999999; text-align: center';
var fundo_modal_estilos = 'top: 0; right: 0;'
+'bottom: 0; left: 0; position: fixed;'
+'background-color: rgba(0, 0, 0, 0.6); z-index: 99999999;'
+'display: none;';
var meu_modal = '<div id="fundo_modal" style="'+fundo_modal_estilos+'">'
+'<div id="meu_modal" style="'+modal_estilos+'">'
+'<h2>Atenção! Ano de apresentação e ano da norma são diferentes.</h2><br />'
+'<button id="close_model_btn" type="button" class="btn btn-warning" data-dismiss="modal">'
+'Compreendo e quero continuar</button>'
+'</div></div>';
var modal_estilos = `
display: block;
width: 85%;
max-width: 600px;
background: #fff;
padding: 15px;
border-radius: 5px;
-webkit-box-shadow: 0px 6px 14px -2px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 6px 14px -2px rgba(0,0,0,0.75);
box-shadow: 0px 6px 14px -2px rgba(0,0,0,0.75);
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
z-index: 99999999;
text-align: center;
`;
var fundo_modal_estilos = `
top: 0;
right: 0;
bottom: 0;
left: 0;
position: fixed;
background-color: rgba(0, 0, 0, 0.6);
z-index: 99999999;
display: none;
`;
var meu_modal = `
<div id="fundo_modal" style="${fundo_modal_estilos}">
<div id="meu_modal" style="${modal_estilos}">
<h2>Atenção! Ano de apresentação e ano da norma são diferentes.</h2><br />
<button id="close_model_btn" type="button" class="btn btn-warning" data-dismiss="modal">
Compreendo e quero continuar
</button>
</div>
</div>
`;
const confirmacao_mudanca_ementa_indexacao = `
<div id="id_fundo_confirmacao_mudanca_ementa_indexacao" style="${fundo_modal_estilos}">
<div id="id_confirmacao_mudanca_ementa_indexacao" style="${modal_estilos}">
<h3>Houve à mudança de Matéria vinculada a norma.</h3>
<h3>Deseja atualizar a Ementa e a Indexação com a nova Matéria?</h3><br/>
<button type="submit" id="id_sim_mudanca_ementa_indexacao" class="btn btn-primary">Sim</button>
<button type="button" id="id_nao_mudanca_ementa_indexacao" class="btn btn-secondary" data-dismiss="modal">Não</button>
</div>
</div>
`;
function verifica_ano(){
let ano = $("select#id_ano.select").val();
@ -93,7 +123,7 @@
}
$(document).ready(function() {
$("body").append(meu_modal);
$("body").append(meu_modal, confirmacao_mudanca_ementa_indexacao);
$("#fundo_modal, #close_model_btn").click(function(){ $("#fundo_modal").hide(); });
$("#meu_modal").click(function(e){ e.stopPropagation(); });

3
sapl/templates/relatorios/blocos_sessao_plenaria/materias_expediente.html

@ -18,6 +18,9 @@
<dt><b>{{materia.num_ordem}} -</b> {{materia.id_materia}}</dt>
<dt style="text-align: left;"><b>Turno:</b> {{materia.des_turno}}</dt>
<dt style="text-align: left;"><b>{{materia.num_autores}}: </b>{{materia.nom_autor}}</dt>
{% if materia.situacao %}
<dt style="text-align: left;"><b>Situação: </b>{{materia.situacao}}</dt>
{% endif %}
</dl>
</td>
<td style="width:60%"><div style="margin:10px">{{materia.txt_ementa}}<br>{{materia.ordem_observacao}}</div></td>

3
sapl/templates/relatorios/blocos_sessao_plenaria/materias_ordemdia.html

@ -16,6 +16,9 @@
<dt><b>{{materia.num_ordem}} -</b> {{materia.id_materia}}</dt>
<dt style="text-align: left;"><b>Turno:</b> {{materia.des_turno}}</dt>
<dt style="text-align: left;"><b>{{materia.num_autores}}: </b>{{materia.nom_autor}}</dt>
{% if materia.situacao %}
<dt style="text-align: left;"><b>Situação: </b>{{materia.situacao}}</dt>
{% endif %}
</dl>
</td>
<td style="width:60%">{{materia.txt_ementa}} <br>{{materia.ordem_observacao}}</td>

40
sapl/templates/relatorios/etiqueta_materia_legislativa.html

@ -0,0 +1,40 @@
{% load i18n %}
{% load crispy_forms_tags %}
{% load common_tags %}
{% load static %}
<head>
<style>
@page{
margin: 0cm
}
div {page-break-inside: avoid;}
p {
font-size:4pt;
margin: 5px;
font-family: Georgia, Times, "Times New Roman";
}
img {
position: absolute;
bottom:0px;
left: 0px;
padding:10px;
height: 20px;
width: 90%;
}
</style>
</head>
<body>
<div>
<p><strong>Materia Legislativa - {{numero}}/{{ano}}</strong></p>
<p>Tipo: {{tipo.sigla}} - {{tipo.descricao}}</p>
<p>Data: {{data_apresentacao}}</p>
<p>Ementa: {{ementa}}</p>
<img src="{{barcode}}">
</div>
</body>

4
sapl/templates/relatorios/relatorio_pauta_sessao.html

@ -19,7 +19,7 @@
<thead><tr><th>Matéria</th><th>Ementa</th></tr></thead>
{% for m in materia_expediente %}
<tr>
<td style="width:20%;">
<td style="width:30%; font-size: x-small;">
{{ m.numero }} - {{ m.titulo }}<br />
<b>Autor{{ m.autor|length|pluralize:"es" }}</b>: {{ m.autor|join:', ' }}
</td>
@ -38,7 +38,7 @@
<thead><tr><th>Matéria</th><th>Ementa</th></tr></thead>
{% for m in materias_ordem %}
<tr>
<td style="width:20%;">
<td style="width:30%; font-size: x-small;">
{{m.numero}} - <b">{{m.titulo}}</b><br />
<b>Autor{{ m.autor|length|pluralize:"es" }}</b>: {{ m.autor|join:', ' }}
</td>

3
sapl/templates/sessao/blocos_ata/materias_expediente.html

@ -15,6 +15,9 @@
{% if m.turno %}
Turno: {{m.turno}},
{% endif %}
{% if m.situacao %}
Situação: {{m.situacao}},
{% endif %}
{% if m.tipo_votacao %}
Tipo: {{m.tipo_votacao}},
Sim: {{ m.voto_sim }},

3
sapl/templates/sessao/blocos_ata/materias_ordem_dia.html

@ -15,6 +15,9 @@
{% if m.turno %}
Turno: {{m.turno}},
{% endif %}
{% if m.situacao %}
Situação: {{m.situacao}},
{% endif %}
{% if m.tipo_votacao %}
Tipo: {{m.tipo_votacao}},
Sim: {{ m.voto_sim }},

5
sapl/templates/sessao/blocos_resumo/materias_expediente.html

@ -34,6 +34,11 @@
<br />
<b>Processo:</b> {{ m.numero_processo }}
{% endif %}
{% if m.situacao %}
<br />
<b>Situação:</b> {{ m.situacao }}
{% endif %}
</td>
<td>
{{m.ementa|dont_break_out}}<br/>

5
sapl/templates/sessao/blocos_resumo/materias_ordem_dia.html

@ -35,6 +35,11 @@
<br />
<b>Processo:</b> {{ m.numero_processo }}
{% endif %}
{% if m.situacao %}
<br />
<b>Situação:</b> {{ m.situacao }}
{% endif %}
</td>
<td>{{m.ementa|dont_break_out}}</b><br/>{{m.observacao|dont_break_out}}</td>
<td><b>{{m.resultado}}</b><br/>{{m.resultado_observacao}}</td>

17
sapl/templates/sessao/oradores_create.html

@ -0,0 +1,17 @@
{% extends "crud/form.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load common_tags %}
{% block extra_js %}
<script type="text/javascript" >
$(document).ready(function(){
if("{{ultima_ordem}}" != "None"){
$("#id_numero_ordem").val({{ultima_ordem}}+1);
}
else{
$("#id_numero_ordem").val(1);
}
});
</script>
{% endblock extra_js %}

2
sapl/webpack-stats.json

@ -1 +1 @@
{"status":"done","publicPath":"/static/sapl/frontend/","chunks":{"chunk-vendors":[{"name":"css/chunk-vendors.42151acc.css","publicPath":"/static/sapl/frontend/css/chunk-vendors.42151acc.css","path":"../sapl/sapl/static/sapl/frontend/css/chunk-vendors.42151acc.css"},{"name":"js/chunk-vendors.f89f6c45.js","publicPath":"/static/sapl/frontend/js/chunk-vendors.f89f6c45.js","path":"../sapl/sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js"},{"name":"css/chunk-vendors.42151acc.css.map","publicPath":"/static/sapl/frontend/css/chunk-vendors.42151acc.css.map","path":"../sapl/sapl/static/sapl/frontend/css/chunk-vendors.42151acc.css.map"},{"name":"js/chunk-vendors.f89f6c45.js.map","publicPath":"/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.map","path":"../sapl/sapl/static/sapl/frontend/js/chunk-vendors.f89f6c45.js.map"}],"compilacao":[{"name":"css/compilacao.eff62463.css","publicPath":"/static/sapl/frontend/css/compilacao.eff62463.css","path":"../sapl/sapl/static/sapl/frontend/css/compilacao.eff62463.css"},{"name":"js/compilacao.d421699a.js","publicPath":"/static/sapl/frontend/js/compilacao.d421699a.js","path":"../sapl/sapl/static/sapl/frontend/js/compilacao.d421699a.js"},{"name":"css/compilacao.eff62463.css.map","publicPath":"/static/sapl/frontend/css/compilacao.eff62463.css.map","path":"../sapl/sapl/static/sapl/frontend/css/compilacao.eff62463.css.map"},{"name":"js/compilacao.d421699a.js.map","publicPath":"/static/sapl/frontend/js/compilacao.d421699a.js.map","path":"../sapl/sapl/static/sapl/frontend/js/compilacao.d421699a.js.map"}],"global":[{"name":"css/global.278b5d61.css","publicPath":"/static/sapl/frontend/css/global.278b5d61.css","path":"../sapl/sapl/static/sapl/frontend/css/global.278b5d61.css"},{"name":"js/global.49490c4a.js","publicPath":"/static/sapl/frontend/js/global.49490c4a.js","path":"../sapl/sapl/static/sapl/frontend/js/global.49490c4a.js"},{"name":"css/global.278b5d61.css.map","publicPath":"/static/sapl/frontend/css/global.278b5d61.css.map","path":"../sapl/sapl/static/sapl/frontend/css/global.278b5d61.css.map"},{"name":"js/global.49490c4a.js.map","publicPath":"/static/sapl/frontend/js/global.49490c4a.js.map","path":"../sapl/sapl/static/sapl/frontend/js/global.49490c4a.js.map"}],"painel":[{"name":"css/painel.5d957a9b.css","publicPath":"/static/sapl/frontend/css/painel.5d957a9b.css","path":"../sapl/sapl/static/sapl/frontend/css/painel.5d957a9b.css"},{"name":"js/painel.33e8b8a5.js","publicPath":"/static/sapl/frontend/js/painel.33e8b8a5.js","path":"../sapl/sapl/static/sapl/frontend/js/painel.33e8b8a5.js"},{"name":"css/painel.5d957a9b.css.map","publicPath":"/static/sapl/frontend/css/painel.5d957a9b.css.map","path":"../sapl/sapl/static/sapl/frontend/css/painel.5d957a9b.css.map"},{"name":"js/painel.33e8b8a5.js.map","publicPath":"/static/sapl/frontend/js/painel.33e8b8a5.js.map","path":"../sapl/sapl/static/sapl/frontend/js/painel.33e8b8a5.js.map"}],"parlamentar":[{"name":"css/parlamentar.0e433876.css","publicPath":"/static/sapl/frontend/css/parlamentar.0e433876.css","path":"../sapl/sapl/static/sapl/frontend/css/parlamentar.0e433876.css"},{"name":"js/parlamentar.35e37659.js","publicPath":"/static/sapl/frontend/js/parlamentar.35e37659.js","path":"../sapl/sapl/static/sapl/frontend/js/parlamentar.35e37659.js"},{"name":"css/parlamentar.0e433876.css.map","publicPath":"/static/sapl/frontend/css/parlamentar.0e433876.css.map","path":"../sapl/sapl/static/sapl/frontend/css/parlamentar.0e433876.css.map"},{"name":"js/parlamentar.35e37659.js.map","publicPath":"/static/sapl/frontend/js/parlamentar.35e37659.js.map","path":"../sapl/sapl/static/sapl/frontend/js/parlamentar.35e37659.js.map"}]}}
{"status":"done","publicPath":"/static/sapl/frontend/","chunks":{"chunk-vendors":[{"name":"css/chunk-vendors.42151acc.css","publicPath":"/static/sapl/frontend/css/chunk-vendors.42151acc.css","path":"../sapl/sapl/static/sapl/frontend/css/chunk-vendors.42151acc.css"},{"name":"js/chunk-vendors.f8cff174.js","publicPath":"/static/sapl/frontend/js/chunk-vendors.f8cff174.js","path":"../sapl/sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js"},{"name":"css/chunk-vendors.42151acc.css.map","publicPath":"/static/sapl/frontend/css/chunk-vendors.42151acc.css.map","path":"../sapl/sapl/static/sapl/frontend/css/chunk-vendors.42151acc.css.map"},{"name":"js/chunk-vendors.f8cff174.js.map","publicPath":"/static/sapl/frontend/js/chunk-vendors.f8cff174.js.map","path":"../sapl/sapl/static/sapl/frontend/js/chunk-vendors.f8cff174.js.map"}],"compilacao":[{"name":"css/compilacao.eff62463.css","publicPath":"/static/sapl/frontend/css/compilacao.eff62463.css","path":"../sapl/sapl/static/sapl/frontend/css/compilacao.eff62463.css"},{"name":"js/compilacao.d421699a.js","publicPath":"/static/sapl/frontend/js/compilacao.d421699a.js","path":"../sapl/sapl/static/sapl/frontend/js/compilacao.d421699a.js"},{"name":"css/compilacao.eff62463.css.map","publicPath":"/static/sapl/frontend/css/compilacao.eff62463.css.map","path":"../sapl/sapl/static/sapl/frontend/css/compilacao.eff62463.css.map"},{"name":"js/compilacao.d421699a.js.map","publicPath":"/static/sapl/frontend/js/compilacao.d421699a.js.map","path":"../sapl/sapl/static/sapl/frontend/js/compilacao.d421699a.js.map"}],"global":[{"name":"css/global.278b5d61.css","publicPath":"/static/sapl/frontend/css/global.278b5d61.css","path":"../sapl/sapl/static/sapl/frontend/css/global.278b5d61.css"},{"name":"js/global.49490c4a.js","publicPath":"/static/sapl/frontend/js/global.49490c4a.js","path":"../sapl/sapl/static/sapl/frontend/js/global.49490c4a.js"},{"name":"css/global.278b5d61.css.map","publicPath":"/static/sapl/frontend/css/global.278b5d61.css.map","path":"../sapl/sapl/static/sapl/frontend/css/global.278b5d61.css.map"},{"name":"js/global.49490c4a.js.map","publicPath":"/static/sapl/frontend/js/global.49490c4a.js.map","path":"../sapl/sapl/static/sapl/frontend/js/global.49490c4a.js.map"}],"painel":[{"name":"css/painel.5d957a9b.css","publicPath":"/static/sapl/frontend/css/painel.5d957a9b.css","path":"../sapl/sapl/static/sapl/frontend/css/painel.5d957a9b.css"},{"name":"js/painel.33e8b8a5.js","publicPath":"/static/sapl/frontend/js/painel.33e8b8a5.js","path":"../sapl/sapl/static/sapl/frontend/js/painel.33e8b8a5.js"},{"name":"css/painel.5d957a9b.css.map","publicPath":"/static/sapl/frontend/css/painel.5d957a9b.css.map","path":"../sapl/sapl/static/sapl/frontend/css/painel.5d957a9b.css.map"},{"name":"js/painel.33e8b8a5.js.map","publicPath":"/static/sapl/frontend/js/painel.33e8b8a5.js.map","path":"../sapl/sapl/static/sapl/frontend/js/painel.33e8b8a5.js.map"}],"parlamentar":[{"name":"css/parlamentar.0e433876.css","publicPath":"/static/sapl/frontend/css/parlamentar.0e433876.css","path":"../sapl/sapl/static/sapl/frontend/css/parlamentar.0e433876.css"},{"name":"js/parlamentar.307451cf.js","publicPath":"/static/sapl/frontend/js/parlamentar.307451cf.js","path":"../sapl/sapl/static/sapl/frontend/js/parlamentar.307451cf.js"},{"name":"css/parlamentar.0e433876.css.map","publicPath":"/static/sapl/frontend/css/parlamentar.0e433876.css.map","path":"../sapl/sapl/static/sapl/frontend/css/parlamentar.0e433876.css.map"},{"name":"js/parlamentar.307451cf.js.map","publicPath":"/static/sapl/frontend/js/parlamentar.307451cf.js.map","path":"../sapl/sapl/static/sapl/frontend/js/parlamentar.307451cf.js.map"}]}}

35
scripts/gerar_hash_proposicoes.py

@ -0,0 +1,35 @@
# Gerar hash de proposições para recebimento sem recibo
from sapl.materia.models import Proposicao
from sapl.utils import gerar_hash_arquivo, SEPARADOR_HASH_PROPOSICAO
from datetime import datetime
def gerar_hash(proposicao):
if proposicao.texto_original:
try:
proposicao.hash_code = gerar_hash_arquivo(
proposicao.texto_original.path, str(proposicao.pk))
except IOError:
raise Exception("Existem proposicoes com arquivos inexistentes.")
elif proposicao.texto_articulado.exists():
ta = proposicao.texto_articulado.first()
proposicao.hash_code = 'P' + ta.hash() + SEPARADOR_HASH_PROPOSICAO + str(proposicao.pk)
print(proposicao.hash_code)
proposicao.save()
def gerar_hash_proposicoes():
di = datetime.now()
print(di)
props = Proposicao.objects.filter(hash_code='', data_recebimento__isnull=True).exclude(data_envio__isnull=True)
print("Total de proposicoes: %s" % props.count())
for prop in props:
try:
print(".",end="")
gerar_hash(prop)
except Exception as e:
print('Erro para proposicao', prop)
print(e)
elapsed = datetime.now() - di
print("\n {}s".format(elapsed.seconds))

2
setup.py

@ -43,7 +43,7 @@ install_requires = [
]
setup(
name='interlegis-sapl',
version='3.1.161-RC2',
version='3.1.161-RC3',
packages=find_packages(),
include_package_data=True,
license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007',

Loading…
Cancel
Save