Browse Source

Campo tramitação para expediente e ordem do dia das pautas de sessoes plenarias

pull/3584/head
joao 3 years ago
parent
commit
9579b7d18f
  1. 58
      sapl/sessao/forms.py
  2. 7
      sapl/sessao/models.py
  3. 4
      sapl/sessao/urls.py
  4. 31
      sapl/sessao/views.py
  5. 33
      sapl/templates/sessao/expedientemateria_form.html
  6. 4
      sapl/templates/sessao/layouts.yaml

58
sapl/sessao/forms.py

@ -1,7 +1,8 @@
from datetime import datetime
import re import re
from crispy_forms.layout import Button, Fieldset, HTML, Layout from crispy_forms.layout import Button, Fieldset, HTML, Layout
from datetime import datetime
from django import forms from django import forms
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.exceptions import ObjectDoesNotExist, ValidationError
@ -12,6 +13,7 @@ from django.forms.widgets import CheckboxSelectMultiple
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import django_filters import django_filters
import sapl.utils
from sapl.base.models import Autor, TipoAutor from sapl.base.models import Autor, TipoAutor
from sapl.crispy_layout_mixin import (form_actions, to_row, from sapl.crispy_layout_mixin import (form_actions, to_row,
SaplFormHelper, SaplFormLayout) SaplFormHelper, SaplFormLayout)
@ -33,13 +35,16 @@ from .models import (Bancada, ExpedienteMateria,
ORDENACAO_RESUMO, PresencaOrdemDia, ORDENACAO_RESUMO, PresencaOrdemDia,
RegistroLeitura, ResumoOrdenacao, RetiradaPauta, RegistroLeitura, ResumoOrdenacao, RetiradaPauta,
SessaoPlenaria, SessaoPlenariaPresenca, SessaoPlenaria, SessaoPlenariaPresenca,
TipoResultadoVotacao, TipoRetiradaPauta) TipoResultadoVotacao, TipoRetiradaPauta, Tramitacao)
MES_CHOICES = RANGE_MESES MES_CHOICES = RANGE_MESES
DIA_CHOICES = RANGE_DIAS_MES DIA_CHOICES = RANGE_DIAS_MES
def tramitacao_select_validation():
return True
class SessaoPlenariaForm(FileFieldCheckMixin, ModelForm): class SessaoPlenariaForm(FileFieldCheckMixin, ModelForm):
class Meta: class Meta:
@ -109,7 +114,7 @@ class SessaoPlenariaForm(FileFieldCheckMixin, ModelForm):
if upload_pauta: if upload_pauta:
validar_arquivo(upload_pauta, "Pauta da Sessão") validar_arquivo(upload_pauta, "Pauta da Sessão")
if upload_ata: if upload_ata:
validar_arquivo(upload_ata, "Ata da Sessão") validar_arquivo(upload_ata, "Ata da Sessão")
@ -117,12 +122,12 @@ class SessaoPlenariaForm(FileFieldCheckMixin, ModelForm):
validar_arquivo(upload_anexo, "Anexo da Sessão") validar_arquivo(upload_anexo, "Anexo da Sessão")
hora_inicio = self.cleaned_data['hora_inicio'] hora_inicio = self.cleaned_data['hora_inicio']
if not re.match(TIME_PATTERN, hora_inicio): if not re.match(sapl.utils.TIME_PATTERN, hora_inicio):
raise ValidationError(f'Formato ou valores de horário de ' raise ValidationError(f'Formato ou valores de horário de '
f'abertura errados: {hora_inicio}') f'abertura errados: {hora_inicio}')
hora_fim = self.cleaned_data['hora_fim'] hora_fim = self.cleaned_data['hora_fim']
if hora_fim and not re.match(TIME_PATTERN, hora_fim): if hora_fim and not re.match(sapl.utils.TIME_PATTERN, hora_fim):
raise ValidationError(f'Formato ou valores de horário de ' raise ValidationError(f'Formato ou valores de horário de '
f'encerramento errados: {hora_fim}.') f'encerramento errados: {hora_fim}.')
@ -294,6 +299,12 @@ class BancadaForm(ModelForm):
return bancada return bancada
class DependentChoiceField(forms.ChoiceField):
def validate(self, value):
return True
class ExpedienteMateriaForm(ModelForm): class ExpedienteMateriaForm(ModelForm):
_model = ExpedienteMateria _model = ExpedienteMateria
@ -306,6 +317,10 @@ class ExpedienteMateriaForm(ModelForm):
empty_label='Selecione', empty_label='Selecione',
widget=forms.Select(attrs={'autocomplete': 'off'})) widget=forms.Select(attrs={'autocomplete': 'off'}))
tramitacao_select = DependentChoiceField(
label=_('Situação Atual'),
widget=forms.Select())
numero_materia = forms.CharField( numero_materia = forms.CharField(
label='Número Matéria', required=True, label='Número Matéria', required=True,
widget=forms.TextInput(attrs={'autocomplete': 'off'})) widget=forms.TextInput(attrs={'autocomplete': 'off'}))
@ -326,7 +341,7 @@ class ExpedienteMateriaForm(ModelForm):
class Meta: class Meta:
model = ExpedienteMateria model = ExpedienteMateria
fields = ['data_ordem', 'numero_ordem', 'tipo_materia', 'observacao', fields = ['data_ordem', 'numero_ordem', 'tipo_materia', 'observacao',
'numero_materia', 'ano_materia', 'tipo_votacao'] 'numero_materia', 'ano_materia', 'tramitacao_select', 'tipo_votacao']
def clean_numero_ordem(self): def clean_numero_ordem(self):
sessao = self.instance.sessao_plenaria sessao = self.instance.sessao_plenaria
@ -363,11 +378,28 @@ class ExpedienteMateriaForm(ModelForm):
else: else:
cleaned_data['materia'] = materia cleaned_data['materia'] = materia
try:
id_t = self.cleaned_data['tramitacao_select'] if self.cleaned_data['tramitacao_select'] != '' else -1
tramitacao = materia.tramitacao_set.get(pk=self.cleaned_data['tramitacao_select'] if self.cleaned_data['tramitacao_select'] != '' else -1)
except ObjectDoesNotExist:
if self.cleaned_data['tramitacao_select'] != '':
raise ValidationError(
_('Tramitação selecionada não existe para a Matéria: %(value)s'),
code='invalid',
params={'value': self.cleaned_data['tramitacao_select']},
)
else:
cleaned_data['tramitacao'] = False
else:
cleaned_data['tramitacao'] = tramitacao
return cleaned_data return cleaned_data
def save(self, commit=False): def save(self, commit=False):
expediente = super(ExpedienteMateriaForm, self).save(commit) expediente = super(ExpedienteMateriaForm, self).save(commit)
expediente.materia = self.cleaned_data['materia'] expediente.materia = self.cleaned_data['materia']
if self.cleaned_data['tramitacao'] is not False:
expediente.tramitacao = self.cleaned_data['tramitacao']
expediente.save() expediente.save()
return expediente return expediente
@ -996,7 +1028,7 @@ class OrdemExpedienteLeituraForm(forms.ModelForm):
'ordem', 'ordem',
'expediente', 'expediente',
'observacao', 'observacao',
'user', 'user',
'ip'] 'ip']
widgets = {'materia': forms.HiddenInput(), widgets = {'materia': forms.HiddenInput(),
'ordem': forms.HiddenInput(), 'ordem': forms.HiddenInput(),
@ -1008,14 +1040,14 @@ class OrdemExpedienteLeituraForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
instance = self.initial['instance'] instance = self.initial['instance']
if instance: if instance:
self.instance = instance.first() self.instance = instance.first()
self.fields['observacao'].initial = self.instance.observacao self.fields['observacao'].initial = self.instance.observacao
row1 = to_row( row1 = to_row(
[('observacao', 12)]) [('observacao', 12)])
actions = [HTML('<a href="{{ view.cancel_url }}"' actions = [HTML('<a href="{{ view.cancel_url }}"'
' class="btn btn-warning">Cancelar Leitura</a>')] ' class="btn btn-warning">Cancelar Leitura</a>')]
@ -1024,11 +1056,11 @@ class OrdemExpedienteLeituraForm(forms.ModelForm):
self.helper.form_method = 'POST' self.helper.form_method = 'POST'
self.helper.layout = Layout( self.helper.layout = Layout(
Fieldset(_('Leitura de Matéria'), Fieldset(_('Leitura de Matéria'),
HTML(''' HTML('''
<b>Matéria:</b> {{materia}}<br> <b>Matéria:</b> {{materia}}<br>
<b>Ementa:</b> {{materia.ementa}} <br> <b>Ementa:</b> {{materia.ementa}} <br>
'''), '''),
row1, row1,
form_actions(more=actions), form_actions(more=actions),
) )
) )

7
sapl/sessao/models.py

@ -10,6 +10,7 @@ import reversion
from sapl.base.models import Autor from sapl.base.models import Autor
from sapl.materia.models import MateriaLegislativa from sapl.materia.models import MateriaLegislativa
from sapl.materia.models import Tramitacao
from sapl.parlamentares.models import (CargoMesa, Legislatura, Parlamentar, from sapl.parlamentares.models import (CargoMesa, Legislatura, Parlamentar,
Partido, SessaoLegislativa) Partido, SessaoLegislativa)
from sapl.utils import (YES_NO_CHOICES, SaplGenericRelation, from sapl.utils import (YES_NO_CHOICES, SaplGenericRelation,
@ -360,6 +361,12 @@ class AbstractOrdemDia(models.Model):
materia = models.ForeignKey(MateriaLegislativa, materia = models.ForeignKey(MateriaLegislativa,
on_delete=models.PROTECT, on_delete=models.PROTECT,
verbose_name=_('Matéria')) verbose_name=_('Matéria'))
tramitacao = models.ForeignKey(Tramitacao,
on_delete=models.PROTECT,
verbose_name=_('Situação Atual'),
blank=True,
default='',
null=True)
data_ordem = models.DateField(verbose_name=_('Data da Sessão')) data_ordem = models.DateField(verbose_name=_('Data da Sessão'))
observacao = models.TextField( observacao = models.TextField(
blank=True, verbose_name=_('Observação')) blank=True, verbose_name=_('Observação'))

4
sapl/sessao/urls.py

@ -36,7 +36,8 @@ from sapl.sessao.views import (AdicionarVariasMateriasExpediente,
OrdemDiaLeituraView, OrdemDiaLeituraView,
retirar_leitura, retirar_leitura,
TransferenciaMateriasExpediente, TransferenciaMateriasOrdemDia, TransferenciaMateriasExpediente, TransferenciaMateriasOrdemDia,
filtra_materias_copia_sessao_ajax, verifica_materia_sessao_plenaria_ajax) filtra_materias_copia_sessao_ajax, verifica_materia_sessao_plenaria_ajax,
recuperar_tramitacao)
from .apps import AppConfig from .apps import AppConfig
@ -68,6 +69,7 @@ urlpatterns = [
name='remove_parlamentar_composicao'), name='remove_parlamentar_composicao'),
url(r'^sessao/recuperar-materia/', recuperar_materia), url(r'^sessao/recuperar-materia/', recuperar_materia),
url(r'^sessao/recuperar-tramitacao/', recuperar_tramitacao),
url(r'^sessao/recuperar-numero-sessao/', url(r'^sessao/recuperar-numero-sessao/',
recuperar_numero_sessao_view, recuperar_numero_sessao_view,
name='recuperar_numero_sessao_view' name='recuperar_numero_sessao_view'

31
sapl/sessao/views.py

@ -1,4 +1,4 @@
import json
from collections import OrderedDict from collections import OrderedDict
from datetime import datetime from datetime import datetime
from re import sub from re import sub
@ -754,7 +754,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
class BaseMixin(MasterDetailCrud.BaseMixin): class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['numero_ordem', 'materia', list_field_names = ['numero_ordem', 'materia',
('materia__ementa', '', 'observacao'), ('materia__ementa', '', 'tramitacao', 'observacao'),
'resultado'] 'resultado']
class CreateView(MasterDetailCrud.CreateView): class CreateView(MasterDetailCrud.CreateView):
@ -790,6 +790,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
context["tipo_materia_salvo"] = self.object.materia.tipo.id context["tipo_materia_salvo"] = self.object.materia.tipo.id
context["numero_materia_salvo"] = self.object.materia.numero context["numero_materia_salvo"] = self.object.materia.numero
context["ano_materia_salvo"] = self.object.materia.ano context["ano_materia_salvo"] = self.object.materia.ano
context["tramitacao_salvo"] = None if not self.object.tramitacao else self.object.tramitacao.id
return context return context
@ -800,6 +801,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
initial['numero_materia'] = self.object.materia.numero initial['numero_materia'] = self.object.materia.numero
initial['ano_materia'] = self.object.materia.ano initial['ano_materia'] = self.object.materia.ano
initial['numero_ordem'] = self.object.numero_ordem initial['numero_ordem'] = self.object.numero_ordem
initial['tramitacao'] = None if not self.object.tramitacao else self.object.tramitacao.id
return initial return initial
@ -839,6 +841,23 @@ def recuperar_materia(request):
return response return response
def recuperar_tramitacao(request):
tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo_materia'])
numero = request.GET['numero_materia']
ano = request.GET['ano_materia']
try:
materia = MateriaLegislativa.objects.get(tipo=tipo,
ano=ano,
numero=numero)
tramitacao = {}
for obj in materia.tramitacao_set.all():
tramitacao[obj.id] = obj.status.descricao
response = JsonResponse(tramitacao)
except ObjectDoesNotExist:
response = JsonResponse({'id': 0})
return response
class ExpedienteMateriaCrud(MasterDetailCrud): class ExpedienteMateriaCrud(MasterDetailCrud):
model = ExpedienteMateria model = ExpedienteMateria
@ -904,6 +923,7 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
context["tipo_materia_salvo"] = self.object.materia.tipo.id context["tipo_materia_salvo"] = self.object.materia.tipo.id
context["numero_materia_salvo"] = self.object.materia.numero context["numero_materia_salvo"] = self.object.materia.numero
context["ano_materia_salvo"] = self.object.materia.ano context["ano_materia_salvo"] = self.object.materia.ano
context["tramitacao_salvo"] = self.object.tramitacao.id if self.object.tramitacao is not None else ''
return context return context
@ -914,6 +934,7 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
initial['numero_materia'] = self.object.materia.numero initial['numero_materia'] = self.object.materia.numero
initial['ano_materia'] = self.object.materia.ano initial['ano_materia'] = self.object.materia.ano
initial['numero_ordem'] = self.object.numero_ordem initial['numero_ordem'] = self.object.numero_ordem
initial['tramitacao'] = self.object.tramitacao.id if self.object.tramitacao is not None else ''
return initial return initial
@ -3757,8 +3778,8 @@ class PautaSessaoDetailView(DetailView):
data_sessao = sessao_plenaria.data_inicio.strftime("%Y-%m-%d ") data_sessao = sessao_plenaria.data_inicio.strftime("%Y-%m-%d ")
data_hora_sessao = datetime.strptime(data_sessao + sessao_plenaria.hora_inicio, "%Y-%m-%d %H:%M") data_hora_sessao = datetime.strptime(data_sessao + sessao_plenaria.hora_inicio, "%Y-%m-%d %H:%M")
data_hora_sessao_utc = pytz.timezone(TIME_ZONE).localize(data_hora_sessao).astimezone(pytz.utc) data_hora_sessao_utc = pytz.timezone(TIME_ZONE).localize(data_hora_sessao).astimezone(pytz.utc)
ultima_tramitacao = m.materia.tramitacao_set.filter(timestamp__lt = data_hora_sessao_utc).order_by( ultima_tramitacao = m.materia.tramitacao_set.filter(timestamp__lt=data_hora_sessao_utc).order_by(
'-data_tramitacao', '-id').first() '-data_tramitacao', '-id').first() if m.tramitacao is None else m.tramitacao
numeracao = m.materia.numeracao_set.first() numeracao = m.materia.numeracao_set.first()
materias_expediente.append({ materias_expediente.append({
@ -3813,7 +3834,7 @@ class PautaSessaoDetailView(DetailView):
data_hora_sessao = datetime.strptime(data_sessao + sessao_plenaria.hora_inicio, "%Y-%m-%d %H:%M") data_hora_sessao = datetime.strptime(data_sessao + sessao_plenaria.hora_inicio, "%Y-%m-%d %H:%M")
data_hora_sessao_utc = pytz.timezone(TIME_ZONE).localize(data_hora_sessao).astimezone(pytz.utc) data_hora_sessao_utc = pytz.timezone(TIME_ZONE).localize(data_hora_sessao).astimezone(pytz.utc)
ultima_tramitacao = o.materia.tramitacao_set.filter(timestamp__lt=data_hora_sessao_utc).order_by( ultima_tramitacao = o.materia.tramitacao_set.filter(timestamp__lt=data_hora_sessao_utc).order_by(
'-data_tramitacao', '-id').first() '-data_tramitacao', '-id').first() if o.tramitacao is None else o.tramitacao
numeracao = o.materia.numeracao_set.first() numeracao = o.materia.numeracao_set.first()
materias_ordem.append({ materias_ordem.append({

33
sapl/templates/sessao/expedientemateria_form.html

@ -54,11 +54,40 @@
} }
} }
function recuperar_tramitacao() {
let tipo_materia = $("#id_tipo_materia").val()
let numero_materia = $("#id_numero_materia").val()
let ano_materia = $("#id_ano_materia").val()
let tramitacao_salvo = "{{ tramitacao_salvo }}"
if (tipo_materia && numero_materia && ano_materia) {
$.get("/sessao/recuperar-tramitacao",
{ tipo_materia: tipo_materia, numero_materia: numero_materia, ano_materia: ano_materia },
function(data, status) {
if (status == 'success') {
$('#id_tramitacao_select').find('option').remove()
$('#id_tramitacao_select').append('<option value="-1">Selecione uma opção..</option>');
for (const property in data) {
console.log(tramitacao_salvo + "===" + property)
$('#id_tramitacao_select').append('<option value="' + property + '">' + data[property] +'</option>');
if (property == tramitacao_salvo) {
$("#id_tramitacao_select option[value='"+ property +"']").attr("selected", "selected");
}
}
}
});
}
}
var fields = ["#id_tipo_materia", "#id_numero_materia", "#id_ano_materia"]; var fields = ["#id_tipo_materia", "#id_numero_materia", "#id_ano_materia"];
for (i = 0; i < fields.length; i++){ for (i = 0; i < fields.length; i++){
$(fields[i]).change(recuperar_materia) $(fields[i]).change(function() {
recuperar_materia();
recuperar_tramitacao();
});
} }
recuperar_materia() recuperar_materia();
recuperar_tramitacao();
var modal_estilos = 'display: block; width: 85%; max-width: 600px; background: #fff; padding: 15px; border-radius: 5px;' 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);' +'-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);'

4
sapl/templates/sessao/layouts.yaml

@ -60,6 +60,7 @@ ExpedienteMateria:
- tipo_materia numero_materia ano_materia - tipo_materia numero_materia ano_materia
- tipo_votacao - tipo_votacao
- apenas_leitura - apenas_leitura
- tramitacao_select
- observacao - observacao
OrdemDia: OrdemDia:
@ -68,6 +69,7 @@ OrdemDia:
- tipo_materia numero_materia ano_materia - tipo_materia numero_materia ano_materia
- tipo_votacao - tipo_votacao
- apenas_leitura - apenas_leitura
- tramitacao_select
- observacao - observacao
ExpedienteMateriaDetail: ExpedienteMateriaDetail:
@ -75,6 +77,7 @@ ExpedienteMateriaDetail:
- materia - materia
- ementa - ementa
- tipo_votacao - tipo_votacao
- tramitacao
- observacao - observacao
OrdemDiaDetail: OrdemDiaDetail:
@ -82,6 +85,7 @@ OrdemDiaDetail:
- materia - materia
- ementa - ementa
- tipo_votacao - tipo_votacao
- tramitacao
- observacao - observacao
Bancada: Bancada:

Loading…
Cancel
Save