Skip to content
28 changes: 28 additions & 0 deletions sapl/api/views_materia.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@

from copy import deepcopy
from django.apps.registry import apps
from django.db import transaction
from django.db.models import Q
from rest_framework.decorators import action
from rest_framework.status import HTTP_201_CREATED
from rest_framework.response import Response

from drfautoapi.drfautoapi import ApiViewSetConstrutor, \
Expand Down Expand Up @@ -90,6 +93,31 @@ class _MateriaLegislativaViewSet:
class Meta:
ordering = ['-ano', 'tipo', 'numero']

@transaction.atomic
def create(self, request, *args, **kwargs):
data = deepcopy(request.data)
tipo = data.get('tipo', None)
numero = data.get('numero', None)
ano = data.get('ano', None)

if tipo:
numero, ano = MateriaLegislativa.get_proximo_numero(
tipo=tipo,
ano=ano,
numero_preferido=numero
)
data['numero'] = numero
data['ano'] = ano

serializer = self.get_serializer(data=data)

serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=HTTP_201_CREATED, headers=headers)



@action(detail=True, methods=['GET'])
def ultima_tramitacao(self, request, *args, **kwargs):

Expand Down
45 changes: 5 additions & 40 deletions sapl/materia/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2458,47 +2458,12 @@ def save(self, commit=False):
if self.instance.tipo.content_type.model_class(
) == TipoMateriaLegislativa:

numeracao = None
try:
self.logger.debug(
"Tentando obter modelo de sequência de numeração.")
numeracao = BaseAppConfig.objects.last(
).sequencia_numeracao_protocolo
except AttributeError as e:
self.logger.error("Erro ao obter modelo. " + str(e))
pass

tipo = self.instance.tipo.tipo_conteudo_related
if tipo.sequencia_numeracao:
numeracao = tipo.sequencia_numeracao
ano = timezone.now().year
if numeracao == 'A':
numero = MateriaLegislativa.objects.filter(
ano=ano, tipo=tipo).aggregate(Max('numero'))
elif numeracao == 'L':
legislatura = Legislatura.objects.filter(
data_inicio__year__lte=ano,
data_fim__year__gte=ano).first()
data_inicio = legislatura.data_inicio
data_fim = legislatura.data_fim
numero = MateriaLegislativa.objects.filter(
data_apresentacao__gte=data_inicio,
data_apresentacao__lte=data_fim,
tipo=tipo).aggregate(
Max('numero'))
elif numeracao == 'U':
numero = MateriaLegislativa.objects.filter(
tipo=tipo).aggregate(Max('numero'))
if numeracao is None:
numero['numero__max'] = 0

if cd['numero_materia_futuro'] and not MateriaLegislativa.objects.filter(tipo=tipo,
ano=ano,
numero=cd['numero_materia_futuro']):
max_numero = cd['numero_materia_futuro']
else:
max_numero = numero['numero__max'] + \
1 if numero['numero__max'] else 1
max_numero, ano = MateriaLegislativa.get_proximo_numero(
tipo=tipo,
ano=None,
numero_preferido=cd.get('numero_materia_futuro', None)
)

# dados básicos
materia = MateriaLegislativa()
Expand Down
93 changes: 93 additions & 0 deletions sapl/materia/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.contrib.auth.models import Group
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models.functions import Concat
from django.template import defaultfilters
Expand Down Expand Up @@ -382,6 +383,98 @@ def save(self, force_insert=False, force_update=False, using=None,
using=using,
update_fields=update_fields)

@staticmethod
def get_proximo_numero(tipo, ano=None, numero_preferido=None):
"""
Retorna o próximo número disponível para uma MateriaLegislativa
baseado no tipo e nas configurações de numeração.

Args:
tipo: TipoMateriaLegislativa - o tipo da matéria
ano: int - o ano da matéria (default: ano atual)
numero_preferido: int - número preferido/desejado (opcional)

Returns:
tuple[int, int]: Uma tupla contendo (numero, ano) da matéria.
"""
from django.db.models import Max
from sapl.parlamentares.models import Legislatura
import sapl.base.models

if ano is None:
ano = timezone.now().year

# Obtém a configuração de numeração
numeracao = None
try:
numeracao = sapl.base.models.AppConfig.objects.last(
).sequencia_numeracao_protocolo
except AttributeError:
pass

