Browse Source

Ajustes solicitados na homologação do gertik #160523

pull/166/head
Sesóstris Vieira 1 year ago
parent
commit
a66cc529b6
  1. 114
      sigi/apps/eventos/admin.py
  2. 55
      sigi/apps/eventos/models.py
  3. 8
      sigi/static/css/change_form.css

114
sigi/apps/eventos/admin.py

@ -35,7 +35,11 @@ from sigi.apps.eventos.models import (
from sigi.apps.eventos.forms import EventoAdminForm, SelecionaModeloForm from sigi.apps.eventos.forms import EventoAdminForm, SelecionaModeloForm
from sigi.apps.utils import abreviatura from sigi.apps.utils import abreviatura
from sigi.apps.utils.filters import EmptyFilter, DateRangeFilter from sigi.apps.utils.filters import EmptyFilter, DateRangeFilter
from sigi.apps.utils.mixins import CartExportMixin, ValueLabeledResource from sigi.apps.utils.mixins import (
CartExportMixin,
LabeledResourse,
ValueLabeledResource,
)
class SolicitacaoStatusFilter(admin.SimpleListFilter): class SolicitacaoStatusFilter(admin.SimpleListFilter):
@ -84,6 +88,50 @@ class SolicitacaoStatusFilter(admin.SimpleListFilter):
return queryset return queryset
class SolicitacaoResource(LabeledResourse):
status = Field(column_name="status")
oficinas = Field(column_name="oficinas solicitadas")
oficinas_uf = Field(column_name="número de oficinas realizadas na UF")
class Meta:
model = Solicitacao
fields = (
"num_processo",
"status",
"senador",
"data_pedido",
"data_recebido_coperi",
"oficinas",
"casa__nome",
"casa__municipio__nome",
"casa__municipio__uf__nome",
"casa__municipio__uf__regiao",
"casa__municipio__populacao",
"oficinas_uf",
"estimativa_casas",
"estimativa_servidores",
)
export_order = fields
def dehydrate_status(self, obj):
return obj.get_status()
def dehydrate_oficinas(self, obj):
return ", ".join(
[i.tipo_evento.sigla for i in obj.itemsolicitado_set.all()]
)
def dehydrate_oficinas_uf(sekf, obj):
return Evento.objects.filter(
status__in=[Evento.STATUS_CONFIRMADO, Evento.STATUS_REALIZADO],
casa_anfitria__municipio__uf=obj.casa.municipio.uf,
data_inicio__year__gte=timezone.localdate().year - 2,
).count()
def dehydrate_casa__municipio__uf__regiao(self, obj):
return obj.casa.municipio.uf.get_regiao_display()
class EventoResource(ValueLabeledResource): class EventoResource(ValueLabeledResource):
# categoria_evento = Field(column_name="tipo_evento__categoria") # categoria_evento = Field(column_name="tipo_evento__categoria")
# status = Field(column_name="status") # status = Field(column_name="status")
@ -178,9 +226,10 @@ class ItemSolicitadoInline(admin.StackedInline):
"status", "status",
"justificativa", "justificativa",
"servidor", "servidor",
"data_analise",
"evento", "evento",
) )
readonly_fields = ("servidor", "evento") readonly_fields = ("servidor", "data_analise", "evento")
extra = 1 extra = 1
autocomplete_fields = ("tipo_evento",) autocomplete_fields = ("tipo_evento",)
@ -194,10 +243,12 @@ class TipoEventoAdmin(admin.ModelAdmin):
@admin.register(Solicitacao) @admin.register(Solicitacao)
class SolicitacaoAdmin(admin.ModelAdmin): class SolicitacaoAdmin(CartExportMixin, admin.ModelAdmin):
resource_class = SolicitacaoResource
list_display = ( list_display = (
"num_processo",
"casa", "casa",
"get_sigad_url",
"get_status",
"senador", "senador",
"data_pedido", "data_pedido",
"data_recebido_coperi", "data_recebido_coperi",
@ -209,7 +260,6 @@ class SolicitacaoAdmin(admin.ModelAdmin):
"get_oficinas_uf", "get_oficinas_uf",
"estimativa_casas", "estimativa_casas",
"estimativa_servidores", "estimativa_servidores",
"get_status",
) )
list_filter = ( list_filter = (
"casa__municipio__uf", "casa__municipio__uf",
@ -219,6 +269,7 @@ class SolicitacaoAdmin(admin.ModelAdmin):
SolicitacaoStatusFilter, SolicitacaoStatusFilter,
) )
list_select_related = ["casa", "casa__municipio", "casa__municipio__uf"] list_select_related = ["casa", "casa__municipio", "casa__municipio__uf"]
list_display_links = ("casa",)
search_fields = ( search_fields = (
"casa__search_text", "casa__search_text",
"casa__municipio__search_text", "casa__municipio__search_text",
@ -237,6 +288,8 @@ class SolicitacaoAdmin(admin.ModelAdmin):
else: else:
servidor = None servidor = None
agora = timezone.localtime()
for item in instances: for item in instances:
if ( if (
item.status == ItemSolicitado.STATUS_SOLICITADO item.status == ItemSolicitado.STATUS_SOLICITADO
@ -253,11 +306,14 @@ class SolicitacaoAdmin(admin.ModelAdmin):
) )
elif item.status == ItemSolicitado.STATUS_AUTORIZADO: elif item.status == ItemSolicitado.STATUS_AUTORIZADO:
item.servidor = servidor item.servidor = servidor
item.data_analise = agora
if item.evento is None: if item.evento is None:
item.evento = Evento( item.evento = Evento(
tipo_evento=item.tipo_evento, tipo_evento=item.tipo_evento,
nome=_( nome=_(
f"{item.tipo_evento} em {item.solicitacao.casa}" f"{item.tipo_evento} em {item.solicitacao.casa}"[
:100
]
), ),
descricao=_( descricao=_(
f"{item.tipo_evento} em {item.solicitacao.casa}" f"{item.tipo_evento} em {item.solicitacao.casa}"
@ -298,27 +354,30 @@ class SolicitacaoAdmin(admin.ModelAdmin):
), ),
messages.INFO, messages.INFO,
) )
elif ItemSolicitado.STATUS_REJEITADO and item.evento is not None: elif item.status == ItemSolicitado.STATUS_REJEITADO:
item.evento.status = Evento.STATUS_CANCELADO item.servidor = servidor
item.evento.observacao += _( item.data_analise = agora
f"\nCancelado por {servidor} com a justificativa: {item.justificativa}" if item.evento is not None:
) item.evento.status = Evento.STATUS_CANCELADO
item.evento.data_cancelamento = timezone.localdate() item.evento.observacao += _(
item.evento.motivo_cancelamento = _( f"\nCancelado por {servidor} com a justificativa: {item.justificativa}"
f"\nCancelado por {servidor} com a justificativa: {item.justificativa}" )
) item.evento.data_cancelamento = timezone.localdate()
self.message_user( item.evento.motivo_cancelamento = _(
request, f"\nCancelado por {servidor} com a justificativa: {item.justificativa}"
_( )
f"Status do evento {item.evento} alterado para " self.message_user(
f"{item.evento.get_status_display()}" request,
), _(
messages.INFO, f"Status do evento {item.evento} alterado para "
) f"{item.evento.get_status_display()}"
),
messages.INFO,
)
if item.evento: if item.evento:
item.evento.tipo_evento = item.tipo_evento item.evento.tipo_evento = item.tipo_evento
item.evento.nome = _( item.evento.nome = _(
f"{item.tipo_evento} em {item.solicitacao.casa}" f"{item.tipo_evento} em {item.solicitacao.casa}"[:100]
) )
item.evento.descricao = _( item.evento.descricao = _(
f"{item.tipo_evento} em {item.solicitacao.casa}" f"{item.tipo_evento} em {item.solicitacao.casa}"
@ -374,13 +433,6 @@ class SolicitacaoAdmin(admin.ModelAdmin):
def get_populacao(self, obj): def get_populacao(self, obj):
return obj.casa.municipio.populacao return obj.casa.municipio.populacao
@admin.display(description=_("Oficinas atendidas/confirmadas na UF"))
def get_oficinas_uf(self, obj):
return Evento.objects.filter(
status__in=[Evento.STATUS_CONFIRMADO, Evento.STATUS_REALIZADO],
casa_anfitria__municipio__uf=obj.casa.municipio.uf,
).count()
@admin.register(Funcao) @admin.register(Funcao)
class FuncaoAdmin(admin.ModelAdmin): class FuncaoAdmin(admin.ModelAdmin):

55
sigi/apps/eventos/models.py

@ -5,9 +5,10 @@ from django.contrib import admin
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.db.models import Sum, Count from django.db.models import Sum, Count, Q
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from sigi.apps.casas.models import Orgao, Servidor from sigi.apps.casas.models import Orgao, Servidor
from sigi.apps.contatos.models import Municipio from sigi.apps.contatos.models import Municipio
@ -142,6 +143,52 @@ class Solicitacao(models.Model):
else: else:
return _("Concluído") return _("Concluído")
@admin.display(description=_("SIGAD"), ordering="num_processo")
def get_sigad_url(self):
m = re.match(
"(?P<orgao>00100|00200)\.(?P<sequencial>\d{6})/(?P<ano>"
"\d{4})-\d{2}",
self.num_processo,
)
if m:
return mark_safe(
(
'<a href="https://intra.senado.leg.br/'
"sigad/novo/protocolo/impressao.asp?area=processo"
"&txt_numero_orgao={orgao}"
"&txt_numero_sequencial={sequencial}"
'&txt_numero_ano={ano}"'
' target="_blank">{processo}</a>'
).format(processo=self.num_processo, **m.groupdict())
)
return self.num_processo
@admin.display(description=_("Oficinas atendidas/confirmadas na UF"))
def get_oficinas_uf(self):
ano_corrente = timezone.localdate().year
counters = Evento.objects.filter(
status__in=[Evento.STATUS_CONFIRMADO, Evento.STATUS_REALIZADO],
casa_anfitria__municipio__uf=self.casa.municipio.uf,
).aggregate(
total=Count("id"),
no_ano=Count("id", filter=Q(data_inicio__year=ano_corrente)),
dois_anos=Count(
"id",
filter=Q(data_inicio__year__gte=ano_corrente - 1),
),
tres_anos=Count(
"id",
filter=Q(data_inicio__year__gte=ano_corrente - 2),
),
)
return _(
(
"Total: {total}, no ano corrente: {no_ano}, "
"nos dois últimos anos: {dois_anos}, "
"nos três últimos anos: {tres_anos}"
).format(**counters)
)
class ItemSolicitado(models.Model): class ItemSolicitado(models.Model):
STATUS_SOLICITADO = "S" STATUS_SOLICITADO = "S"
@ -187,6 +234,12 @@ class ItemSolicitado(models.Model):
null=True, null=True,
editable=False, editable=False,
) )
data_analise = models.DateTimeField(
_("data de autorização/rejeição"),
blank=True,
null=True,
editable=False,
)
justificativa = models.TextField( justificativa = models.TextField(
verbose_name=_("Justificativa"), blank=True verbose_name=_("Justificativa"), blank=True
) )

8
sigi/static/css/change_form.css

@ -14,4 +14,12 @@
.sigi-object-tools>ul>li>a { .sigi-object-tools>ul>li>a {
color: var(--object-tools-fg); color: var(--object-tools-fg);
border-color: var(--object-tools-fg); border-color: var(--object-tools-fg);
}
.input-field>label {
position: relative;
}
.readonly-label {
height: unset;
} }
Loading…
Cancel
Save