Browse Source

Merge branch '3.1.x' into impl_params_expand_include_exclude

pull/3809/head
Edward 2 weeks ago
committed by GitHub
parent
commit
7799e1ab97
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 12
      docker/config/nginx/sapl.conf
  2. 28
      sapl/audiencia/migrations/0020_auto_20251201_1450.py
  3. 4
      sapl/audiencia/models.py
  4. 21
      sapl/logging/filters.py
  5. 0
      sapl/middleware/__init__.py
  6. 0
      sapl/middleware/check_password.py
  7. 0
      sapl/middleware/endpoint_restriction.py
  8. 24
      sapl/middleware/request_id.py
  9. 10
      sapl/painel/views.py
  10. 23
      sapl/parlamentares/migrations/0045_auto_20251201_1531.py
  11. 4
      sapl/parlamentares/models.py
  12. 16
      sapl/relatorios/forms.py
  13. 19
      sapl/sessao/forms.py
  14. 4
      sapl/sessao/views.py
  15. 18
      sapl/settings.py
  16. 2
      sapl/templates/norma/layouts.yaml
  17. 11
      sapl/templates/painel/voto_individual.html
  18. 22
      sapl/templates/sessao/adicionar_varias_materias_expediente.html
  19. 2
      sapl/templates/sessao/blocos_ata/materias_expediente.html
  20. 2
      sapl/templates/sessao/blocos_ata/materias_ordem_dia.html

12
docker/config/nginx/sapl.conf

@ -4,6 +4,13 @@ upstream sapl_server {
} }
# Se o cliente já manda X-Request-ID, reaproveita; senão, usa $request_id (nginx)
map $http_x_request_id $req_id {
default $http_x_request_id;
"" $request_id;
}
server { server {
listen 80; listen 80;
@ -30,7 +37,9 @@ server {
return 204; return 204;
} }
proxy_set_header X-Request-ID $req_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
proxy_redirect off; proxy_redirect off;
proxy_pass http://sapl_server; proxy_pass http://sapl_server;
@ -45,10 +54,11 @@ server {
} }
location / { location / {
proxy_set_header X-Request-ID $req_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
proxy_redirect off; proxy_redirect off;
proxy_pass http://sapl_server; proxy_pass http://sapl_server;
} }

28
sapl/audiencia/migrations/0020_auto_20251201_1450.py

@ -0,0 +1,28 @@
# Generated by Django 2.2.28 on 2025-12-01 17:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('audiencia', '0019_auto_20240711_1400'),
]
operations = [
migrations.AlterField(
model_name='audienciapublica',
name='ano',
field=models.PositiveSmallIntegerField(choices=[(2026, 2026), (2025, 2025), (2024, 2024), (2023, 2023), (2022, 2022), (2021, 2021), (2020, 2020), (2019, 2019), (2018, 2018), (2017, 2017), (2016, 2016), (2015, 2015), (2014, 2014), (2013, 2013), (2012, 2012), (2011, 2011), (2010, 2010), (2009, 2009), (2008, 2008), (2007, 2007), (2006, 2006), (2005, 2005), (2004, 2004), (2003, 2003), (2002, 2002), (2001, 2001), (2000, 2000), (1999, 1999), (1998, 1998), (1997, 1997), (1996, 1996), (1995, 1995), (1994, 1994), (1993, 1993), (1992, 1992), (1991, 1991), (1990, 1990), (1989, 1989), (1988, 1988), (1987, 1987), (1986, 1986), (1985, 1985), (1984, 1984), (1983, 1983), (1982, 1982), (1981, 1981), (1980, 1980), (1979, 1979), (1978, 1978), (1977, 1977), (1976, 1976), (1975, 1975), (1974, 1974), (1973, 1973), (1972, 1972), (1971, 1971), (1970, 1970), (1969, 1969), (1968, 1968), (1967, 1967), (1966, 1966), (1965, 1965), (1964, 1964), (1963, 1963), (1962, 1962), (1961, 1961), (1960, 1960), (1959, 1959), (1958, 1958), (1957, 1957), (1956, 1956), (1955, 1955), (1954, 1954), (1953, 1953), (1952, 1952), (1951, 1951), (1950, 1950), (1949, 1949), (1948, 1948), (1947, 1947), (1946, 1946), (1945, 1945), (1944, 1944), (1943, 1943), (1942, 1942), (1941, 1941), (1940, 1940), (1939, 1939), (1938, 1938), (1937, 1937), (1936, 1936), (1935, 1935), (1934, 1934), (1933, 1933), (1932, 1932), (1931, 1931), (1930, 1930), (1929, 1929), (1928, 1928), (1927, 1927), (1926, 1926), (1925, 1925), (1924, 1924), (1923, 1923), (1922, 1922), (1921, 1921), (1920, 1920), (1919, 1919), (1918, 1918), (1917, 1917), (1916, 1916), (1915, 1915), (1914, 1914), (1913, 1913), (1912, 1912), (1911, 1911), (1910, 1910), (1909, 1909), (1908, 1908), (1907, 1907), (1906, 1906), (1905, 1905), (1904, 1904), (1903, 1903), (1902, 1902), (1901, 1901), (1900, 1900), (1899, 1899), (1898, 1898), (1897, 1897), (1896, 1896), (1895, 1895), (1894, 1894), (1893, 1893), (1892, 1892), (1891, 1891), (1890, 1890)], verbose_name='Ano'),
),
migrations.AlterField(
model_name='audienciapublica',
name='nome',
field=models.CharField(max_length=250, verbose_name='Nome da Audiência Pública'),
),
migrations.AlterField(
model_name='audienciapublica',
name='tema',
field=models.CharField(max_length=250, verbose_name='Tema da Audiência Pública'),
),
]

