Sistema de Informações Gerenciais do Interlegis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

393 lines
12 KiB

import calendar
import datetime
import locale
from dashboard import Dashcard, getcolor
from random import randint, seed
from django.db.models import Count, F, Q
from django.db.models.functions import TruncMonth
from django.http import QueryDict
from django.utils import timezone
from django.utils.text import slugify
from django.utils.translation import gettext as _, to_locale, get_language
import django_filters
from sigi.apps.servicos.models import Servico, TipoServico
from sigi.apps.contatos.models import UnidadeFederativa
class UsoServicosFilter(django_filters.FilterSet):
uf = django_filters.ModelChoiceFilter(
field_name="servico__casa_legislativa__municipio__uf",
label=_("UF"),
queryset=UnidadeFederativa.objects.all(),
)
class Meta:
model = TipoServico
fields = ["uf"]
class AnoServicoFilter(django_filters.FilterSet):
ano = django_filters.ModelChoiceFilter(
field_name="data_ativacao__year",
label=_("Ano"),
queryset=(
Servico.objects.filter(hospedagem_interlegis=True)
.order_by("data_ativacao__year")
.values_list("data_ativacao__year", flat=True)
.distinct("data_ativacao__year")
),
)
class Meta:
model = Servico
fields = ["ano"]
class Sazonalidade(Dashcard):
title = _("Sazonalidade da hospedagem de serviços")
chart_type = Dashcard.TYPE_LINE
model = Servico
label_field = ("data_ativacao", TruncMonth, lambda d: d.strftime("%m/%Y"))
datasets = [
{
"label_field": "tipo_servico__sigla",
"data_field": ("*", Count),
}
]
def get_dataset_color(self, dataset_label):
return getcolor(dataset_label)
def get_queryset(self, request):
qs = (
super()
.get_queryset(request)
.filter(data_desativacao=None)
.order_by("tipo_servico__sigla", "data_ativacao")
)
ano = request.GET.get("ano", None)
if ano is None:
ano = (
qs.dates("data_ativacao", "year")
.values_list("data_ativacao__year", flat=True)
.last()
)
return qs.filter(data_ativacao__year=ano)
def get_prev_page(self, request=None, queryset=None):
anos = Servico.objects.dates("data_ativacao", "year").values_list(
"data_ativacao__year", flat=True
)
if request is None:
params = QueryDict().copy()
params["ano"] = anos.last() - 1
else:
params = request.GET.copy()
params["ano"] = int(request.GET.get("ano", anos.last())) - 1
if params["ano"] not in anos:
return None
return params.urlencode()
def get_next_page(self, request=None, queryset=None):
if request is None:
return None
anos = Servico.objects.dates("data_ativacao", "year").values_list(
"data_ativacao__year", flat=True
)
params = request.GET.copy()
params["ano"] = int(request.GET.get("ano", anos.last())) + 1
if params["ano"] not in anos:
return None
return params.urlencode()
class ResumoSeit(Dashcard):
title = _("Serviços hospedados no Interlegis")
chart_type = Dashcard.TYPE_TABLE
label_name = _("Serviço")
model = Servico
def get_meses(self, request=None):
if request is None:
mes = datetime.date.today().month
ano = datetime.date.today().year
else:
mes = int(request.GET.get("mes", datetime.date.today().month))
ano = int(request.GET.get("ano", datetime.date.today().year))
mes_atual = datetime.date(year=ano, month=mes, day=1)
mes_anterior = (mes_atual - datetime.timedelta(days=1)).replace(day=1)
mes_proximo = mes_atual + datetime.timedelta(
days=calendar.monthrange(mes_atual.year, mes_atual.month)[1]
)
return mes_atual, mes_anterior, mes_proximo
def get_queryset(self, request):
mes_atual, mes_anterior, mes_proximo = self.get_meses(request)
return (
super()
.get_queryset(request)
.filter(
(
Q(data_ativacao__year=mes_atual.year)
& Q(Q(data_ativacao__month=mes_atual.month))
)
| (
Q(data_ativacao__year=mes_anterior.year)
& Q(Q(data_ativacao__month=mes_anterior.month))
)
)
.values(
servico=F("tipo_servico__nome"),
mes=TruncMonth("data_ativacao"),
)
.annotate(ativados=Count("casa_legislativa__id", distinct=True))
)
def get_labels(self, request, queryset=None):
mes_atual, mes_anterior, mes_proximo = self.get_meses(request)
return [
_("Total de casas atendidas"),
_(f"Novas casas em {mes_anterior:%m/%Y}"),
_(f"Novas casas em {mes_atual:%m/%Y}"),
]
def get_datasets(self, request, queryset=None):
mes_atual, mes_anterior, mes_proximo = self.get_meses(request)
if queryset is None:
queryset = self.get_queryset(request)
labels = self.get_labels(request, queryset)
datasets = {
s["servico"]: {
"total": s["total"],
mes_anterior: 0,
mes_atual: 0,
}
for s in Servico.objects.filter(data_desativacao=None)
.values(servico=F("tipo_servico__nome"))
.annotate(total=Count("casa_legislativa", distinct=True))
}
for data in queryset:
datasets[data["servico"]][data["mes"]] = data["ativados"]
return [
{
"label": label,
"data": {
labels[0]: data["total"],
labels[1]: data[mes_atual],
labels[2]: data[mes_anterior],
},
}
for label, data in datasets.items()
]
def get_prev_page(self, request=None, queryset=None):
mes_atual, mes_anterior, mes_proximo = self.get_meses(request)
params = QueryDict().copy()
params["ano"] = mes_anterior.year
params["mes"] = mes_anterior.month
return params.urlencode()
def get_next_page(self, request=None, queryset=None):
mes_atual, mes_anterior, mes_proximo = self.get_meses(request)
params = QueryDict().copy()
params["ano"] = mes_proximo.year
params["mes"] = mes_proximo.month
return params.urlencode()
class AtualizacaoServicos(Dashcard):
title = _("Frequência de atualização")
chart_type = Dashcard.TYPE_BAR
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),
]
def get_queryset(self, request):
counts = {}
hoje = timezone.localdate()
ate = hoje
for label, dias in self.intervalos:
if dias is not None:
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)
)
return (
super()
.get_queryset(request)
.exclude(string_pesquisa="")
.filter(servico__data_desativacao=None)
.annotate(**counts)
)
def get_labels(self, request, queryset=None):
return [label for label, *__ in self.intervalos]
def get_datasets(self, request, queryset=None):
if queryset is None:
queryset = self.get_queryset(request)
return [
{
"type": "bar",
"label": ts.sigla,
"data": {
label: getattr(ts, slugify(label))
for label, *__ in self.intervalos
},
"backgroundColor": getcolor(ts.sigla),
}
for ts in queryset
]
class UsoServicos(Dashcard):
title = _("Uso dos serviços")
chart_type = Dashcard.TYPE_BAR
model = TipoServico
filterset = UsoServicosFilter
label_field = "sigla"
def get_dataset_color(self, dataset_label):
return getcolor(dataset_label)
def apply_filters(self, request, queryset):
queryset = queryset.exclude(string_pesquisa="").filter(
servico__data_desativacao=None
)
return super().apply_filters(request, queryset)
def get_datasets(self, request, queryset=None):
if queryset is None:
queryset = self.get_queryset(request)
counts = {
f"{key}_count": Count(
"servico",
distinct=True,
filter=Q(servico__resultado_verificacao=key),
)
for key, *__ in Servico.RESULTADO_CHOICES
}
queryset = queryset.annotate(**counts)
return [
{
"label": label,
"data": {
r.sigla: getattr(r, f"{key}_count") for r in queryset
},
}
for key, label in Servico.RESULTADO_CHOICES
]
class ServicosAno(Dashcard):
title = _("Serviços hospedados por ano")
chart_type = Dashcard.TYPE_BAR
model = Servico
filterset = AnoServicoFilter
chart_options = {
"scales": {"x": {"stacked": True}, "y": {"stacked": True}},
"plugins": {"tooltip": {"mode": "index"}},
}
def get_dataset_color(self, dataset_label):
return getcolor(dataset_label)
def apply_filters(self, request, queryset):
return (
super()
.apply_filters(request, queryset)
.filter(hospedagem_interlegis=True)
)
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.GET.get("ano", None):
# Usuário informou um ano, então vamos mostrar os meses daquele ano
qs = (
qs.order_by("data_ativacao__month", "tipo_servico__sigla")
.values(
label=F("data_ativacao__month"),
sigla=F("tipo_servico__sigla"),
)
.annotate(total=Count("id"))
)
else:
qs = (
qs.order_by("data_ativacao__year", "tipo_servico__sigla")
.values(
label=F("data_ativacao__year"),
sigla=F("tipo_servico__sigla"),
)
.annotate(total=Count("id"))
)
return qs
def get_labels(self, request, queryset=None):
if queryset is None:
return list(
Servico.objects.filter(hospedagem_interlegis=True)
.order_by("data_ativacao__year")
.values_list("data_ativacao__year")
.distinct("data_ativacao__year")
)
if request.GET.get("ano", None):
lang = to_locale(get_language()) + ".UTF-8"
locale.setlocale(locale.LC_ALL, lang)
map_function = lambda x: _(calendar.month_abbr[x])
else:
map_function = str
labels = list({r["label"] for r in queryset})
labels.sort()
labels = list(map(map_function, labels))
return labels
def get_datasets(self, request, queryset=None):
if queryset is None:
queryset = self.get_queryset(request)
if request.GET.get("ano", None):
lang = to_locale(get_language()) + ".UTF-8"
locale.setlocale(locale.LC_ALL, lang)
map_function = lambda x: _(calendar.month_abbr[x])
else:
map_function = str
labels = self.get_labels(request, queryset)
series = {}
for d in queryset:
sigla = d["sigla"]
label = map_function(d["label"])
if sigla not in series:
series[sigla] = dict(zip(labels, [0] * len(labels)))
series[sigla][label] = d["total"]
return [
{
"label": s,
"data": series[s],
"backgroundColor": getcolor(s),
}
for s in series
]