diff --git a/requirements/requirements.txt b/requirements/requirements.txt
index abfd1d4..ab6351f 100644
--- a/requirements/requirements.txt
+++ b/requirements/requirements.txt
@@ -21,3 +21,4 @@ requests==2.8.1
six==1.10.0
djangorestframework==2.4.8
django-ipware==1.1.6
+django-tinymce==2.6.0
\ No newline at end of file
diff --git a/sigi/apps/casas/admin.py b/sigi/apps/casas/admin.py
index c09d079..3685f93 100644
--- a/sigi/apps/casas/admin.py
+++ b/sigi/apps/casas/admin.py
@@ -1,11 +1,13 @@
# -*- coding: utf-8 -*-
+from unicodedata import name
from django.contrib import admin
from django.contrib.contenttypes import generic
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.utils.translation import ugettext as _
+#from geraldo.site.newsite.django_1_0.django.forms import extras
from image_cropping import ImageCroppingMixin
from sigi.apps.casas.forms import OrgaoForm
@@ -50,7 +52,31 @@ class PresidenteInline(admin.StackedInline):
extra = 1
max_num = 1
verbose_name_plural = _(u'Presidente')
+ def get_queryset(self, request):
+ return (self.model.objects.exclude(desativado=True)
+ .extra(select={'ult_null': 'ult_alteracao is null'})
+ .order_by('ult_null', '-ult_alteracao')
+ # A função extra foi usada para quando existir um registro com o campo igual a null não aparecer na frente dos mais novos
+ )
+class ContatoInterlegisInline(admin.StackedInline):
+ model = Funcionario
+ fields = ('nome', 'sexo', 'data_nascimento', 'nota', 'email', 'cargo',
+ 'funcao', 'setor', 'tempo_de_servico', 'ult_alteracao',
+ 'endereco', 'municipio', 'bairro', 'cep', 'redes_sociais',
+ 'desativado', 'observacoes')
+ raw_id_fields = ('municipio',)
+ readonly_fields = ('ult_alteracao',)
+ extra = 1
+ inlines = (TelefonesInline,)
+ verbose_name_plural = _(u'Contato(s) Interlegis Vigente(s)')
+ def get_queryset(self, request):
+ return (self.model.objects.filter(setor='contato_interlegis')
+ .extra(select={'ult_null': 'ult_alteracao is null'}).order_by('-ult_alteracao')
+ )
+ def get_extra(self, request, obj=None , **kwargs):
+ extra = 0
+ return extra
class FuncionariosInline(admin.StackedInline):
model = Funcionario
@@ -59,6 +85,7 @@ class FuncionariosInline(admin.StackedInline):
'endereco', 'municipio', 'bairro', 'cep', 'redes_sociais',
'desativado', 'observacoes')
raw_id_fields = ('municipio',)
+
# fieldsets = ((None, {
# 'fields': (
# ('nome', 'sexo', 'data_nascimento'),
@@ -74,22 +101,22 @@ class FuncionariosInline(admin.StackedInline):
readonly_fields = ('ult_alteracao',)
extra = 1
inlines = (TelefonesInline,)
+ verbose_name_plural = _(u'Outros Contatos da Casa')
def get_queryset(self, request):
- return (self.model.objects.exclude(
- cargo='Presidente').exclude(desativado=True)
+ return (self.model.objects.exclude(cargo='Presidente',)
+ .exclude(desativado=True).extra(select={'ult_null': 'ult_alteracao is null'})
+ .order_by('ult_null', '-ult_alteracao')
+ # A função extra foi usada para quando existir um registro com o campo igual a null não aparecer na frente dos mais novos
)
-
class ConveniosInline(admin.TabularInline):
model = Convenio
fieldsets = (
(None, {'fields': (
('link_sigad', 'status_convenio', 'num_convenio',
'projeto', 'observacao'),
- ('data_adesao', 'data_retorno_assinatura', 'data_termo_aceite',
- 'data_pub_diario', 'data_devolucao_via', 'data_postagem_correio'),
- ('data_devolucao_sem_assinatura', 'data_retorno_sem_assinatura',),
+ ('data_retorno_assinatura', 'data_pub_diario',),
('get_anexos',),
('link_convenio',),
)}),
@@ -103,6 +130,7 @@ class ConveniosInline(admin.TabularInline):
extra = 0
can_delete = False
template = 'admin/casas/convenios_inline.html'
+ ordering = ('-data_retorno_assinatura',)
def has_add_permission(self, request):
return False
@@ -210,10 +238,10 @@ class ServicoInline(admin.TabularInline):
model = Servico
fields = ('link_url', 'contato_tecnico', 'contato_administrativo',
'hospedagem_interlegis', 'data_ativacao', 'data_alteracao',
- 'data_desativacao')
+ 'data_desativacao', 'link_servico')
readonly_fields = ['link_url', 'contato_tecnico', 'contato_administrativo',
'hospedagem_interlegis', 'data_ativacao',
- 'data_alteracao', 'data_desativacao']
+ 'data_alteracao', 'data_desativacao', 'link_servico']
extra = 0
max_num = 0
can_delete = False
@@ -225,6 +253,24 @@ class ServicoInline(admin.TabularInline):
link_url.short_description = _(u'URL do serviço')
link_url.allow_tags = True
+ ordering = ('-data_alteracao',)
+
+ def link_servico(self, obj):
+ if obj.pk is None:
+ return ""
+ url = reverse('admin:%s_%s_change' % (obj._meta.app_label, obj._meta.module_name), args=[obj.pk])
+ url = url + '?_popup=1'
+ return """
+
+ Editar
+ """ % (obj.pk, obj.pk, url)
+
+ link_servico.short_description = _(u'Editar Serviço')
+ link_servico.allow_tags = True
+
+ def has_add_permission(self, request):
+ return False
+
# class PlanoDiretorInline(admin.TabularInline):
# model = PlanoDiretor
@@ -237,6 +283,8 @@ class OcorrenciaInline(admin.TabularInline):
can_delete = False
template = 'admin/casas/ocorrencia_inline.html'
+ ordering = ('-data_modificacao',)
+
def link_editar(self, obj):
if obj.pk is None:
return ""
@@ -264,7 +312,7 @@ class ConvenioFilter(admin.SimpleListFilter):
def lookups(self, request, model_admin):
return (
('SC', _(u"Sem nenhum convênio")),
- ('CC', _(u"Com algum convênio"))
+ ('CC', _(u"Com algum convênio")),
) + tuple([(p.pk, p.sigla) for p in Projeto.objects.all()])
def queryset(self, request, queryset):
@@ -278,6 +326,19 @@ class ConvenioFilter(admin.SimpleListFilter):
return queryset.distinct('municipio__uf__nome', 'nome')
+class ExcluirConvenioFilter(admin.SimpleListFilter):
+ title=_(u"Excluir convênio da pesquisa")
+ parameter_name = 'excluir_convenio'
+
+ def lookups(self, request, model_admin):
+ return tuple([(p.pk, p.sigla) for p in Projeto.objects.all()])
+
+ def queryset(self, request, queryset):
+ if (self.value() is None):
+ return queryset
+ else:
+ queryset = queryset.exclude(convenio__projeto_id=self.value()).distinct('municipio__uf__nome', 'nome')
+ return queryset
class ServicoFilter(admin.SimpleListFilter):
title = _(u"Serviço")
@@ -313,17 +374,34 @@ class ServicoFilter(admin.SimpleListFilter):
return queryset.distinct('municipio__uf__nome', 'nome')
+class ServicoAtivoFilter(admin.SimpleListFilter):
+ title = _(u"Serviço ativo")
+ parameter_name = 'ativo'
+
+ def lookups(self, request, model_admin):
+ return (
+ ('ativo', _(u"Ativo")),
+ ('desativado', _(u"Desativado")),
+ )
+
+ def queryset(self, request, queryset):
+ if self.value() is not None:
+ if self.value() == 'ativo':
+ queryset = queryset.filter(servico__data_desativacao__isnull=True)
+ else:
+ queryset = queryset.filter(servico__data_desativacao__isnull=False)
+ return queryset
@admin.register(Orgao)
class OrgaoAdmin(ImageCroppingMixin, BaseModelAdmin):
form = OrgaoForm
actions = ['adicionar_casas', ]
- inlines = (TelefonesInline, PresidenteInline, FuncionariosInline,
+ inlines = (TelefonesInline, PresidenteInline, ContatoInterlegisInline, FuncionariosInline,
ConveniosInline, ServicoInline, OcorrenciaInline,)
list_display = ('id', 'sigla', 'nome', 'get_uf', 'get_gerentes', 'get_convenios',
'get_servicos')
list_display_links = ('sigla', 'nome',)
list_filter = ('tipo', ('gerentes_interlegis', GerentesInterlegisFilter),
- 'municipio__uf__nome', ConvenioFilter, ServicoFilter,
+ 'municipio__uf__nome', ConvenioFilter, ServicoAtivoFilter, ExcluirConvenioFilter, ServicoFilter,
'inclusao_digital',)
ordering = ('municipio__uf__nome', 'nome')
queryset = queryset_ascii
diff --git a/sigi/apps/casas/models.py b/sigi/apps/casas/models.py
index 29c93e8..1ca27b7 100644
--- a/sigi/apps/casas/models.py
+++ b/sigi/apps/casas/models.py
@@ -194,6 +194,19 @@ class Orgao(models.Model):
return self.funcionario_set.get(setor='presidente')
except Funcionario.DoesNotExist:
return None
+
+ @property
+ def contato_interlegis(self):
+ """ Link para acessar diretamente o contato do presidente da casa
+ Util para relatorios antigos
+ """
+ try:
+ if self.funcionario_set.filter(setor='contato_interlegis').count() > 1:
+ return self.funcionario_set.filter(setor='contato_interlegis')[0]
+ else:
+ return self.funcionario_set.get(setor='contato_interlegis')
+ except Funcionario.DoesNotExist:
+ return None
@property
def total_parlamentares(self):
diff --git a/sigi/apps/casas/views.py b/sigi/apps/casas/views.py
index 694e84b..741786d 100644
--- a/sigi/apps/casas/views.py
+++ b/sigi/apps/casas/views.py
@@ -2,6 +2,9 @@
import csv
from datetime import datetime
from functools import reduce
+
+from django.contrib import messages
+from sigi.apps.utils import to_ascii
from geraldo.generators import PDFGenerator
from django.conf import settings
@@ -257,9 +260,10 @@ class importa_casas(View):
for reg in reader:
self.total_registros += 1
reg[self.ERROS] = []
+ nome_orgao = to_ascii(reg[self.MUNICIPIO])
orgao = Orgao.objects.filter(
tipo__sigla=reg[self.TIPO],
- municipio__nome=reg[self.MUNICIPIO],
+ municipio__search_text__icontains=nome_orgao,
municipio__uf__sigla=reg[self.UF]
)
if orgao.count() == 0:
@@ -444,7 +448,8 @@ def visualizar_carrinho(request):
def excluir_carrinho(request):
if 'carrinho_casas' in request.session:
del request.session['carrinho_casas']
- return HttpResponseRedirect('.')
+ messages.info(request, u'O carrinho foi esvaziado')
+ return HttpResponseRedirect('../../')
@login_required
diff --git a/sigi/apps/convenios/admin.py b/sigi/apps/convenios/admin.py
index ce5a6fe..971dd1e 100644
--- a/sigi/apps/convenios/admin.py
+++ b/sigi/apps/convenios/admin.py
@@ -6,7 +6,8 @@ from geraldo.generators import PDFGenerator
from sigi.apps.convenios.models import (Projeto, StatusConvenio,
TipoSolicitacao, Convenio,
- EquipamentoPrevisto, Anexo, Tramitacao)
+ EquipamentoPrevisto, Anexo, Tramitacao,
+ Gescon)
from sigi.apps.convenios.reports import ConvenioReport
from sigi.apps.convenios.views import adicionar_convenios_carrinho
from sigi.apps.utils import queryset_ascii
@@ -51,35 +52,37 @@ class ConvenioAdmin(BaseModelAdmin):
'projeto', 'data_sigi',)}
),
(_(u"Acompanhamento no gabinete"),
- {'fields': ('data_solicitacao', 'data_sigad', 'tipo_solicitacao',
- 'status', 'acompanha', 'observacao',)}
+ {'fields': ('data_solicitacao', 'data_sigad', 'observacao',)}
),
(_(u"Gestão do convênio"),
{'fields': ('servico_gestao', 'servidor_gestao',)}
),
(_(u'Datas'),
- {'fields': ('data_retorno_assinatura', 'duracao',
- 'data_pub_diario',)}
+ {'fields': ('data_retorno_assinatura', 'data_termino_vigencia',
+ 'data_pub_diario',)}
),
+ (_(u'Gescon'),
+ {'fields': ('atualizacao_gescon', 'observacao_gescon', 'link_gescon')}
+ ),
)
- readonly_fields = ('data_sigi',)
+ readonly_fields = ('data_sigi', 'atualizacao_gescon', 'observacao_gescon', 'link_gescon')
actions = ['adicionar_convenios']
inlines = (AnexosInline,)
- list_display = ('num_convenio', 'casa_legislativa', 'get_uf',
+ list_display = ('num_convenio', 'projeto','casa_legislativa', 'get_uf',
'status_convenio', 'link_sigad', 'data_retorno_assinatura',
- 'duracao', 'projeto', 'status', 'acompanha',)
+ 'data_termino_vigencia',)
list_display_links = ('num_convenio', 'casa_legislativa',)
- list_filter = ('status', ('acompanha', AcompanhaFilter),
- ('casa_legislativa__gerentes_interlegis',
+ list_filter = (('casa_legislativa__gerentes_interlegis',
GerentesInterlegisFilter), 'projeto',
'casa_legislativa__tipo', 'conveniada','equipada',
'casa_legislativa__municipio__uf',)
#date_hierarchy = 'data_adesao'
- ordering = ('casa_legislativa__tipo__sigla', 'casa_legislativa__municipio__uf', 'casa_legislativa')
+ ordering = ('casa_legislativa', '-data_retorno_assinatura')
raw_id_fields = ('casa_legislativa',)
get_queryset = queryset_ascii
- search_fields = ('id', 'search_text', # 'casa_legislativa__nome',
- 'num_processo_sf', 'num_convenio')
+ search_fields = ('id', 'casa_legislativa__search_text',
+ 'casa_legislativa__sigla', 'num_processo_sf',
+ 'num_convenio')
def get_uf(self, obj):
return obj.casa_legislativa.municipio.uf.sigla
@@ -112,6 +115,16 @@ class ConvenioAdmin(BaseModelAdmin):
link_sigad.short_description = _("Processo no Senado")
link_sigad.allow_tags = True
+ def link_gescon(self, obj):
+ if not obj.id_contrato_gescon:
+ return u""
+ return (
+ u"https://adm.senado.gov.br/"
+ u"gestao-contratos/api/{id}").format(id=obj.id_contrato_gescon)
+ link_gescon.short_description = _("Download MINUTA ASSINADA do Gescon")
+ link_gescon.allow_tags = True
+
def changelist_view(self, request, extra_context=None):
from sigi.apps.convenios.views import normaliza_data
request.GET._mutable = True
@@ -172,8 +185,13 @@ class EquipamentoPrevistoAdmin(BaseModelAdmin):
search_fields = ('convenio__id', 'equipamento__fabricante__nome',
'equipamento__modelo__modelo', 'equipamento__modelo__tipo__tipo')
+@admin.register(Gescon)
+class GesconAdmin(admin.ModelAdmin):
+ list_display = ('url_gescon', 'email', 'ultima_importacao')
+ readonly_fields = ('ultima_importacao',)
+
admin.site.register(Projeto)
admin.site.register(StatusConvenio)
admin.site.register(TipoSolicitacao)
admin.site.register(Convenio, ConvenioAdmin)
-admin.site.register(EquipamentoPrevisto, EquipamentoPrevistoAdmin)
+admin.site.register(EquipamentoPrevisto, EquipamentoPrevistoAdmin)
\ No newline at end of file
diff --git a/sigi/apps/convenios/management/commands/duracao_act.py b/sigi/apps/convenios/management/commands/duracao_act.py
deleted file mode 100644
index 2144582..0000000
--- a/sigi/apps/convenios/management/commands/duracao_act.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# sigi.apps.casas.management.commands.importa_gerentes
-#
-# Copyright (c) 2015 by Interlegis
-#
-# GNU General Public License (GPL)
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
-
-from django.core.management.base import BaseCommand, CommandError
-from sigi.apps.convenios.models import Projeto, Convenio
-
-class Command(BaseCommand):
- help = u"""Define a duração de todos os ACT para 60 meses.
- * A sigla do Projeto precisa ser ACT;
- * O campo duracao precisa estar em branco.
- """
-
- def handle(self, *args, **options):
- self.stdout.write(u"Atualizando ACTs... ")
- act = Projeto.objects.get(sigla='ACT')
- for conv in Convenio.objects.filter(projeto=act, duracao=None):
- conv.duracao = 60
- conv.save()
- self.stdout.write(u"\tACT {sigad} da Casa {casa} atualizado".format(
- sigad=conv.num_processo_sf, casa=conv.casa_legislativa.nome
- ))
- self.stdout.write(u"Pronto!")
diff --git a/sigi/apps/convenios/migrations/0010_auto_20210819_0833.py b/sigi/apps/convenios/migrations/0010_auto_20210819_0833.py
new file mode 100644
index 0000000..e1827de
--- /dev/null
+++ b/sigi/apps/convenios/migrations/0010_auto_20210819_0833.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('convenios', '0009_auto_20210611_0946'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='convenio',
+ name='data_retorno_assinatura',
+ field=models.DateField(help_text='Conv\xeanio firmado.', null=True, verbose_name='data in\xedcio vig\xeancia', blank=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/sigi/apps/convenios/migrations/0011_convenio_data_termino_vigencia.py b/sigi/apps/convenios/migrations/0011_convenio_data_termino_vigencia.py
new file mode 100644
index 0000000..c5065c1
--- /dev/null
+++ b/sigi/apps/convenios/migrations/0011_convenio_data_termino_vigencia.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('convenios', '0010_auto_20210819_0833'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='convenio',
+ name='data_termino_vigencia',
+ field=models.DateField(help_text='T\xe9rmino da vig\xeancia do conv\xeanio.', null=True, verbose_name='Data t\xe9rmino vig\xeancia', blank=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/sigi/apps/convenios/migrations/0012_auto_20210831_0844.py b/sigi/apps/convenios/migrations/0012_auto_20210831_0844.py
new file mode 100644
index 0000000..b4e2692
--- /dev/null
+++ b/sigi/apps/convenios/migrations/0012_auto_20210831_0844.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+from datetime import date
+from django.db import models, migrations
+
+def migra_data_termino_vigencia(apps, schema_editor):
+ Convenio = apps.get_model('convenios', 'Convenio')
+
+ for c in Convenio.objects.all():
+ if (c.data_retorno_assinatura is None or c.duracao is None):
+ continue
+
+ ano = c.data_retorno_assinatura.year + int(c.duracao / 12)
+ mes = int(c.data_retorno_assinatura.month + int(c.duracao % 12))
+ if mes > 12:
+ ano = ano + 1
+ mes = mes - 12
+ dia = c.data_retorno_assinatura.day
+
+ while True:
+ try:
+ data_fim = date(year=ano, month=mes,day=dia)
+ break
+ except:
+ dia = dia - 1
+
+ c.data_termino_vigencia = data_fim
+ c.save()
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('convenios', '0011_convenio_data_termino_vigencia'),
+ ]
+
+ operations = [
+ migrations.RunPython(migra_data_termino_vigencia),
+ ]
diff --git a/sigi/apps/convenios/migrations/0013_remove_convenio_duracao.py b/sigi/apps/convenios/migrations/0013_remove_convenio_duracao.py
new file mode 100644
index 0000000..bcc66bc
--- /dev/null
+++ b/sigi/apps/convenios/migrations/0013_remove_convenio_duracao.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('convenios', '0012_auto_20210831_0844'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='convenio',
+ name='duracao',
+ ),
+ ]
diff --git a/sigi/apps/convenios/migrations/0014_gescon.py b/sigi/apps/convenios/migrations/0014_gescon.py
new file mode 100644
index 0000000..7fe216c
--- /dev/null
+++ b/sigi/apps/convenios/migrations/0014_gescon.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('convenios', '0013_remove_convenio_duracao'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Gescon',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('url_gescon', models.URLField(default='https://adm.senado.gov.br/gestao-contratos/api/contratos/busca?especie={s}', help_text='Informe o ponto de consulta do webservice do Gescon, inclusive com a querystring. No ponto onde deve ser inserida a sigla da subespecie do contrato, use a marca\xe7\xe3o {s}.
Por exemplo: https://adm.senado.gov.br/gestao-contratos/api/contratos/busca?especie={s}', verbose_name='Webservice Gescon')),
+ ('subespecies', models.TextField(default='AC=ACT\nPI=PI\nCN=PML\nTA=PML', help_text='Informe as siglas das subesp\xe9cies de contratos que devem ser pesquisados no Gescon com a sigla correspondente do projeto no SIGI. Coloque um par de siglas por linha, no formato SIGLA_GESTON=SIGLA_SIGI. As siglas n\xe3o encontradas ser\xe3o ignoradas.', verbose_name='Subesp\xe9cies')),
+ ('palavras', models.TextField(default='ILB\nINTERLEGIS', help_text='Palavras que devem aparecer no campo OBJETO dos dados do Gescon para identificar se o contrato pertence ao ILB.
- Informe uma palavra por linha.
- Ocorrendo qualquer uma das palavras, o contrato ser\xe1 importado.
', verbose_name='Palavras de filtro')),
+ ('email', models.EmailField(help_text='Caixa de e-mail para onde o relat\xf3rio di\xe1rio de importa\xe7\xe3o ser\xe1 enviado.', max_length=75, verbose_name='E-mail')),
+ ('ultima_importacao', models.TextField(verbose_name='Resultado da \xfaltima importa\xe7\xe3o', blank=True)),
+ ],
+ options={
+ 'verbose_name': 'Configura\xe7\xe3o do Gescon',
+ 'verbose_name_plural': 'Configura\xe7\xf5es do Gescon',
+ },
+ bases=(models.Model,),
+ ),
+ ]
diff --git a/sigi/apps/convenios/migrations/0015_remove_convenio_search_text.py b/sigi/apps/convenios/migrations/0015_remove_convenio_search_text.py
new file mode 100644
index 0000000..c187381
--- /dev/null
+++ b/sigi/apps/convenios/migrations/0015_remove_convenio_search_text.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('convenios', '0014_gescon'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='convenio',
+ name='search_text',
+ ),
+ ]
diff --git a/sigi/apps/convenios/migrations/0016_auto_20210909_0732.py b/sigi/apps/convenios/migrations/0016_auto_20210909_0732.py
new file mode 100644
index 0000000..9c98cbc
--- /dev/null
+++ b/sigi/apps/convenios/migrations/0016_auto_20210909_0732.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('convenios', '0015_remove_convenio_search_text'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='convenio',
+ name='atualizacao_gescon',
+ field=models.DateTimeField(null=True, verbose_name='Data de atualiza\xe7\xe3o pelo Gescon', blank=True),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='convenio',
+ name='observacao_gescon',
+ field=models.TextField(verbose_name='Observa\xe7\xf5es da atualiza\xe7\xe3o do Gescon', blank=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/sigi/apps/convenios/migrations/0017_convenio_id_contrato_gescon.py b/sigi/apps/convenios/migrations/0017_convenio_id_contrato_gescon.py
new file mode 100644
index 0000000..83bddab
--- /dev/null
+++ b/sigi/apps/convenios/migrations/0017_convenio_id_contrato_gescon.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('convenios', '0016_auto_20210909_0732'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='convenio',
+ name='id_contrato_gescon',
+ field=models.CharField(default=b'', verbose_name='ID do contrato no Gescon', max_length=20, editable=False, blank=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/sigi/apps/convenios/migrations/0018_auto_20211208_1256.py b/sigi/apps/convenios/migrations/0018_auto_20211208_1256.py
new file mode 100644
index 0000000..ed6b3c2
--- /dev/null
+++ b/sigi/apps/convenios/migrations/0018_auto_20211208_1256.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('convenios', '0017_convenio_id_contrato_gescon'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='convenio',
+ name='projeto',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Tipo de Convenio', to='convenios.Projeto'),
+ preserve_default=True,
+ ),
+ ]
diff --git a/sigi/apps/convenios/models.py b/sigi/apps/convenios/models.py
index 775f066..7e69675 100644
--- a/sigi/apps/convenios/models.py
+++ b/sigi/apps/convenios/models.py
@@ -1,9 +1,14 @@
#-*- coding: utf-8 -*-
import re
+import requests
from datetime import datetime, date
from django.db import models
+from django.db.models import Q, fields
+from django.core.mail import send_mail
+from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
-from sigi.apps.utils import SearchField
+from sigi.apps.utils import SearchField, to_ascii
+from sigi.apps.casas.models import Orgao
from sigi.apps.servidores.models import Servidor, Servico
class Projeto(models.Model):
@@ -15,10 +20,10 @@ class Projeto(models.Model):
def __unicode__(self):
return self.sigla
-
+
class Meta:
ordering = ('nome',)
-
+
class StatusConvenio(models.Model):
nome = models.CharField(max_length=100)
cancela = models.BooleanField(_(u"Cancela o convênio"), default=False)
@@ -49,10 +54,10 @@ class Convenio(models.Model):
verbose_name=_(u'órgão conveniado')
)
# campo de busca em caixa baixa e sem acentos
- search_text = SearchField(field_names=['casa_legislativa'])
projeto = models.ForeignKey(
Projeto,
on_delete=models.PROTECT,
+ verbose_name=_(u'Tipo de Convenio')
)
# numero designado pelo Senado Federal para o convênio
num_processo_sf = models.CharField(
@@ -61,11 +66,19 @@ class Convenio(models.Model):
blank=True,
help_text=_(u'Formatos:
Antigo: XXXXXX/XX-X.
SIGAD: XXXXX.XXXXXX/XXXX-XX')
)
+ # link_processo_stf = ('get_sigad_url')
num_convenio = models.CharField(
_(u'número do convênio'),
max_length=10,
blank=True
)
+ id_contrato_gescon = models.CharField(
+ _(u"ID do contrato no Gescon"),
+ max_length=20,
+ blank=True,
+ default="",
+ editable=False
+ )
data_sigi = models.DateField(
_(u"data de cadastro no SIGI"),
blank=True,
@@ -130,17 +143,17 @@ class Convenio(models.Model):
blank=True,
)
data_retorno_assinatura = models.DateField(
- _(u'conveniadas'),
+ _(u'data início vigência'),
null=True,
blank=True,
help_text=_(u'Convênio firmado.')
)
- duracao = models.PositiveIntegerField(
- _(u"duração (meses)"),
+ data_termino_vigencia = models.DateField(
+ _(u'Data término vigência'),
null=True,
blank=True,
- help_text=_(u"Deixar em branco caso a duração seja indefinida")
- )
+ help_text=_(u'Término da vigência do convênio.')
+ )
data_pub_diario = models.DateField(
_(u'data da publicação no Diário Oficial'),
null=True,
@@ -177,35 +190,23 @@ class Convenio(models.Model):
)
conveniada = models.BooleanField(default=False)
equipada = models.BooleanField(default=False)
-
- def get_termino_convenio(self):
- if (self.data_retorno_assinatura is None or
- self.duracao is None):
- return None
-
- ano = self.data_retorno_assinatura.year + int(self.duracao / 12)
- mes = int(self.data_retorno_assinatura.month + int(self.duracao % 12))
- if mes > 12:
- ano = ano + 1
- mes = mes - 12
- dia = self.data_retorno_assinatura.day
-
- while True:
- try:
- data_fim = date(year=ano, month=mes,day=dia)
- break
- except:
- dia = dia - 1
-
- return data_fim
+ atualizacao_gescon = models.DateTimeField(
+ _(u"Data de atualização pelo Gescon"),
+ blank=True,
+ null=True
+ )
+ observacao_gescon = models.TextField(
+ _(u"Observações da atualização do Gescon"),
+ blank=True
+ )
def get_status(self):
if self.status and self.status.cancela:
return _(u"Cancelado")
if self.data_retorno_assinatura is not None:
- if self.duracao is not None:
- if date.today() >= self.get_termino_convenio():
+ if self.data_termino_vigencia is not None:
+ if date.today() >= self.data_termino_vigencia:
return _(u"Vencido")
return _(u"Vigente")
@@ -219,6 +220,14 @@ class Convenio(models.Model):
return _(u"Indefinido")
+ def link_sigad(self, obj):
+ if obj.pk is None:
+ return ""
+ return obj.get_sigad_url()
+
+ link_sigad.short_description = _("Processo no Senado")
+ link_sigad.allow_tags = True
+
def get_sigad_url(self):
m = re.match(
r'(?P00100|00200)\.(?P\d{6})/(?P\d{4})-\d{2}',
@@ -257,18 +266,18 @@ class Convenio(models.Model):
if ((self.data_retorno_assinatura is None) and
(self.equipada and self.data_termo_aceite is not None)):
- return _(u"Convênio nº {number} - equipada em {date} pelo {project}"
+ return _(u"{project} nº {number} - equipada em {date}"
).format(number=self.num_convenio,
date=self.data_termo_aceite.strftime('%d/%m/%Y'),
project=self.projeto.sigla)
elif self.data_retorno_assinatura is None:
- return _(u"Convênio nº {number} - adesão ao projeto {project}, "
+ return _(u"{project}, nº {number}, início "
u"em {date}").format(number=self.num_convenio,
project=self.projeto.sigla,
date=self.data_adesao)
if ((self.data_retorno_assinatura is not None) and not
(self.equipada and self.data_termo_aceite is not None)):
- return _(u"Convênio nº {number} - conveniada ao {project} em "
+ return _(u"{project}, nº {number}, inicio em "
u"{date}. Status: {status}").format(
number=self.num_convenio,
project=self.projeto.sigla,
@@ -276,7 +285,7 @@ class Convenio(models.Model):
status=self.get_status())
if ((self.data_retorno_assinatura is not None) and
(self.equipada and self.data_termo_aceite is not None)):
- return _(u"Convẽnio nº {number} - conveniada ao {project} em {date}"
+ return _(u"{project}, nº {number}, início em {date}"
u" e equipada em {equipped_date}. Status: {status}"
).format(number=self.num_convenio,
project=self.projeto.sigla,
@@ -381,3 +390,412 @@ class Tramitacao(models.Model):
if self.observacao:
result = result + u" (%s)" % (self.observacao)
return unicode(result) # XXX is this unicode(...) really necessary???
+
+class Gescon(models.Model):
+ url_gescon = models.URLField(
+ _(u"Webservice Gescon"),
+ default=(u"https://adm.senado.gov.br/gestao-contratos/api/contratos"
+ u"/busca?especie={s}"),
+ help_text=_(u"Informe o ponto de consulta do webservice do Gescon, "
+ u"inclusive com a querystring. No ponto onde deve ser "
+ u"inserida a sigla da subespecie do contrato, use a "
+ u"marcação {s}.
Por exemplo: "
+ u"https://adm.senado.gov.br/gestao-contratos/api/contratos"
+ u"/busca?especie={s}")
+ )
+ subespecies = models.TextField(
+ _(u"Subespécies"),
+ default=u"AC=ACT\nPI=PI\nCN=PML\nTA=PML",
+ help_text=_(u"Informe as siglas das subespécies de contratos que "
+ u"devem ser pesquisados no Gescon com a sigla "
+ u"correspondente do projeto no SIGI. Coloque um par de "
+ u"siglas por linha, no formato SIGLA_GESTON=SIGLA_SIGI. "
+ u"As siglas não encontradas serão ignoradas.")
+ )
+ palavras = models.TextField(
+ _(u"Palavras de filtro"),
+ default=u"ILB\nINTERLEGIS",
+ help_text=_(u"Palavras que devem aparecer no campo OBJETO dos dados do "
+ u"Gescon para identificar se o contrato pertence ao ILB. "
+ u"- Informe uma palavra por linha.
"
+ u"- Ocorrendo qualquer uma das palavras, o contrato será "
+ u"importado.
")
+ )
+ email = models.EmailField(
+ _(u"E-mail"),
+ help_text=_(u"Caixa de e-mail para onde o relatório diário de "
+ u"importação será enviado.")
+ )
+ ultima_importacao = models.TextField(
+ _(u"Resultado da última importação"),
+ blank=True
+ )
+
+ class Meta:
+ verbose_name = _(u"Configuração do Gescon")
+ verbose_name_plural = _(u"Configurações do Gescon")
+
+ def __unicode__(self):
+ return self.url_gescon
+
+ def save(self, *args, **kwargs):
+ self.pk = 1 # Highlander (singleton pattern)
+ return super(Gescon, self).save(*args, **kwargs)
+
+ def delete(self, *args, **kwargs):
+ pass # Highlander is immortal
+
+ def add_message(self, msg, save=False):
+ self.ultima_importacao += msg + "\n"
+ if save:
+ self.save()
+ self.email_report()
+
+ def email_report(self):
+ if self.email:
+ send_mail(
+ subject=_(u"Relatório de importação GESCON"),
+ message=self.ultima_importacao,
+ recipient_list=self.email,
+ fail_silently=True
+ )
+ else:
+ self.ultima_importacao += _(
+ u"\n\n*Não foi definida uma caixa de e-mail nas configurações "
+ u"do Gescon*"
+ )
+ self.save()
+
+ def importa_contratos(self):
+ self.ultima_importacao = ""
+ self.add_message(
+ _(u"Importação iniciada em {:%d/%m/%Y %H:%M:%S}\n"
+ u"==========================================\n").format(
+ datetime.now()
+ )
+ )
+
+ if self.palavras == "":
+ self.add_message(_(u"Nenhuma palavra de pesquisa definida - "
+ u"processo abortado."), True)
+ return
+
+ if self.subespecies == "":
+ self.add_message(_(u"Nenhuma subespécie definida - processo "
+ u"abortado."), True)
+ return
+
+ if "{s}" not in self.url_gescon:
+ self.add_message(
+ _(
+ u"Falta a marcação {s} na URL para indicar o local onde "
+ u"inserir a sigla da subespécia na consulta ao webservice "
+ u"- processo abortado."
+ ),
+ True
+ )
+ return
+
+ palavras = self.palavras.split()
+ subespecies = {tuple(s.split("=")) for s in self.subespecies.split()}
+
+ for sigla_gescon, sigla_sigi in subespecies:
+ self.add_message(_(u"\nImportando subespécie {s}".format(
+ s=sigla_gescon)))
+ url = self.url_gescon.format(s=sigla_gescon)
+
+ projeto = Projeto.objects.get(sigla=sigla_sigi)
+
+ try:
+ response = requests.get(url, verify=False)
+ except Exception as e:
+ self.add_message(
+ _(u"\tErro ao acessar {url}: {errmsg}").format(
+ url=url,
+ errmsg=e.message.decode("utf8")
+ )
+ )
+ continue
+
+ if not response.ok:
+ self.add_message(
+ _(u"\tErro ao acessar {url}: {reason}").format(
+ url=url,
+ reason=response.reason
+ )
+ )
+ continue
+
+ if not 'application/json' in response.headers.get('Content-Type'):
+ self.add_message(_(u"\tResultado da consulta à {url} não "
+ u"retornou dados em formato json").format(
+ url=url
+ )
+ )
+ continue
+
+ contratos = response.json()
+
+ # Pegar só os contratos que possuem alguma das palavras-chave
+
+ nossos = [c for c in contratos
+ if any(palavra in c['objeto'] for palavra in palavras)]
+
+ self.add_message(
+ _(u"\t{count} contratos encontrados no Gescon").format(
+ count=len(nossos)
+ )
+ )
+
+ novos = 0
+ erros = 0
+ alertas = 0
+ atualizados = 0
+
+ for contrato in nossos:
+ numero = contrato['numero'].zfill(8)
+ numero = "{}/{}".format(numero[:4], numero[4:])
+ sigad = contrato['processo'].zfill(17)
+ sigad = "{}.{}/{}-{}".format(sigad[:5], sigad[5:11],
+ sigad[11:15], sigad[15:])
+
+
+ if contrato['cnpjCpfFornecedor']:
+ cnpj = contrato['cnpjCpfFornecedor'].zfill(14)
+ cnpj = "{}.{}.{}/{}-{}".format(cnpj[:2], cnpj[2:5],
+ cnpj[5:8], cnpj[8:12],
+ cnpj[12:])
+ else:
+ cnpj = None
+
+ if contrato['nomeFornecedor']:
+ nome = contrato['nomeFornecedor']
+ nome = nome.replace(u'VEREADORES DE', '')
+ nome = nome.split('-')[0]
+ nome = nome.split('/')[0]
+ nome = nome.strip()
+ nome = nome.replace(" ", " ")
+ nome = to_ascii(nome)
+ else:
+ nome = None
+
+ if (cnpj is None) and (nome is None):
+ self.add_message(
+ _(u"\tO contrato {numero} no Gescon não informa o CNPJ "
+ u"nem o nome do órgão.").format(numero=numero)
+ )
+ erros += 1
+ continue
+
+ orgao = None
+
+ if cnpj is not None:
+ try:
+ orgao = Orgao.objects.get(cnpj=cnpj)
+ except (
+ Orgao.DoesNotExist,
+ Orgao.MultipleObjectsReturned) as e:
+ orgao = None
+ pass
+
+ if (orgao is None) and (nome is not None):
+ try:
+ orgao = Orgao.objects.get(search_text__iexact=nome)
+ except (
+ Orgao.DoesNotExist,
+ Orgao.MultipleObjectsReturned) as e:
+ orgao = None
+ pass
+
+ if orgao is None:
+ self.add_message(
+ _(u"\tÓrgão não encontrado no SIGI ou mais de um órgão"
+ u"encontrado com o mesmo CNPJ ou nome. Favor "
+ u"regularizar o cadastro: CNPJ: {cnpj}, "
+ u"Nome: {nome}".format(
+ cnpj=contrato['cnpjCpfFornecedor'],
+ nome=contrato['nomeFornecedor']
+ )
+ )
+ )
+ erros += 1
+ continue
+
+ # O mais seguro é o NUP sigad
+ convenios = Convenio.objects.filter(num_processo_sf=sigad)
+ chk = convenios.count()
+
+ if chk == 0:
+ # NUP não encontrado, talvez exista apenas com o número
+ # do GESCON
+ convenios = Convenio.objects.filter(
+ Q(num_convenio=numero) |
+ Q(num_processo_sf=numero)
+ )
+ chk = convenios.count()
+ if chk > 1:
+ # Pode ser que existam vários contratos de subespécies
+ # diferentes com o mesmo número Gescon. Neste caso, o
+ # ideal é filtrar pelo tipo de projeto. Existindo, é
+ # ele mesmo. Se não existir, então segue com os
+ # múltiplos para registrar o problema mais adiante
+ if convenios.filter(projeto=projeto).count() == 1:
+ convenios = convenios.filter(projeto=projeto)
+ chk = 1
+
+ if chk == 0:
+ convenio = Convenio(
+ casa_legislativa=orgao,
+ projeto=projeto,
+ num_processo_sf=sigad,
+ num_convenio=numero,
+ data_sigi=date.today(),
+ data_sigad=contrato['assinatura'],
+ observacao=contrato['objeto'],
+ data_retorno_assinatura=contrato['inicioVigencia'],
+ data_termino_vigencia=contrato['terminoVigencia'],
+ data_pub_diario=contrato['publicacao'],
+ atualizacao_gescon=datetime.now(),
+ observacao_gescon=_(u"Importado integralmente do"
+ u"Gescon")
+ )
+ convenio.save()
+ novos += 1
+ continue
+ elif chk == 1:
+ convenio = convenios.get()
+ convenio.atualizacao_gescon = datetime.now()
+ convenio.observacao_gescon = ''
+ if convenio.casa_legislativa != orgao:
+ self.add_message(
+ _(u"\tO órgao no convênio {url} diverge do que "
+ u"consta no Gescon ({cnpj}, {nome})").format(
+ url=reverse('admin:%s_%s_change' % (
+ convenio._meta.app_label,
+ convenio._meta.model_name),
+ args=[convenio.id]),
+ cnpj=cnpj,
+ nome=contrato['nomeFornecedor']
+ )
+ )
+ convenio.observacao_gescon = _(
+ u'ERRO: Órgão diverge do Gescon. Não atualizado!'
+ )
+ convenio.save()
+ erros += 1
+ continue
+
+ if convenio.num_processo_sf != sigad:
+ self.add_message(
+ _(u"\tO contrato Gescon nº {numero} corresponde"
+ u" ao convênio SIGI {url}, mas o NUP sigad "
+ u"diverge (Gescon: {sigad_gescon}, "
+ u"SIGI: {sigad_sigi}). CORRIGIDO!").format(
+ numero=numero,
+ url=reverse('admin:%s_%s_change' % (
+ convenio._meta.app_label,
+ convenio._meta.model_name),
+ args=[convenio.id]),
+ sigad_gescon=sigad,
+ sigad_sigi=convenio.num_processo_sf
+ )
+ )
+ convenio.num_processo_sf = sigad
+ convenio.observacao_gescon += _(
+ u"Número do SIGAD atualizado.\n"
+ )
+ alertas += 1
+
+ if convenio.num_convenio != numero:
+ self.add_message(
+ _(u"\tO contrato Gescon ID {id} corresponde ao "
+ u"convênio SIGI {url}, mas o número do convênio"
+ u" diverge (Gescon: {numero_gescon}, SIGI: "
+ u"{numero_sigi}). CORRIGIDO!").format(
+ id=contrato['id'],
+ url=reverse('admin:%s_%s_change' % (
+ convenio._meta.app_label,
+ convenio._meta.model_name),
+ args=[convenio.id]
+ ),
+ numero_gescon=numero,
+ numero_sigi=convenio.num_convenio
+ )
+ )
+ convenio.num_convenio = numero
+ convenio.observacao_gescon += _(
+ u"Número do convênio atualizado.\n"
+ )
+ alertas += 1
+
+ if contrato['objeto'] not in convenio.observacao:
+ convenio.observacao += "\n" + contrato['objeto']
+ convenio.observacao_gescon += _(
+ u"Observação atualizada.\n"
+ )
+
+ convenio.data_sigad = contrato['assinatura']
+ convenio.data_retorno_assinatura = contrato[
+ 'inicioVigencia'
+ ]
+ convenio.data_termino_vigencia = contrato[
+ 'terminoVigencia'
+ ]
+ convenio.data_pub_diario = contrato['publicacao']
+ if contrato['codTextoContrato']:
+ convenio.id_contrato_gescon = contrato[
+ 'codTextoContrato'
+ ]
+ else:
+ convenio.id_contrato_gescon = ""
+
+ try:
+ convenio.save()
+ except Exception as e:
+ self.add_message(
+ _(u"Ocorreu um erro ao salvar o convênio {url} no "
+ u"SIGI. Alguma informação do Gescon pode ter "
+ u"quebrado o sistema. Informe ao suporte. Erro:"
+ u"{errmsg}").format(
+ url=reverse('admin:%s_%s_change' % (
+ convenio._meta.app_label,
+ convenio._meta.model_name),
+ args=[convenio.id]
+ ),
+ errmsg=e.message.decode("utf8")
+ )
+ )
+ erros += 1
+ continue
+
+ atualizados += 1
+ else:
+ self.add_message(_(u"\tExistem {count} convênios no SIGI "
+ u"que correspondem ao mesmo contrato no "
+ u"Gescon (contrato {numero}, sigad "
+ u"{sigad})").format(
+ count=chk,
+ numero=numero,
+ sigad=sigad
+ )
+ )
+ erros += 1
+ continue
+
+ self.add_message(
+ _(u"\t{novos} novos convenios adicionados ao SIGI, "
+ u"{atualizados} atualizados, sendo {alertas} com alertas, e "
+ u"{erros} reportados com erro.").format(
+ novos=novos,
+ atualizados=atualizados,
+ alertas=alertas,
+ erros=erros
+ )
+ )
+
+ self.save()
+
+ @classmethod
+ def load(cls):
+ obj, created = cls.objects.get_or_create(pk=1)
+ return obj
diff --git a/sigi/apps/convenios/reports.py b/sigi/apps/convenios/reports.py
index 15f68a8..dea94fc 100644
--- a/sigi/apps/convenios/reports.py
+++ b/sigi/apps/convenios/reports.py
@@ -26,12 +26,12 @@ class SemEquipamentosReport(object):
class ConvenioReport(ReportDefault):
- title = _(u'Relatório de Convênios')
-
+ title = _(u'Relatório de Parcerias')
+
class band_page_header(ReportDefault.band_page_header):
label_top = ReportDefault.band_page_header.label_top
- label_left = [0, 1.5, 7, 9, 11, 13, 15, 17]
+ label_left = [0, 2.5, 6, 8, 10, 12, 14, 16]
elements = list(ReportDefault.band_page_header.elements)
height = 4.7 * cm
@@ -47,15 +47,15 @@ class ConvenioReport(ReportDefault):
top=label_top + 0.4 * cm,
),
Label(
- text=_(u"Data de Adesão"),
+ text=_(u"Número do Convênio"),
left=label_left[2] * cm,
top=label_top,
width=2 * cm,
),
Label(
- text=_(u"Número do Convênio"),
+ text=_(u"Projeto"),
left=label_left[3] * cm,
- top=label_top,
+ top=label_top + 0.4 * cm,
width=2 * cm,
),
Label(
@@ -71,14 +71,8 @@ class ConvenioReport(ReportDefault):
width=2 * cm,
),
Label(
- text=_(u"Data de Aceite"),
+ text=_(u"Orgão"),
left=label_left[6] * cm,
- top=label_top,
- width=2 * cm,
- ),
- Label(
- text=_(u"Projeto"),
- left=label_left[7] * cm,
top=label_top + 0.4 * cm,
width=2 * cm,
),
@@ -89,7 +83,7 @@ class ConvenioReport(ReportDefault):
class band_detail(ReportDefault.band_detail):
- label_left = [0, 1.5, 7, 9, 11, 13, 15, 17]
+ label_left = [0, 2.5, 6, 8, 10, 12, 14, 16]
elements = [
ObjectValue(
@@ -101,13 +95,11 @@ class ConvenioReport(ReportDefault):
left=label_left[1] * cm
),
ObjectValue(
- attribute_name='data_adesao',
- left=label_left[2] * cm,
- get_value=lambda instance:
- instance.data_adesao.strftime('%d/%m/%Y') if instance.data_adesao is not None else '-'
+ attribute_name='num_convenio',
+ left=label_left[2] * cm
),
ObjectValue(
- attribute_name='num_convenio',
+ attribute_name='projeto.sigla',
left=label_left[3] * cm
),
ObjectValue(
@@ -123,30 +115,24 @@ class ConvenioReport(ReportDefault):
instance.data_pub_diario.strftime('%d/%m/%Y') if instance.data_pub_diario is not None else '-'
),
ObjectValue(
- attribute_name='data_termo_aceite',
- left=label_left[6] * cm,
- get_value=lambda instance:
- instance.data_termo_aceite.strftime('%d/%m/%Y') if instance.data_termo_aceite is not None else '-'
- ),
- ObjectValue(
- attribute_name='projeto.sigla',
- left=label_left[7] * cm
+ attribute_name='casa_legislativa.nome',
+ left=label_left[6] * cm
),
]
- groups = [
- ReportGroup(attribute_name='casa_legislativa.municipio.uf',
- band_header=ReportBand(
- height=0.7 * cm,
- elements=[
- ObjectValue(attribute_name='casa_legislativa.municipio.uf',
- get_Value=lambda instance: '%s: %s' % (_(u'Casa Legislativa'), instance.casa_legislativa.uf)
- )
- ],
- borders={'top': True},
- )
- )
- ]
+ #groups = [
+ # ReportGroup(attribute_name='casa_legislativa.municipio.uf',
+ # band_header=ReportBand(
+ # height=0.7 * cm,
+ # elements=[
+ # ObjectValue(attribute_name='casa_legislativa.municipio.uf',
+ # get_Value=lambda instance: '%s: %s' % (_(u'Casa Legislativa'), instance.casa_legislativa.uf)
+ # )
+ # ],
+ # borders={'top': True},
+ # )
+ # )
+ #]
class ConvenioReportSemAceite(ConvenioReport):
@@ -154,7 +140,7 @@ class ConvenioReportSemAceite(ConvenioReport):
class band_page_header(ReportDefault.band_page_header):
label_top = ReportDefault.band_page_header.label_top
- label_left = [0, 1.5, 7, 9, 11, 13, 15, 17]
+ label_left = [0, 2.5, 6, 8, 10, 12, 14, 16]
elements = list(ReportDefault.band_page_header.elements)
height = 4.7 * cm
@@ -169,33 +155,27 @@ class ConvenioReportSemAceite(ConvenioReport):
left=label_left[1] * cm,
top=label_top + 0.4 * cm,
),
- Label(
- text=_(u"Data de Adesão"),
- left=label_left[3] * cm,
- top=label_top,
- width=2 * cm,
- ),
Label(
text=_(u"Número do Convênio"),
- left=label_left[4] * cm,
+ left=label_left[2] * cm,
top=label_top,
width=2 * cm,
- ),
+ ),
Label(
- text=_(u"Data do Convênio"),
- left=label_left[5] * cm,
+ text=_(u"Projeto"),
+ left=label_left[3] * cm,
top=label_top,
width=2 * cm,
),
Label(
- text=_(u"Data de Publicação"),
- left=label_left[6] * cm,
+ text=_(u"Data do Convênio"),
+ left=label_left[4] * cm,
top=label_top,
width=2 * cm,
),
Label(
- text=_(u"Projeto"),
- left=label_left[7] * cm,
+ text=_(u"Orgão"),
+ left=label_left[5] * cm,
top=label_top + 0.4 * cm,
width=2 * cm,
),
@@ -203,7 +183,7 @@ class ConvenioReportSemAceite(ConvenioReport):
class band_detail(ReportDefault.band_detail):
- label_left = [0, 1.5, 7, 9, 11, 13, 15, 17]
+ label_left = [0, 2.5, 6, 8, 10, 12, 14, 16]
elements = [
ObjectValue(
@@ -215,30 +195,22 @@ class ConvenioReportSemAceite(ConvenioReport):
left=label_left[1] * cm
),
ObjectValue(
- attribute_name='data_adesao',
- left=label_left[3] * cm,
- get_value=lambda instance:
- instance.data_adesao.strftime('%d/%m/%Y') if instance.data_adesao is not None else '-'
+ attribute_name='num_convenio',
+ left=label_left[2] * cm
),
ObjectValue(
- attribute_name='num_convenio',
- left=label_left[4] * cm
+ attribute_name='projeto.sigla',
+ left=label_left[3],
),
ObjectValue(
attribute_name='data_retorno_assinatura',
- left=label_left[5] * cm,
+ left=label_left[4] * cm,
get_value=lambda instance:
instance.data_retorno_assinatura.strftime('%d/%m/%Y') if instance.data_retorno_assinatura is not None else '-'
),
ObjectValue(
- attribute_name='data_pub_diario',
- left=label_left[6] * cm,
- get_value=lambda instance:
- instance.data_pub_diario.strftime('%d/%m/%Y') if instance.data_pub_diario is not None else '-'
- ),
- ObjectValue(
- attribute_name='projeto.sigla',
- left=label_left[7] * cm
+ attribute_name='casa_legislativa.nome',
+ left=label_left[5] * cm
),
]
@@ -247,7 +219,7 @@ float_duas_casas = lambda instance: '%.2f' % (instance)
class ConvenioReportRegiao(ReportDefault):
- title = _(u'Relatório de Convênios por Região')
+ title = _(u'Relatório de Parcerias por Região')
class band_page_header(ReportDefault.band_page_header):
label_top = ReportDefault.band_page_header.label_top
@@ -298,16 +270,16 @@ class ConvenioReportRegiao(ReportDefault):
class ConvenioPorCMReport(ConvenioReport):
- title = _(u'Relatório de Convênios por Câmara Municipal')
+ title = _(u'Relatório de Parcerias por Câmara Municipal')
class ConvenioPorALReport(ConvenioReport):
- title = _(u'Relatório de Convênios por Assembléia Legislativa')
+ title = _(u'Relatório de Parcerias por Assembléia Legislativa')
class ConvenioReportSemAceiteCM(ConvenioReportSemAceite):
- title = _(u'Relatório de Convênios por Câmara Municipal')
+ title = _(u'Relatório de Parcerias por Câmara Municipal')
class ConvenioReportSemAceiteAL(ConvenioReportSemAceite):
- title = _(u'Relatório de Convênios por Assembléia Legislativa')
+ title = _(u'Relatório de Parcerias por Assembléia Legislativa')
diff --git a/sigi/apps/convenios/templates/convenios/change_list.html b/sigi/apps/convenios/templates/convenios/change_list.html
index f9aae7b..1c5a553 100644
--- a/sigi/apps/convenios/templates/convenios/change_list.html
+++ b/sigi/apps/convenios/templates/convenios/change_list.html
@@ -14,32 +14,34 @@
Filtro de datas
Use AAAA, AAAA-MM ou AAAA-MM-DD
+