4
sapl/audiencia/models.py

@ -65,9 +65,9 @@ class AudienciaPublica(models.Model):
ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'), ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'),
choices=RANGE_ANOS) choices=RANGE_ANOS)
nome = models.CharField( nome = models.CharField(
max_length=100, verbose_name=_('Nome da Audiência Pública')) max_length=250, verbose_name=_('Nome da Audiência Pública'))
tema = models.CharField( tema = models.CharField(
max_length=100, verbose_name=_('Tema da Audiência Pública')) max_length=250, verbose_name=_('Tema da Audiência Pública'))
data = models.DateField(verbose_name=_('Data')) data = models.DateField(verbose_name=_('Data'))
hora_inicio = models.CharField( hora_inicio = models.CharField(
max_length=5, verbose_name=_('Horário Início(hh:mm)')) max_length=5, verbose_name=_('Horário Início(hh:mm)'))

21
sapl/logging/filters.py

@ -0,0 +1,21 @@
# sapl/logging/filters.py
import logging
import contextvars
_request_id = contextvars.ContextVar("request_id", default="-")
def set_request_id(value: str):
_request_id.set(value)
def get_request_id() -> str:
return _request_id.get()
class RequestIdFilter(logging.Filter):
def filter(self, record: logging.LogRecord) -> bool:
# garante que SEMPRE existe
if not hasattr(record, "request_id"):
record.request_id = get_request_id()
return True

0
sapl/middleware/__init__.py

0
sapl/middleware.py → sapl/middleware/check_password.py

0
sapl/endpoint_restriction_middleware.py → sapl/middleware/endpoint_restriction.py

24
sapl/middleware/request_id.py

@ -0,0 +1,24 @@
import uuid
from sapl.logging.filters import set_request_id
HEADER_NAME = "HTTP_X_REQUEST_ID"
RESPONSE_HEADER = "X-Request-ID"
def _new_id():
return uuid.uuid4().hex
class RequestIdMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# recebe `request_id` do nginx ou do cliente senão cria um
request_id = request.META.get(HEADER_NAME) or _new_id()
request_id = str(request_id)[:64]
request.request_id = request_id
set_request_id(request_id)
response = self.get_response(request)
response[RESPONSE_HEADER] = request_id
return response

10
sapl/painel/views.py