if not isinstance(tipo, TipoMateriaLegislativa):
if tipo is None:
raise ValidationError(_("O tipo é obrigatório."))

try:
tipo_id = int(tipo)
except (ValueError, TypeError):
raise ValidationError(_("Tipo inválido: '%s'") % tipo)

try:
tipo = TipoMateriaLegislativa.objects.get(pk=tipo_id)
except TipoMateriaLegislativa.DoesNotExist:
raise TipoMateriaLegislativa.DoesNotExist(
_("TipoMateriaLegislativa with pk '%s' does not exist.") % tipo_id
)

# O tipo pode sobrescrever a configuração global
if tipo.sequencia_numeracao:
numeracao = tipo.sequencia_numeracao

# Calcula o próximo número baseado no tipo de numeração
if numeracao == 'A': # Por ano
numero = MateriaLegislativa.objects.filter(
ano=ano, tipo=tipo).aggregate(Max('numero'))
elif numeracao == 'L': # Por legislatura
legislatura = Legislatura.objects.filter(
data_inicio__year__lte=ano,
data_fim__year__gte=ano).first()
if legislatura:
data_inicio = legislatura.data_inicio
data_fim = legislatura.data_fim
numero = MateriaLegislativa.objects.filter(
data_apresentacao__gte=data_inicio,
data_apresentacao__lte=data_fim,
tipo=tipo).aggregate(Max('numero'))
else:
numero = {'numero__max': 0}
elif numeracao == 'U': # Único/Universal
numero = MateriaLegislativa.objects.filter(
tipo=tipo).aggregate(Max('numero'))
else:
numero = {'numero__max': 0}

# Converte o número preferido para inteiro, se possível
numero_preferido_int = None
if numero_preferido:
try:
numero_preferido_int = int(numero_preferido)
except (TypeError, ValueError):
numero_preferido_int = None

# Verifica se o número preferido está disponível
if numero_preferido_int is not None and not MateriaLegislativa.objects.filter(
tipo=tipo,
ano=ano,
numero=numero_preferido_int).exists():
return numero_preferido_int, ano

# Retorna o próximo número sequencial
max_numero = numero['numero__max']
return ((max_numero + 1) if max_numero else 1), ano



class Autoria(models.Model):
autor = models.ForeignKey(Autor,
Expand Down
48 changes: 5 additions & 43 deletions sapl/materia/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,53 +340,15 @@ def get(self, request, *args, **kwargs):

@permission_required('materia.detail_materialegislativa')
def recuperar_materia(request):
logger = logging.getLogger(__name__)
username = request.user.username
tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo'])
ano = request.GET.get('ano', '')

if not (tipo and ano):
return JsonResponse({'numero': '', 'ano': ''})

numeracao = None
try:
logger.debug("user=" + username +
". Tentando obter numeração da matéria.")
numeracao = sapl.base.models.AppConfig.objects.last(
).sequencia_numeracao_protocolo
except AttributeError as e:
logger.error("user=" + username + ". " + str(e) +
" Numeracao da matéria definida como None.")
pass
ano = request.GET.get('ano', None)

if tipo.sequencia_numeracao:
numeracao = tipo.sequencia_numeracao

if numeracao == 'A':
numero = MateriaLegislativa.objects.filter(
ano=ano, tipo=tipo).aggregate(Max('numero'))
elif numeracao == 'L':
legislatura = Legislatura.objects.filter(
data_inicio__year__lte=ano,
data_fim__year__gte=ano).first()
data_inicio = legislatura.data_inicio
data_fim = legislatura.data_fim
numero = MateriaLegislativa.objects.filter(
data_apresentacao__gte=data_inicio,
data_apresentacao__lte=data_fim,
tipo=tipo).aggregate(
Max('numero'))
elif numeracao == 'U':
numero = MateriaLegislativa.objects.filter(
tipo=tipo).aggregate(Max('numero'))

if numeracao is None:
numero['numero__max'] = 0

max_numero = numero['numero__max'] + 1 if numero['numero__max'] else 1
max_numero, ano = MateriaLegislativa.get_proximo_numero(
tipo=tipo,
ano=int(ano) if ano else None
)

response = JsonResponse({'numero': max_numero, 'ano': ano})

return response


Expand Down