diff --git a/etc/cron/atualiza_data_uso.py b/etc/cron/atualiza_data_uso.py new file mode 100644 index 0000000..4663a0a --- /dev/null +++ b/etc/cron/atualiza_data_uso.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Atualiza a data de último uso dos serviços SEIT realizados pelas Casas Legislativas +# Colocar no CRON - basta executar uma vez por dia +# + +import sys +from django.core.management import setup_environ + +# Produção +sys.path.insert(0, '/var/interlegis/sigi') +sys.path.insert(0, '/var/interlegis/sigi/sigi') + +# Dev +import os +BASE_DIR = os.path.abspath(os.path.dirname(__file__) + '../..') +PROJECT_DIR = BASE_DIR + '/sigi' +print BASE_DIR, PROJECT_DIR +sys.path.insert(0, BASE_DIR) +sys.path.insert(0, PROJECT_DIR) + +# Faça! +from sigi import settings +setup_environ(settings) + +from sigi.apps.servicos.models import Servico + +queryset = Servico.objects.exclude(url="").exclude(tipo_servico__string_pesquisa="") +for obj in queryset: + obj.atualiza_data_uso() + print obj.url, obj.data_ultimo_uso, obj.erro_atualizacao \ No newline at end of file diff --git a/sigi/apps/casas/models.py b/sigi/apps/casas/models.py index 13f658b..71ef475 100644 --- a/sigi/apps/casas/models.py +++ b/sigi/apps/casas/models.py @@ -6,7 +6,7 @@ from sigi.apps.utils import SearchField from datetime import datetime import random from unicodedata import normalize -from apps.contatos.models import Municipio +from sigi.apps.contatos.models import Municipio class TipoCasaLegislativa(models.Model): """ Modelo para representar o tipo da Casa Legislativa diff --git a/sigi/apps/servicos/admin.py b/sigi/apps/servicos/admin.py index 8bb32f6..d890558 100644 --- a/sigi/apps/servicos/admin.py +++ b/sigi/apps/servicos/admin.py @@ -48,7 +48,9 @@ class TipoServicoAdmin(admin.ModelAdmin): class ServicoAdmin(admin.ModelAdmin): form = ServicoFormAdmin - list_display = ('casa_legislativa','getUf', 'tipo_servico', 'hospedagem_interlegis', 'data_ativacao', 'data_desativacao', 'getUrl') + actions = ['calcular_data_uso',] + list_display = ('casa_legislativa','getUf', 'tipo_servico', 'hospedagem_interlegis', 'data_ativacao', 'data_desativacao', + 'getUrl', 'data_ultimo_uso', 'erro_atualizacao') fieldsets = (( None, { 'fields': ('casa_legislativa', 'data_ativacao',) }), @@ -62,10 +64,9 @@ class ServicoAdmin(admin.ModelAdmin): 'fields': ('data_alteracao', 'data_desativacao', 'motivo_desativacao',) })) readonly_fields = ('casa_legislativa', 'data_ativacao', 'data_alteracao') - list_filter = ('tipo_servico', 'hospedagem_interlegis', 'casa_legislativa') + list_filter = ('tipo_servico', 'hospedagem_interlegis', 'data_ultimo_uso', 'casa_legislativa', ) list_display_links = [] ordering = ('casa_legislativa__municipio__uf', 'casa_legislativa', 'tipo_servico',) - actions = None inlines = (LogServicoInline,) def getUf(self, obj): @@ -77,8 +78,22 @@ class ServicoAdmin(admin.ModelAdmin): return u'%s' % (obj.url, obj.url) getUrl.short_description = 'Url' getUrl.allow_tags = True - + def calcular_data_uso(self, request, queryset): + for servico in queryset: + servico.atualiza_data_uso() + self.message_user(request, "Atualização concluída. Os sites que não responderam foram deixados com a data em branco" ) + return HttpResponseRedirect('.') + calcular_data_uso.short_description = u"Atualizar a data do último uso do(s) serviço(s)" + + def get_actions(self, request): + from django.utils.datastructures import SortedDict + actions = [self.get_action(action) for action in self.actions] + actions = filter(None, actions) + actions.sort(lambda a,b: cmp(a[2].lower(), b[2].lower())) + actions = SortedDict([ (name, (func, name, desc)) for func, name, desc in actions ]) + return actions + def lookup_allowed(self, lookup, value): return super(ServicoAdmin, self).lookup_allowed(lookup, value) or \ lookup in ['casa_legislativa__municipio__uf__codigo_ibge__exact'] diff --git a/sigi/apps/servicos/models.py b/sigi/apps/servicos/models.py index a4d7ba0..83c4718 100644 --- a/sigi/apps/servicos/models.py +++ b/sigi/apps/servicos/models.py @@ -6,14 +6,16 @@ from django.core.mail import send_mail from sigi.settings import DEFAULT_FROM_EMAIL class TipoServico(models.Model): - email_help = '''Use:
+ email_help = u'''Use:
{url} para incluir a URL do serviço,
{senha} para incluir a senha inicial do serviço''' - nome = models.CharField('Nome', max_length=60) - sigla = models.CharField('Sigla', max_length='12') - 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 + '
{motivo} para incluir o motivo da desativação do serviço', blank=True) + nome = models.CharField(u'Nome', max_length=60) + sigla = models.CharField(u'Sigla', max_length='12') + string_pesquisa = models.CharField(u'String de pesquisa', blank=True, max_length=200, + help_text=u'Sufixo para pesquisa RSS para averiguar a data da última atualização do serviço') + template_email_ativa = models.TextField(u'Template de email de ativação', help_text = email_help, blank=True) + template_email_altera = models.TextField(u'Template de email de alteração', help_text = email_help, blank=True) + template_email_desativa = models.TextField(u'Template de email de desativação', help_text = email_help + u'
{motivo} para incluir o motivo da desativação do serviço', blank=True) @property def qtde_casas_atendidas(self): @@ -21,29 +23,81 @@ class TipoServico(models.Model): return self.servico_set.filter(data_desativacao=None).count() class Meta: - verbose_name = 'Tipo de serviço' - verbose_name_plural = 'Tipos de serviço' + verbose_name = u'Tipo de serviço' + verbose_name_plural = u'Tipos de serviço' def __unicode__(self): return self.nome; class Servico(models.Model): - casa_legislativa = models.ForeignKey(CasaLegislativa, verbose_name='Casa legislativa') - tipo_servico = models.ForeignKey(TipoServico, verbose_name='Tipo de serviço') - contato_tecnico = models.ForeignKey(Funcionario, verbose_name='Contato técnico', related_name='contato_tecnico') - contato_administrativo = models.ForeignKey(Funcionario, verbose_name='Contato administrativo', related_name='contato_administrativo') - url = models.URLField('URL do serviço', verify_exists=False, blank=True) - hospedagem_interlegis = models.BooleanField('Hospedagem no Interlegis?') - nome_servidor = models.CharField('Hospedado em', max_length=60, blank=True, help_text='Se hospedado no Interlegis, informe o nome do servidor.
Senão, informe o nome do provedor de serviços.') - porta_servico = models.PositiveSmallIntegerField('Porta de serviço (instância)', blank=True, null=True) - senha_inicial = models.CharField('Senha inicial', max_length=33, blank=True) - data_ativacao = models.DateField('Data de ativação', default=date.today) - 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) + casa_legislativa = models.ForeignKey(CasaLegislativa, verbose_name=u'Casa legislativa') + tipo_servico = models.ForeignKey(TipoServico, verbose_name=u'Tipo de serviço') + contato_tecnico = models.ForeignKey(Funcionario, verbose_name=u'Contato técnico', related_name='contato_tecnico') + contato_administrativo = models.ForeignKey(Funcionario, verbose_name=u'Contato administrativo', related_name='contato_administrativo') + url = models.URLField(u'URL do serviço', verify_exists=False, blank=True) + hospedagem_interlegis = models.BooleanField(u'Hospedagem no Interlegis?') + nome_servidor = models.CharField(u'Hospedado em', max_length=60, blank=True, + help_text=u'Se hospedado no Interlegis, informe o nome do servidor.
Senão, informe o nome do provedor de serviços.') + porta_servico = models.PositiveSmallIntegerField(u'Porta de serviço (instância)', blank=True, null=True) + senha_inicial = models.CharField(u'Senha inicial', max_length=33, blank=True) + data_ativacao = models.DateField(u'Data de ativação', default=date.today) + data_alteracao = models.DateField(u'Data da última alteração', blank=True, null=True, auto_now=True) + data_desativacao = models.DateField(u'Data de desativação', blank=True, null=True) + motivo_desativacao = models.TextField(u'Motivo da desativação', blank=True) + data_ultimo_uso = models.DateField(u'Data da última utilização', blank=True, null=True, + help_text=u'Data em que o serviço foi utilizado pela Casa Legislativa pela última vez
NÃO É ATUALIZADO AUTOMATICAMENTE!') + erro_atualizacao = models.CharField(u"Erro na atualização", blank=True, max_length=200, + help_text=u"Erro ocorrido na última tentativa de atualizar a data de último acesso") casa_legislativa.casa_uf_filter = True + def atualiza_data_uso(self): + def reset(erro=u""): + if self.data_ultimo_uso is None and not erro: + return + self.data_ultimo_uso = None + self.erro_atualizacao = erro + self.save() + return + + if self.tipo_servico.string_pesquisa == "": + reset() + return + + url = self.url + + if not url: + reset() + return + + if url[-1] != '/': + url += '/' + url += self.tipo_servico.string_pesquisa + + import urllib2 + from xml.dom.minidom import parseString + + try: + try: # Tentar conxão sem proxy + req = urllib2.urlopen(url=url, timeout=5) + except: # Tentar com proxy + proxy = urllib2.ProxyHandler() + opener = urllib2.build_opener(proxy) + req = opener.open(fullurl=url, timeout=5) + + rss = req.read() + xml = parseString(rss) + items = xml.getElementsByTagName('item') + first_item = items[0] + date_list = first_item.getElementsByTagName('dc:date') + date_item = date_list[0] + date_text = date_item.firstChild.nodeValue + self.data_ultimo_uso = date_text[:10] # Apenas YYYY-MM-DD + self.erro_atualizacao = "" + self.save() + except Exception as e: + reset(erro=e.message) + def __unicode__(self): return "%s (%s)" % (self.tipo_servico.nome, 'ativo' if self.data_desativacao is None else 'Desativado')