@ -93,7 +93,7 @@ def votacao_aberta(request):
return votacoes_abertas.first(), None return votacoes_abertas.first(), None
def votacao(context,context_vars): def votacao(context, context_vars):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
parlamentar = context_vars['votante'].parlamentar parlamentar = context_vars['votante'].parlamentar
parlamentar_presente = False parlamentar_presente = False
@ -204,7 +204,7 @@ def votante_view(request):
username = request.user.username if request.user.is_authenticated else 'AnonymousUser' username = request.user.username if request.user.is_authenticated else 'AnonymousUser'
# Pega o votante relacionado ao usuário # Pega o votante relacionado ao usuário
template_name = 'painel/voto_nominal.html' template_name = 'painel/voto_individual.html'
context = {} context = {}
context_vars = {} context_vars = {}
@ -237,13 +237,15 @@ def votante_view(request):
if request.method == 'POST': if request.method == 'POST':
if context_vars['ordem_dia']: if context_vars['ordem_dia']:
try: try:
logger.info("user=" + username + ". Tentando obter objeto VotoParlamentar para parlamentar={} e ordem={}." logger.info("user=" + username + ". Tentando obter objeto VotoParlamentar para parlamentar={} e "
"ordem={}. "
.format(context_vars['parlamentar'], context_vars['ordem_dia'])) .format(context_vars['parlamentar'], context_vars['ordem_dia']))
voto = VotoParlamentar.objects.get( voto = VotoParlamentar.objects.get(
parlamentar=context_vars['parlamentar'], parlamentar=context_vars['parlamentar'],
ordem=context_vars['ordem_dia']) ordem=context_vars['ordem_dia'])
except ObjectDoesNotExist: except ObjectDoesNotExist:
logger.error("user=" + username + ". Erro ao obter VotoParlamentar para parlamentar={} e ordem={}. Criando objeto." logger.error("user=" + username + ". Erro ao obter VotoParlamentar para parlamentar={} e ordem={}. "
"Criando objeto. "
.format(context_vars['parlamentar'], context_vars['ordem_dia'])) .format(context_vars['parlamentar'], context_vars['ordem_dia']))
voto = VotoParlamentar.objects.create( voto = VotoParlamentar.objects.create(
parlamentar=context_vars['parlamentar'], parlamentar=context_vars['parlamentar'],

23
sapl/parlamentares/migrations/0045_auto_20251201_1531.py

@ -0,0 +1,23 @@
# Generated by Django 2.2.28 on 2025-12-01 18:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('parlamentares', '0044_adiciona_cargos_mesa'),
]
operations = [
migrations.AlterField(
model_name='parlamentar',
name='nome_completo',
field=models.CharField(max_length=80, verbose_name='Nome Completo'),
),
migrations.AlterField(
model_name='parlamentar',
name='nome_parlamentar',
field=models.CharField(max_length=80, verbose_name='Nome Parlamentar'),
),
]

4
sapl/parlamentares/models.py

@ -206,9 +206,9 @@ class Parlamentar(models.Model):
on_delete=models.PROTECT, on_delete=models.PROTECT,
verbose_name=_('Situação Militar')) verbose_name=_('Situação Militar'))
nome_completo = models.CharField( nome_completo = models.CharField(
max_length=50, verbose_name=_('Nome Completo')) max_length=80, verbose_name=_('Nome Completo'))
nome_parlamentar = models.CharField( nome_parlamentar = models.CharField(
max_length=50, max_length=80,
verbose_name=_('Nome Parlamentar')) verbose_name=_('Nome Parlamentar'))
sexo = models.CharField( sexo = models.CharField(
max_length=1, verbose_name=_('Sexo'), choices=SEXO_CHOICE) max_length=1, verbose_name=_('Sexo'), choices=SEXO_CHOICE)

16
sapl/relatorios/forms.py

