diff --git a/sigi/apps/servicos/jobs/daily/sincroniza_rancher.py b/sigi/apps/servicos/jobs/daily/sincroniza_rancher.py index bb99d6c..05a1d59 100644 --- a/sigi/apps/servicos/jobs/daily/sincroniza_rancher.py +++ b/sigi/apps/servicos/jobs/daily/sincroniza_rancher.py @@ -20,44 +20,52 @@ class Job(DailyJob): _infos = {} def execute(self): - print( - _( - "Sincroniza os serviços SEIT a partir da infraestrutura." - f" Início: {datetime.datetime.now(): %d/%m/%Y %H:%M:%S}" + try: + print( + _( + "Sincroniza os serviços SEIT a partir da infraestrutura." + f" Início: {datetime.datetime.now(): %d/%m/%Y %H:%M:%S}" + ) ) - ) - self._nomes_gerados = { - generate_instance_name(o): o - for o in Orgao.objects.filter(tipo__legislativo=True) - } - print( - _(f"\t{len(self._nomes_gerados)} órgãos que podem ter instâncias.") - ) - - for tipo in TipoServico.objects.filter(modo="H").exclude( - tipo_rancher="" - ): + self._nomes_gerados = { + generate_instance_name(o): o + for o in Orgao.objects.filter(tipo__legislativo=True) + } print( _( - f"\tProcessando {tipo.nome}." - f" Início: {datetime.datetime.now():%H:%M:%S}." - ), - end="", + f"\t{len(self._nomes_gerados)} órgãos que podem ter instâncias." + ) ) - self.process(tipo) - print(_(f" Término: {datetime.datetime.now():%H:%M:%S}.")) - try: - shutil.rmtree(settings.HOSPEDAGEM_PATH) - except Exception as e: - print(_(f"Erro ao excluir diretório {settings.HOSPEDAGEM_PATH}")) + for tipo in TipoServico.objects.filter(modo="H").exclude( + tipo_rancher="" + ): + print( + _( + f"\tProcessando {tipo.nome}." + f" Início: {datetime.datetime.now():%H:%M:%S}." + ), + end="", + ) + self.process(tipo) + print(_(f" Término: {datetime.datetime.now():%H:%M:%S}.")) - print("Relatório final:\n================") - self.report() + try: + shutil.rmtree(settings.HOSPEDAGEM_PATH) + except Exception as e: + print( + _(f"Erro ao excluir diretório {settings.HOSPEDAGEM_PATH}") + ) - print(_(f"Término: {datetime.datetime.now(): %d/%m/%Y %H:%M:%S}")) + print("Relatório final:\n================") + self.report() + + print(_(f"Término: {datetime.datetime.now(): %d/%m/%Y %H:%M:%S}")) + except Exception as e: + self.report_error(e) def process(self, tipo): + self.nomeia_instancias(tipo) NAO_CONSTA = "*não-consta-no-rancher*" self._errors[tipo] = [] self._infos[tipo] = [] @@ -122,7 +130,7 @@ class Job(DailyJob): ) encontrados += 1 except Servico.MultipleObjectsReturned: - self._errors.append( + self._errors[tipo].append( _( f"Existe mais de um registro ativo da instância {iname}" f" de {tipo}." @@ -195,6 +203,15 @@ class Job(DailyJob): _(f"{desativados} {tipo.nome} desativados no SIGI") ) + # Preenche o nome das instâncias com o nome padrão para os serviços com + # este campo em branco + def nomeia_instancias(self, tipo): + for s in Servico.objects.filter( + tipo_servico=tipo, data_desativacao=None, instancia="" + ): + s.instancia = generate_instance_name(s.casa_legislativa) + s.save() + def report(self): rst = render_to_string( "servicos/emails/report_sincroniza_rancher.rst", @@ -219,3 +236,30 @@ class Job(DailyJob): fail_silently=True, ) print(rst) + + def report_error(self, error): + import traceback + + rst = render_to_string( + "emails/report_error.rst", + { + "title": _("Resultado da sincronização do SIGI com o Rancher"), + "process_name": self.help, + "traceback": traceback.format_exception(error), + }, + ) + html = docutils.core.publish_string( + rst, + writer_name="html5", + settings_overrides={ + "input_encoding": "unicode", + "output_encoding": "unicode", + }, + ) + mail_admins( + subject=self.help, + message=rst, + html_message=html, + fail_silently=True, + ) + print(rst) diff --git a/sigi/apps/servicos/migrations/0021_remove_servico_unique_instance_and_more.py b/sigi/apps/servicos/migrations/0021_remove_servico_unique_instance_and_more.py new file mode 100644 index 0000000..677501c --- /dev/null +++ b/sigi/apps/servicos/migrations/0021_remove_servico_unique_instance_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 4.1.4 on 2023-01-24 14:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("servicos", "0020_servico_apps"), + ] + + operations = [ + migrations.RemoveConstraint( + model_name="servico", + name="unique_instance", + ), + migrations.AddConstraint( + model_name="servico", + constraint=models.UniqueConstraint( + condition=models.Q( + ("data_desativacao", None), + models.Q(("instancia", ""), _negated=True), + ), + fields=("tipo_servico", "instancia", "url"), + name="unique_instance", + ), + ), + ] diff --git a/sigi/apps/servicos/migrations/0022_atualiza_mail_leg.py b/sigi/apps/servicos/migrations/0022_atualiza_mail_leg.py new file mode 100644 index 0000000..2d87153 --- /dev/null +++ b/sigi/apps/servicos/migrations/0022_atualiza_mail_leg.py @@ -0,0 +1,34 @@ +# Generated by Django 4.1.5 on 2023-01-25 14:40 + +from django.db import migrations + + +def mailleg_fw(apps, schema_editor): + TipoServico = apps.get_model("servicos", "TipoServico") + tipo = TipoServico.objects.get(sigla__icontains="mail") + tipo.tipo_rancher = "emailleg" + tipo.arquivo_rancher = "mail.json" + tipo.spec_rancher = "mail" + tipo.prefixo_padrao = "correioadm" + tipo.save() + + +def mailleg_rw(apps, schema_editor): + TipoServico = apps.get_model("servicos", "TipoServico") + tipo = TipoServico.objects.get(sigla__icontains="mail") + tipo.tipo_rancher = "" + tipo.arquivo_rancher = "" + tipo.spec_rancher = "" + tipo.prefixo_padrao = "" + tipo.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ("servicos", "0021_remove_servico_unique_instance_and_more"), + ] + + operations = [ + migrations.RunPython(mailleg_fw, mailleg_rw), + ] diff --git a/sigi/apps/servicos/models.py b/sigi/apps/servicos/models.py index 7e5e5dc..75831ee 100644 --- a/sigi/apps/servicos/models.py +++ b/sigi/apps/servicos/models.py @@ -1,5 +1,6 @@ from django.utils import timezone from django.db import models +from django.db.models import Q from sigi.apps.casas.models import Orgao, Funcionario from django.utils.translation import gettext as _ @@ -301,7 +302,8 @@ class Servico(models.Model): verbose_name_plural = _("serviços SEIT") constraints = [ models.UniqueConstraint( - fields=["tipo_servico", "instancia", "data_desativacao"], + fields=["tipo_servico", "instancia", "url"], + condition=Q(data_desativacao=None) & ~Q(instancia=""), name="unique_instance", ) ] diff --git a/sigi/templates/emails/report_error.rst b/sigi/templates/emails/report_error.rst new file mode 100644 index 0000000..a01f501 --- /dev/null +++ b/sigi/templates/emails/report_error.rst @@ -0,0 +1,16 @@ +{% extends 'emails/base_email.rst' %} +{% load i18n %} + +{% block content %} +{% blocktrans %}UM ERRO OCORREU NO PROCESSO DE IMPORTAÇÃO DE {{ process_name }}{% endblocktrans %} + +{% trans "VERIFIQUE O LOG DO SIGI PARA MAIORES DETALHES" %} + +* {% trans "Data/hora de execução" %}: {% now 'SHORT_DATETIME_FORMAT' %} + +::{% autoescape off %}{% for error_row in traceback %} + {{ error_row }} +{% endfor %} +{% endautoescape %} + +{% endblock content %} \ No newline at end of file