diff --git a/sigi/apps/casas/dashboards.py b/sigi/apps/casas/dashboards.py
index b0027fd..8dfb1b0 100644
--- a/sigi/apps/casas/dashboards.py
+++ b/sigi/apps/casas/dashboards.py
@@ -1,3 +1,4 @@
+from django.urls import reverse
import django_filters
from dashboard import Dashcard, getcolor
from django.db.models import Count
@@ -32,6 +33,16 @@ class CasasGerente(Dashcard):
.exclude(casas_que_gerencia=None)
)
+ def get_view_link(self, x_axis, y_axis, value):
+ try:
+ s = Servidor.objects.exclude(casas_que_gerencia=None).get(
+ nome_completo=x_axis
+ )
+ except:
+ return None
+ base_url = reverse("admin:casas_orgao_changelist")
+ return f"{base_url}?gerentes_interlegis__id__exact={s.id}"
+
class PerformanceCarteira(Dashcard):
chart_type = Dashcard.TYPE_DOUGHNUT
@@ -42,20 +53,9 @@ class PerformanceCarteira(Dashcard):
LABEL_USAM = _("Utilizam serviços")
LABEL_NAO_USAM = _("Não utilizam servços")
- def apply_filters(self, request, queryset):
- filter = self.filterset(request.GET, queryset=queryset)
- valid = filter.is_valid()
- if filter.form.cleaned_data["servidor"] is None:
- if (
- request.user.servidor
- and request.user.servidor.casas_que_gerencia.exists()
- ):
- return request.user.servidor.casas_que_gerencia.all()
- return (
- super()
- .apply_filters(request, queryset)
- .exclude(gerentes_interlegis=None)
- )
+ def get_queryset(self, request):
+ queryset = super().get_queryset(request)
+ return queryset.exclude(gerentes_interlegis=None)
def get_labels(self, request, queryset=None):
return [self.LABEL_USAM, self.LABEL_NAO_USAM]
@@ -63,11 +63,23 @@ class PerformanceCarteira(Dashcard):
def get_datasets(self, request, queryset=None):
if queryset is None:
queryset = self.get_queryset(request)
+ base_url = reverse("admin:casas_orgao_changelist")
+ filter = self.get_filter(request.GET, queryset)
+ filter.is_valid()
+ servidor_id = filter.data.get("servidor")
+ if servidor_id:
+ servidor_qs = f"&gerentes_interlegis__id__exact={servidor_id}"
+ else:
+ servidor_qs = ""
return [
{
"data": [
queryset.exclude(servico=None).count(),
queryset.filter(servico=None).count(),
- ]
+ ],
+ "links": [
+ f"{base_url}?tipo__legislativo__exact=1&servico=CS{servidor_qs}",
+ f"{base_url}?tipo__legislativo__exact=1&servico=SS{servidor_qs}",
+ ],
}
]
diff --git a/sigi/apps/casas/filters.py b/sigi/apps/casas/filters.py
index d92c24e..cbf05ca 100644
--- a/sigi/apps/casas/filters.py
+++ b/sigi/apps/casas/filters.py
@@ -2,7 +2,7 @@ from django.contrib import admin
from django.utils.translation import gettext as _
from sigi.apps.servidores.models import Servidor
from sigi.apps.convenios.models import Projeto
-from sigi.apps.servicos.models import TipoServico
+from sigi.apps.servicos.models import TipoServico, Servico
class GerentesInterlegisFilter(admin.filters.RelatedFieldListFilter):
@@ -36,7 +36,14 @@ class ServicoFilter(admin.SimpleListFilter):
)
elif self.value() == "CR":
queryset = queryset.exclude(
- servico__tipo_servico__modo="H"
+ id__in=(
+ Servico.objects.filter(
+ data_desativacao__isnull=True,
+ tipo_servico__modo="H",
+ )
+ .distinct("casa_legislativa_id")
+ .values_list("casa_legislativa_id", flat=True)
+ )
).exclude(servico=None)
elif self.value() == "CH":
queryset = queryset.filter(
diff --git a/sigi/apps/convenios/dashboards.py b/sigi/apps/convenios/dashboards.py
index 7a9a484..51c0dd5 100644
--- a/sigi/apps/convenios/dashboards.py
+++ b/sigi/apps/convenios/dashboards.py
@@ -1,3 +1,4 @@
+from django.urls import reverse
import numpy as np
import pandas as pd
import django_filters
@@ -171,24 +172,28 @@ class ConvenioServico(Dashcard):
if queryset is None:
queryset = self.get_queryset(request)
values = dict(queryset)
+ base_url = reverse("admin:casas_orgao_changelist")
datasets = [
{
"label": _(
"Casas sem convenio que utilizam algum serviço de hospedagem"
),
"data": [values["hospedagem"]],
+ "links": [f"{base_url}?convenio=SC&servico=CH"],
},
{
"label": _(
"Casas sem convenio que utilizam somente serviço de registro"
),
"data": [values["total"] - values["hospedagem"]],
+ "links": [f"{base_url}?convenio=SC&servico=CR"],
},
{
"label": _(
"Casas sem convenio que utilizam algum serviço de registro e/ou hospedagem"
),
"data": [values["total"]],
+ "links": [f"{base_url}?convenio=SC&servico=CS"],
},
]
return datasets
diff --git a/sigi/apps/convenios/templates/convenios/dashboard/resumo_convenios.html b/sigi/apps/convenios/templates/convenios/dashboard/resumo_convenios.html
index 27c977e..fae4524 100644
--- a/sigi/apps/convenios/templates/convenios/dashboard/resumo_convenios.html
+++ b/sigi/apps/convenios/templates/convenios/dashboard/resumo_convenios.html
@@ -13,7 +13,7 @@
| {{ label }} |
{% for value in values %}
- {{ value }} |
+ {{ value }} |
{% endfor %}
{% endfor %}
@@ -24,7 +24,7 @@
{% for label, value in datasets.totais %}
| {{ label }} |
- {{ value }} |
+ {{ value }} |
{% endfor %}
\ No newline at end of file
diff --git a/sigi/apps/eventos/dashboards.py b/sigi/apps/eventos/dashboards.py
index a600108..a25452e 100644
--- a/sigi/apps/eventos/dashboards.py
+++ b/sigi/apps/eventos/dashboards.py
@@ -1,5 +1,6 @@
import calendar
import datetime
+from django.urls import reverse
import django_filters
from dashboard import Dashcard, getcolor
from django.db.models import F, Count, Q
@@ -32,9 +33,31 @@ class AnoFilterset(django_filters.FilterSet):
fields = ["ano"]
+class AnoCategoriaFilterset(django_filters.FilterSet):
+ ano = django_filters.ChoiceFilter(
+ field_name="data_inicio",
+ lookup_expr="year",
+ label=_("Ano"),
+ distinct=True,
+ choices=get_anos,
+ )
+ categoria = django_filters.ChoiceFilter(
+ field_name="tipo_evento__categoria",
+ lookup_expr="exact",
+ label=_("Categoria"),
+ distinct=True,
+ choices=TipoEvento.CATEGORIA_CHOICES,
+ )
+
+ class Meta:
+ model = Evento
+ fields = ["ano", "categoria"]
+
+
class EventosStatus(Dashcard):
chart_type = Dashcard.TYPE_DOUGHNUT
title = _("Eventos por status")
+ filterset = AnoCategoriaFilterset
model = Evento
label_field = ("status", F, lambda s: dict(Evento.STATUS_CHOICES)[s])
datasets = [{"data_field": ("id", Count)}]
@@ -42,6 +65,19 @@ class EventosStatus(Dashcard):
def get_dataset_color(self, dataset_label):
return getcolor(dataset_label)
+ def get_view_link(self, x_axis, y_axis, value):
+ base_url = reverse("admin:eventos_evento_changelist")
+ querystrs = [f"status__exact={x_axis}"]
+ filter = self.get_filter(self.request.GET)
+ if filter.is_valid():
+ ano = filter.data.get("ano")
+ categoria = filter.data.get("categoria")
+ if ano:
+ querystrs.append(f"data_inicio__year={ano}")
+ if categoria:
+ querystrs.append(f"tipo_evento__categoria__exact={categoria}")
+ return base_url + "?" + "&".join(querystrs)
+
class EventosAno(Dashcard):
chart_type = Dashcard.TYPE_LINE
@@ -98,10 +134,7 @@ class EventosAno(Dashcard):
def get_queryset(self, request):
counts = self.get_counters(request)
return (
- super()
- .get_queryset(request)
- .values("categoria")
- .annotate(**counts)
+ super().get_queryset(request).values("categoria").annotate(**counts)
)
def get_dataset_color(self, dataset_label):
@@ -116,6 +149,10 @@ class EventosAno(Dashcard):
{
"label": categorias[r["categoria"]],
"data": [r[c] for c in counters],
+ "links": [
+ self.get_view_link(r["categoria"], c, r[c])
+ for c in counters
+ ],
"backgroundColor": self.get_dataset_color(r["categoria"]),
}
for r in queryset
@@ -129,6 +166,15 @@ class EventosAno(Dashcard):
mes = self.get_meses(request)[-3]
return f"ano={mes.year}&mes={mes.month}"
+ def get_view_link(self, x_axis, y_axis, value):
+ base_link = reverse("admin:eventos_evento_changelist")
+ return (
+ f"{base_link}?status__exact={Evento.STATUS_REALIZADO}"
+ f"&tipo_evento__categoria__exact={x_axis}"
+ f'&data_inicio__year={y_axis.split("_")[1]}'
+ f'&data_inicio__month={y_axis.split("_")[2]}'
+ )
+
class EventosCategoria(Dashcard):
chart_type = Dashcard.TYPE_DOUGHNUT
@@ -151,3 +197,16 @@ class EventosCategoria(Dashcard):
def get_dataset_color(self, dataset_label):
return getcolor(dataset_label)
+
+ def get_view_link(self, x_axis, y_axis, value):
+ base_url = reverse("admin:eventos_evento_changelist")
+ q_ano = ""
+ filter = self.get_filter(self.request.GET)
+ if filter.is_valid():
+ ano = filter.data.get("ano")
+ if ano:
+ q_ano = f"data_inicio__year={ano}&"
+ return (
+ f"{base_url}?{q_ano}status__exact={Evento.STATUS_REALIZADO}"
+ f"&tipo_evento__categoria__exact={x_axis}"
+ )
diff --git a/sigi/apps/servicos/dashboards.py b/sigi/apps/servicos/dashboards.py
index 8cb8bea..47bf19d 100644
--- a/sigi/apps/servicos/dashboards.py
+++ b/sigi/apps/servicos/dashboards.py
@@ -6,6 +6,7 @@ from random import choice, randint, seed
from django.db.models import Count, F, Q
from django.db.models.functions import TruncMonth
from django.http import QueryDict
+from django.urls import reverse
from django.utils import timezone
from django.utils.text import slugify
from django.utils.translation import gettext as _, to_locale, get_language
@@ -82,6 +83,18 @@ class Sazonalidade(Dashcard):
)
return qs.filter(data_ativacao__year=ano)
+ def get_view_link(self, x_axis, y_axis, value):
+ try:
+ tipo = TipoServico.objects.get(sigla=x_axis)
+ except TipoServico.DoesNotExist:
+ return None
+ mes, ano = y_axis.split("/")
+ base_url = reverse("admin:servicos_servico_changelist")
+ return (
+ f"{base_url}?tipo_servico__id__exact={tipo.pk}"
+ f"&data_ativacao__year={ano}&data_ativacao__month={mes}"
+ )
+
def get_prev_page(self, request=None, queryset=None):
anos = Servico.objects.dates("data_ativacao", "year").values_list(
"data_ativacao__year", flat=True
@@ -170,9 +183,13 @@ class ResumoSeit(Dashcard):
"total": s["total"],
mes_anterior: 0,
mes_atual: 0,
+ "servico_id": s["servico_id"],
}
for s in Servico.objects.filter(data_desativacao=None)
- .values(servico=F("tipo_servico__nome"))
+ .values(
+ servico=F("tipo_servico__nome"),
+ servico_id=F("tipo_servico__id"),
+ )
.annotate(total=Count("casa_legislativa", distinct=True))
}
for data in queryset:
@@ -186,10 +203,39 @@ class ResumoSeit(Dashcard):
labels[1]: data[mes_atual],
labels[2]: data[mes_anterior],
},
+ "links": [
+ self.get_view_link(
+ "total", data["servico_id"], data["total"]
+ ),
+ self.get_view_link(
+ mes_atual, data["servico_id"], data[mes_atual]
+ ),
+ self.get_view_link(
+ mes_anterior, data["servico_id"], data[mes_anterior]
+ ),
+ ],
}
for label, data in datasets.items()
]
+ def get_view_link(self, x_axis, y_axis, value):
+ if value == 0:
+ return None
+ base_url = reverse("admin:servicos_servico_changelist")
+ qstrs = [
+ "data_desativacao__isnull=True",
+ f"tipo_servico__id__exact={y_axis}",
+ ]
+ if not isinstance(x_axis, str):
+ qstrs.extend(
+ [
+ f"data_ativacao__year={x_axis.year}",
+ f"data_ativacao__month={x_axis.month}",
+ ]
+ )
+ qstrs = "&".join(qstrs)
+ return f"{base_url}?{qstrs}"
+
def get_prev_page(self, request=None, queryset=None):
mes_atual, mes_anterior, mes_proximo = self.get_meses(request)
params = QueryDict().copy()
@@ -211,12 +257,13 @@ class AtualizacaoServicos(Dashcard):
model = TipoServico
intervalos = [
- ("Na semana", 7),
- ("No mês", 30),
- ("No trimestre", 3 * 30),
- ("No semestre", 6 * 30),
- ("No ano", 365),
- ("Mais de ano", None),
+ ("Na semana", 7, "updated"),
+ ("No mês", 30, "week"),
+ ("No trimestre", 90, "month"),
+ ("No semestre", 182, "quarter"),
+ ("No ano", 365, "semester"),
+ ("Mais de ano", 0, "year"),
+ ("Erro na verificação", None, "err"),
]
def get_queryset(self, request):
@@ -224,17 +271,21 @@ class AtualizacaoServicos(Dashcard):
hoje = timezone.localdate()
ate = hoje
- for label, dias in self.intervalos:
- if dias is not None:
+ for label, dias, *__ in self.intervalos:
+ if dias is None:
+ counts[slugify(label)] = Count(
+ "servico", ~Q(servico__erro_atualizacao="")
+ )
+ elif dias > 0:
de = hoje - datetime.timedelta(days=dias)
counts[slugify(label)] = Count(
"servico", Q(servico__data_ultimo_uso__range=(de, ate))
)
- ate = de - datetime.timedelta(days=1)
- else:
- counts[slugify(label)] = Count(
- "servico", Q(servico__data_ultimo_uso__lte=ate)
- )
+ ate = de - datetime.timedelta(days=1)
+ else:
+ counts[slugify(label)] = Count(
+ "servico", Q(servico__data_ultimo_uso__lte=ate)
+ )
return (
super()
@@ -259,10 +310,25 @@ class AtualizacaoServicos(Dashcard):
for label, *__ in self.intervalos
},
"backgroundColor": getcolor(ts.sigla),
+ "links": [
+ self.get_view_link(
+ ts.id, atualizacao, getattr(ts, slugify(label))
+ )
+ for label, dias, atualizacao in self.intervalos
+ ],
}
for ts in queryset
]
+ def get_view_link(self, x_axis, y_axis, value):
+ print(x_axis, y_axis, value)
+ base_url = reverse("admin:servicos_servico_changelist")
+ return (
+ f"{base_url}?data_desativacao__isnull=True"
+ f"&atualizacao={y_axis}"
+ f"&tipo_servico__id__exact={x_axis}"
+ )
+
class UsoServicos(Dashcard):
title = _("Uso dos serviços")
@@ -299,10 +365,22 @@ class UsoServicos(Dashcard):
{
"label": label,
"data": {r.sigla: getattr(r, f"{key}_count") for r in queryset},
+ "links": [
+ self.get_view_link(r.id, key, getattr(r, f"{key}_count"))
+ for r in queryset
+ ],
}
for key, label in Servico.RESULTADO_CHOICES
]
+ def get_view_link(self, x_axis, y_axis, value):
+ base_url = reverse("admin:servicos_servico_changelist")
+ return (
+ f"{base_url}?data_desativacao__isnull=True"
+ f"&resultado_verificacao__exact={y_axis}"
+ f"&tipo_servico__id__exact={x_axis}"
+ )
+
class ServicosAno(Dashcard):
title = _("Serviços hospedados por ano")