@ -70,16 +70,16 @@ class RelatorioDocumentosAcessoriosFilterSet(django_filters.FilterSet):
) )
def ordem_or_expediente(queryset, name, value): class RelatorioVotacoesNominaisFilterSet(django_filters.FilterSet):
if value is None:
return queryset
value = getattr(value, "pk", value)
ordem_q = f"ordem__materia__{name}"
expediente_q = f"expediente__materia__{name}"
return queryset.filter(Q(**{ordem_q: value}) | Q(**{expediente_q: value}))
def ordem_or_expediente(self, queryset, name, value):
if value is None:
return queryset
value = getattr(value, "pk", value)
ordem_q = f"ordem__materia__{name}"
expediente_q = f"expediente__materia__{name}"
return queryset.filter(Q(**{ordem_q: value}) | Q(**{expediente_q: value}))
class RelatorioVotacoesNominaisFilterSet(django_filters.FilterSet):
tipo_id = django_filters.ModelChoiceFilter( tipo_id = django_filters.ModelChoiceFilter(
queryset=TipoMateriaLegislativa.objects.all(), queryset=TipoMateriaLegislativa.objects.all(),
method='ordem_or_expediente', method='ordem_or_expediente',

19
sapl/sessao/forms.py

@ -22,7 +22,8 @@ from sapl.materia.models import (MateriaLegislativa, StatusTramitacao,
from sapl.parlamentares.models import Mandato, Parlamentar from sapl.parlamentares.models import Mandato, Parlamentar
from sapl.protocoloadm.models import TipoDocumentoAdministrativo,\ from sapl.protocoloadm.models import TipoDocumentoAdministrativo,\
DocumentoAdministrativo DocumentoAdministrativo
from sapl.sessao.models import Correspondencia from sapl.sessao.models import Correspondencia, AbstractOrdemDia
from sapl.utils import (autor_label, autor_modal, from sapl.utils import (autor_label, autor_modal,
choice_anos_com_sessaoplenaria, choice_anos_com_sessaoplenaria,
FileFieldCheckMixin, FileFieldCheckMixin,
@ -563,6 +564,22 @@ class SessaoPlenariaFilterSet(django_filters.FilterSet):
) )
class AdicionarVariasMateriasForm(forms.Form):
check_all = forms.BooleanField(
label='Marcar/Desmarcar Todos',
required=False,
widget=forms.CheckboxInput(
attrs={'onchange':'checkAll(this)'}),
)
tipo_votacao = forms.ChoiceField(required=False,
choices= AbstractOrdemDia.TIPO_VOTACAO_CHOICES,
initial=False,
widget=forms.RadioSelect(
attrs={'onchange':'marcaTipoVotacao()'}),
)
class AdicionarVariasMateriasFilterSet(MateriaLegislativaFilterSet): class AdicionarVariasMateriasFilterSet(MateriaLegislativaFilterSet):
o = MateriaPesquisaOrderingFilter() o = MateriaPesquisaOrderingFilter()

4
sapl/sessao/views.py

@ -51,7 +51,7 @@ from sapl.settings import TIME_ZONE, RATE_LIMITER_RATE
from sapl.utils import show_results_filter_set, remover_acentos, get_client_ip, \ from sapl.utils import show_results_filter_set, remover_acentos, get_client_ip, \
MultiFormatOutputMixin, PautaMultiFormatOutputMixin, ratelimit_ip MultiFormatOutputMixin, PautaMultiFormatOutputMixin, ratelimit_ip
from .forms import (AdicionarVariasMateriasFilterSet, BancadaForm, from .forms import (AdicionarVariasMateriasFilterSet, AdicionarVariasMateriasForm, BancadaForm,
ExpedienteForm, JustificativaAusenciaForm, OcorrenciaSessaoForm, ListMateriaForm, ExpedienteForm, JustificativaAusenciaForm, OcorrenciaSessaoForm, ListMateriaForm,
MesaForm, OradorExpedienteForm, OradorForm, PautaSessaoFilterSet, MesaForm, OradorExpedienteForm, OradorForm, PautaSessaoFilterSet,
PresencaForm, ResumoOrdenacaoForm, SessaoPlenariaFilterSet, PresencaForm, ResumoOrdenacaoForm, SessaoPlenariaFilterSet,
@ -4190,6 +4190,8 @@ class AdicionarVariasMateriasExpediente(PermissionRequiredForAppCrudMixin,
qr = self.request.GET.copy() qr = self.request.GET.copy()
form = AdicionarVariasMateriasForm
context['form'] = form
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else '' context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
context['pk_sessao'] = self.kwargs['pk'] context['pk_sessao'] = self.kwargs['pk']

18
sapl/settings.py

@ -138,11 +138,12 @@ HAYSTACK_CONNECTIONS = {
} }
MIDDLEWARE = [ MIDDLEWARE = [
'sapl.middleware.request_id.RequestIdMiddleware',
'django_prometheus.middleware.PrometheusBeforeMiddleware', 'django_prometheus.middleware.PrometheusBeforeMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'sapl.endpoint_restriction_middleware.EndpointRestrictionMiddleware', 'sapl.middleware.endpoint_restriction.EndpointRestrictionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
@ -150,7 +151,7 @@ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware',
'waffle.middleware.WaffleMiddleware', 'waffle.middleware.WaffleMiddleware',
'sapl.middleware.CheckWeakPasswordMiddleware', 'sapl.middleware.check_password.CheckWeakPasswordMiddleware',
'django_prometheus.middleware.PrometheusAfterMiddleware', 'django_prometheus.middleware.PrometheusAfterMiddleware',
] ]
if DEBUG: if DEBUG:
@ -421,32 +422,37 @@ LOGGING = {
'require_debug_true': { 'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue', '()': 'django.utils.log.RequireDebugTrue',
}, },
'request_id': {
"()": 'sapl.logging.filters.RequestIdFilter',
},
}, },
'formatters': { 'formatters': {
'verbose': { 'verbose': {
'format': '%(levelname)s %(asctime)s ' + host + ' %(pathname)s %(name)s:%(funcName)s:%(lineno)d %(message)s' 'format': '%(levelname)s %(asctime)s [%(request_id)s] ' + host + '%(pathname)s %(name)s:%(funcName)s:%('
'lineno)d %(message)s '
}, },
'simple': { 'simple': {
'format': '%(levelname)s %(asctime)s - %(message)s' 'format': '%(levelname)s %(asctime)s [%(request_id)s] - %(message)s'
}, },
}, },
'handlers': { 'handlers': {
'console': { 'console': {
'level': 'INFO', 'level': 'INFO',
'class': 'logging.StreamHandler', 'class': 'logging.StreamHandler',
'filters': ['require_debug_true'], 'filters': ['request_id', 'require_debug_true'],
'formatter': 'simple', 'formatter': 'simple',
}, },
'console_verbose': { 'console_verbose': {
'level': 'DEBUG', 'level': 'DEBUG',
'class': 'logging.StreamHandler', 'class': 'logging.StreamHandler',
'filters': ['require_debug_true'], 'filters': ['request_id', 'require_debug_true'],
'formatter': 'verbose', 'formatter': 'verbose',
}, },
'applogfile': { 'applogfile': {
'level': 'INFO', 'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler', 'class': 'logging.handlers.RotatingFileHandler',
'filename': 'sapl.log', 'filename': 'sapl.log',
'filters': ['request_id'],
'maxBytes': 1024 * 1024 * 15, # 15MB 'maxBytes': 1024 * 1024 * 15, # 15MB
'backupCount': 10, 'backupCount': 10,
'formatter': 'verbose', 'formatter': 'verbose',

2
sapl/templates/norma/layouts.yaml

@ -32,7 +32,7 @@ AnexoNormaJuridica:
NormaJuridicaCreate: NormaJuridicaCreate:
{% trans 'Identificação Básica' %}: {% trans 'Identificação Básica' %}:
- orgao tipo:5 numero:2 ano:2 - orgao tipo:5 ano:2 numero:2
- data esfera_federacao complemento - data esfera_federacao complemento
- tipo_materia numero_materia ano_materia - tipo_materia numero_materia ano_materia
- data_publicacao veiculo_publicacao data_vigencia pagina_inicio_publicacao pagina_fim_publicacao - data_publicacao veiculo_publicacao data_vigencia pagina_inicio_publicacao pagina_fim_publicacao

11
sapl/templates/painel/voto_nominal.html → sapl/templates/painel/voto_individual.html

@ -132,9 +132,6 @@
{% render_bundle 'painel' 'js' %} {% render_bundle 'painel' 'js' %}
<script type="text/javascript"> <script type="text/javascript">
var d = new Date();
var n = d.toLocaleDateString();
document.getElementById("date").innerHTML = n;
$(window).on('beforeunload', function () { $(window).on('beforeunload', function () {
$("input[type=submit], input[type=button]").prop("disabled", "disabled"); $("input[type=submit], input[type=button]").prop("disabled", "disabled");
@ -177,12 +174,14 @@
m = checkTime(m); m = checkTime(m);
s = checkTime(s); s = checkTime(s);
$("#relogio").text(h+":"+m+":"+s) $("#relogio").text(h+":"+m+":"+s)
var t = setTimeout(function(){ var t = setInterval(() => startTime(), 500);
startTime()
}, 500);
} }
$(document).ready(function(){ $(document).ready(function(){
var d = new Date();
var n = d.toLocaleDateString();
$("#date").text(n);
startTime(); startTime();
setTimeout(function() { setTimeout(function() {

22
sapl/templates/sessao/adicionar_varias_materias_expediente.html

@ -38,6 +38,16 @@
{% elif paginator.count == 1 %} {% elif paginator.count == 1 %}
<h3>{% trans 'Pesquisa concluída com sucesso! Foi encontrada 1 matéria.'%}</h3> <h3>{% trans 'Pesquisa concluída com sucesso! Foi encontrada 1 matéria.'%}</h3>
{% endif %} {% endif %}
<tr>
<td>
{{ form.check_all }} {{ form.check_all.label }}
</td>
<td>
{% for tipo in form.tipo_votacao %}
{{ tipo }}<br />
{% endfor %}
</td>
</tr>
{% for m in page_obj %} {% for m in page_obj %}
<tr> <tr>
<td> <td>
@ -126,5 +136,17 @@
$(window).on('beforeunload', function() { $(window).on('beforeunload', function() {
$("input[type=submit], input[type=button]").prop("disabled", "disabled") $("input[type=submit], input[type=button]").prop("disabled", "disabled")
}); });
function checkAll(elem) {
$('input[name="materia_id"]:checkbox').prop('checked', elem.checked);
}
function marcaTipoVotacao() {
$('input[name="materia_id"]:checked').each(function() {
var tipoVotacao = $('input[name="tipo_votacao"]:checked').val();
var idMateria = "#tipo_votacao_" + $(this).val() + "_" + tipoVotacao;
$(idMateria).prop('checked', true);
});
}
</script> </script>
{% endblock extra_js %} {% endblock extra_js %}

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

@ -24,7 +24,7 @@
Abstenções: {{ m.voto_abstencoes }}, Abstenções: {{ m.voto_abstencoes }},
{% endif %} {% endif %}
{% endif %} {% endif %}
Resultado:</b> {{ m.resultado }} <strong>Resultado:</b> {{ m.resultado }}</strong>
{% if m.resultado_observacao %} - Obs.: {{ m.resultado_observacao }} {% endif %} {% if m.resultado_observacao %} - Obs.: {{ m.resultado_observacao }} {% endif %}
{% if m.voto_nominal %} {% if m.voto_nominal %}
<b>Votos Nominais :</b> <b>Votos Nominais :</b>

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

@ -25,7 +25,7 @@
Abstenções: {{ m.voto_abstencoes }}, Abstenções: {{ m.voto_abstencoes }},
{% endif %} {% endif %}
{% endif %} {% endif %}
Resultado:</b> {{ m.resultado }} <strong>Resultado:</b> {{ m.resultado }}</strong>
{% if m.resultado_observacao %} - Obs.: {{ m.resultado_observacao }} {% endif %} {% if m.resultado_observacao %} - Obs.: {{ m.resultado_observacao }} {% endif %}
{% if m.voto_nominal %} {% if m.voto_nominal %}
<b>Votos Nominais :</b> <b>Votos Nominais :</b>

Loading…
Cancel
Save