mirror of https://github.com/interlegis/sigi.git
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.
371 lines
12 KiB
371 lines
12 KiB
from django.utils import timezone
|
|
from django.db import models
|
|
from sigi.apps.casas.models import Orgao, Funcionario
|
|
from django.utils.translation import gettext as _
|
|
|
|
|
|
class TipoServico(models.Model):
|
|
MODO_CHOICES = (("H", _("Hospedagem")), ("R", _("Registro")))
|
|
email_help = "Use a marcação {url} para incluir a URL do serviço,<br/>"
|
|
string_pesquisa_help = (
|
|
"Parâmetros da pesquisa para averiguar a data da "
|
|
"última atualização do serviço. Formato:<br/>"
|
|
"<ul><li>/caminho/da/pesquisa/?parametros "
|
|
"[xml|json] campo.de.data</li>"
|
|
)
|
|
nome = models.CharField(_("nome"), max_length=60)
|
|
sigla = models.CharField(_("sigla"), max_length=12)
|
|
modo = models.CharField(
|
|
_("modo de prestação do serviço"), max_length=1, choices=MODO_CHOICES
|
|
)
|
|
string_pesquisa = models.TextField(
|
|
_("string de pesquisa"), blank=True, help_text=string_pesquisa_help
|
|
)
|
|
template_email_ativa = models.TextField(
|
|
_("template de email de ativação"), help_text=email_help, blank=True
|
|
)
|
|
template_email_altera = models.TextField(
|
|
_("template de email de alteração"), help_text=email_help, blank=True
|
|
)
|
|
template_email_desativa = models.TextField(
|
|
_("template de email de desativação"),
|
|
help_text=email_help
|
|
+ _("<br/>{motivo} para incluir o motivo da desativação do serviço"),
|
|
blank=True,
|
|
)
|
|
|
|
@property
|
|
def qtde_casas_atendidas(self):
|
|
"""Quantidade de casas atendidas"""
|
|
return self.servico_set.filter(data_desativacao=None).count()
|
|
|
|
class Meta:
|
|
verbose_name = _("tipo de serviço")
|
|
verbose_name_plural = _("tipos de serviço")
|
|
|
|
def __str__(self):
|
|
return self.nome
|
|
|
|
|
|
class Servico(models.Model):
|
|
RESULTADO_CHOICES = (
|
|
("N", _("Não verificado")),
|
|
("F", _("Funcionando")),
|
|
("U", _("Nunca foi usado")),
|
|
("D", _("Acesso negado")),
|
|
("O", _("Fora do ar")),
|
|
("I", _("Dados imcompatíveis - não é serviço Interlegis")),
|
|
)
|
|
casa_legislativa = models.ForeignKey(
|
|
Orgao, on_delete=models.PROTECT, verbose_name=_("Casa Legislativa")
|
|
)
|
|
tipo_servico = models.ForeignKey(
|
|
TipoServico, on_delete=models.PROTECT, verbose_name=_("tipo de serviço")
|
|
)
|
|
url = models.URLField(_("URL do serviço"), blank=True)
|
|
hospedagem_interlegis = models.BooleanField(
|
|
_("Hospedagem no Interlegis?"), default=False
|
|
)
|
|
data_ativacao = models.DateField(
|
|
_("Data de ativação"), default=timezone.localdate
|
|
)
|
|
data_alteracao = models.DateField(
|
|
_("Data da última alteração"), blank=True, null=True, auto_now=True
|
|
)
|
|
data_desativacao = models.DateField(
|
|
_("Data de desativação"), blank=True, null=True
|
|
)
|
|
motivo_desativacao = models.TextField(
|
|
_("Motivo da desativação"), blank=True
|
|
)
|
|
data_verificacao = models.DateTimeField(
|
|
_("data da última verificação"), blank=True, null=True
|
|
)
|
|
resultado_verificacao = models.CharField(
|
|
_("resultado da verificação"),
|
|
choices=RESULTADO_CHOICES,
|
|
default="N",
|
|
max_length=1,
|
|
)
|
|
data_ultimo_uso = models.DateField(
|
|
_("Data da última utilização"),
|
|
blank=True,
|
|
null=True,
|
|
help_text=_(
|
|
"Data em que o serviço foi utilizado pela Casa Legislativa"
|
|
" pela última vez"
|
|
),
|
|
)
|
|
erro_atualizacao = models.TextField(
|
|
_("Erro na atualização"),
|
|
blank=True,
|
|
help_text=_(
|
|
"Erro ocorrido na última tentativa de verificar a data "
|
|
"de última atualização do serviço"
|
|
),
|
|
)
|
|
|
|
@property
|
|
def status_servico(self):
|
|
if self.data_desativacao is None:
|
|
return _("Ativo")
|
|
else:
|
|
return _("Inativo")
|
|
|
|
def atualiza_data_uso(self):
|
|
import requests
|
|
from xml.dom.minidom import parseString
|
|
|
|
def reset():
|
|
if self.data_ultimo_uso is not None:
|
|
self.data_verificacao = None
|
|
self.resultado_verificacao = "N"
|
|
self.data_ultimo_uso = None
|
|
self.erro_atualizacao = ""
|
|
self.save()
|
|
return
|
|
|
|
def ultimo_uso(url, string_pesquisa):
|
|
param_pesquisa = string_pesquisa.split(" ")
|
|
if len(param_pesquisa) != 3:
|
|
return {
|
|
"data": "",
|
|
"resultado": "N",
|
|
"erro": _("String de pesquisa mal configurada"),
|
|
"comment": _("Corrija a string de pesquisa"),
|
|
}
|
|
campos = [
|
|
int(s) if s.isdigit() else s
|
|
for s in param_pesquisa[2].split(".")
|
|
]
|
|
|
|
url += param_pesquisa[0]
|
|
|
|
try: # Captura erros de conexão
|
|
req = requests.get(url, verify=False, allow_redirects=True)
|
|
except Exception as e:
|
|
return {
|
|
"data": "",
|
|
"resultado": "O",
|
|
"erro": str(e),
|
|
"comment": _(
|
|
"Não foi possível conectar com o servidor. "
|
|
"Pode estar fora do ar ou não ser "
|
|
"um {tipo}".format(tipo=self.tipo_servico.nome)
|
|
),
|
|
}
|
|
|
|
if req.status_code != 200:
|
|
return {
|
|
"data": "",
|
|
"resultado": "D",
|
|
"erro": req.reason,
|
|
"comment": _(
|
|
"Não foi possível receber os dados do "
|
|
"servidor. O acesso pode ter sido negado."
|
|
),
|
|
}
|
|
|
|
try:
|
|
if param_pesquisa[1] == "xml":
|
|
data = parseString(req.content)
|
|
elif param_pesquisa[1] == "json":
|
|
data = req.json()
|
|
else:
|
|
return {
|
|
"data": "",
|
|
"resultado": "N",
|
|
"erro": _("String de pesquisa mal configurada"),
|
|
"comment": "",
|
|
}
|
|
|
|
for c in campos:
|
|
if isinstance(c, int):
|
|
if (len(data) - 1) < c:
|
|
return {
|
|
"data": "",
|
|
"resultado": "U",
|
|
"erro": _("Sem dados para verificação"),
|
|
"comment": _("Parece que nunca foi usado"),
|
|
}
|
|
data = data[c]
|
|
else:
|
|
if param_pesquisa[1] == "xml":
|
|
data = data.getElementsByTagName(c)
|
|
else:
|
|
data = data[c]
|
|
|
|
if param_pesquisa[1] == "xml":
|
|
data = data.firstChild.nodeValue
|
|
data = data[:10]
|
|
data = data.replace("/", "-")
|
|
return {
|
|
"data": data,
|
|
"resultado": "F",
|
|
"erro": "",
|
|
"comment": "",
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
"data": "",
|
|
"resultado": "I",
|
|
"erro": str(e),
|
|
"comment": _(
|
|
"Parece que não é um {tipo}".format(
|
|
tipo=self.tipo_servico.nome
|
|
)
|
|
),
|
|
}
|
|
|
|
if self.tipo_servico.string_pesquisa == "":
|
|
reset()
|
|
return
|
|
|
|
url = self.url
|
|
|
|
if not url:
|
|
reset()
|
|
self.erro_atualizacao = _("Serviço sem URL")
|
|
self.data_verificacao = timezone.localtime()
|
|
self.save()
|
|
return
|
|
|
|
if url[-1] != "/":
|
|
url += "/"
|
|
|
|
resultados = []
|
|
|
|
for string_pesquisa in self.tipo_servico.string_pesquisa.splitlines():
|
|
resultados.append(ultimo_uso(url, string_pesquisa))
|
|
|
|
data = max([r["data"] for r in resultados])
|
|
resultado = {r["resultado"] for r in resultados}
|
|
|
|
if "F" in resultado:
|
|
self.resultado_verificacao = "F"
|
|
else:
|
|
self.resultado_verificacao = resultado.pop()
|
|
|
|
if data == "":
|
|
# Nenhuma busca deu resultado, guardar log de erro
|
|
self.data_ultimo_uso = None
|
|
self.erro_atualizacao = "<br/>".join(
|
|
set(
|
|
[
|
|
f"{r['erro']} ({r['comment']})"
|
|
for r in resultados
|
|
if r["erro"] != "" and r["comment"] != ""
|
|
]
|
|
)
|
|
)
|
|
else:
|
|
# Atualiza a maior data de atualização
|
|
self.data_ultimo_uso = data[:10] # Apenas YYYY-MM-DD
|
|
self.erro_atualizacao = ""
|
|
|
|
self.data_verificacao = timezone.localtime()
|
|
self.save()
|
|
|
|
return
|
|
|
|
def __str__(self):
|
|
return f"{self.tipo_servico.nome} ({self.status_servico})"
|
|
|
|
def save(self, *args, **kwargs):
|
|
# Reter o objeto original para verificar mudanças
|
|
|
|
if self.id is not None:
|
|
original = Servico.objects.get(id=self.id)
|
|
|
|
if self.id is None:
|
|
# Novo serviço, email de ativação
|
|
subject = _("INTERLEGIS - Ativação de serviço %s") % (
|
|
self.tipo_servico.nome,
|
|
)
|
|
body = self.tipo_servico.template_email_ativa
|
|
elif (
|
|
self.data_desativacao is not None
|
|
and original.data_desativacao is None
|
|
):
|
|
# Serviço foi desativado. Email de desativação
|
|
subject = _("INTERLEGIS - Desativação de serviço %s") % (
|
|
self.tipo_servico.nome,
|
|
)
|
|
body = self.tipo_servico.template_email_desativa
|
|
elif (
|
|
self.tipo_servico != original.tipo_servico
|
|
or self.url != original.url
|
|
):
|
|
# Serviço foi alterado
|
|
subject = _("INTERLEGIS - Alteração de serviço %s") % (
|
|
self.tipo_servico.nome,
|
|
)
|
|
body = self.tipo_servico.template_email_altera
|
|
else:
|
|
# Salvar o Servico
|
|
super(Servico, self).save(*args, **kwargs)
|
|
return # sem enviar email
|
|
|
|
# Prepara e envia o email
|
|
body = body.replace("{url}", self.url).replace(
|
|
"{motivo}", self.motivo_desativacao
|
|
)
|
|
|
|
# send_mail(subject, body, DEFAULT_FROM_EMAIL, \
|
|
# (self.contato_tecnico.email,), fail_silently=False)
|
|
|
|
# Salvar o Servico
|
|
super(Servico, self).save(*args, **kwargs)
|
|
|
|
return
|
|
|
|
|
|
class LogServico(models.Model):
|
|
servico = models.ForeignKey(
|
|
Servico, on_delete=models.CASCADE, verbose_name=_("Serviço")
|
|
)
|
|
descricao = models.CharField(_("Breve descrição da ação"), max_length=60)
|
|
data = models.DateField(_("Data da ação"), default=timezone.localdate)
|
|
log = models.TextField(_("Log da ação"))
|
|
|
|
def __str__(self):
|
|
return f"{self.descricao} ({self.data})"
|
|
|
|
class Meta:
|
|
verbose_name = _("Log do serviço")
|
|
verbose_name_plural = _("Logs do serviço")
|
|
|
|
|
|
class CasaManifesta(models.Model):
|
|
casa_legislativa = models.OneToOneField(Orgao, on_delete=models.CASCADE)
|
|
data_manifestacao = models.DateTimeField(auto_now_add=True)
|
|
data_atualizacao = models.DateTimeField(auto_now=True)
|
|
informante = models.CharField(
|
|
_("Nome do informante"), max_length=100, blank=True
|
|
)
|
|
cargo = models.CharField(
|
|
_("Cargo do informante"), max_length=100, blank=True
|
|
)
|
|
email = models.EmailField(_("E-mail de contato"), blank=True)
|
|
|
|
|
|
class ServicoManifesto(models.Model):
|
|
casa_manifesta = models.ForeignKey(CasaManifesta, on_delete=models.CASCADE)
|
|
servico = models.ForeignKey(TipoServico, on_delete=models.CASCADE)
|
|
url = models.URLField(blank=True)
|
|
hospedagem_interlegis = models.BooleanField(
|
|
_("Hospedagem no Interlegis?"), default=False
|
|
)
|
|
|
|
class Meta:
|
|
unique_together = ("casa_manifesta", "servico")
|
|
|
|
|
|
class RegistroServico(models.Model):
|
|
produto = models.CharField(max_length=50)
|
|
versao = models.CharField(max_length=30)
|
|
url = models.URLField()
|
|
data_registro = models.DateTimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
verbose_name_plural = _("Registro de serviços")
|
|
|