From 97f98c9d0b1022ee89e6e5a63171cb84c5dde00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ses=C3=B3stris=20Vieira?= Date: Tue, 11 Jan 2022 15:59:11 -0300 Subject: [PATCH] =?UTF-8?q?Prepara=20app=20Casas=20para=20migra=C3=A7?= =?UTF-8?q?=C3=A3o=20-=20V=C3=A1rios=20TODOs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements/requirements.txt | 4 + sigi/apps/casas/admin.py | 613 ++--- sigi/apps/casas/apps.py | 6 + sigi/apps/casas/filters.py | 97 + sigi/apps/casas/forms.py | 1 - sigi/apps/casas/migrations/0001_initial.py | 12 +- .../migrations/0002_auto_20150710_1247.py | 5 +- .../migrations/0003_auto_20200207_0919.py | 1 - .../migrations/0004_auto_20201015_0810.py | 3 +- ...005_casalegislativa_gerentes_interlegis.py | 1 - ...6_remove_casalegislativa_gerente_contas.py | 1 - .../migrations/0007_auto_20201016_1632.py | 3 +- .../migrations/0008_auto_20210218_1007.py | 3 +- .../migrations/0009_auto_20210406_1055.py | 3 +- .../migrations/0010_auto_20210406_1101.py | 1 - .../migrations/0011_auto_20210406_1135.py | 1 - .../migrations/0012_auto_20210406_1420.py | 1 - .../migrations/0013_auto_20210406_1428.py | 1 - .../migrations/0014_auto_20210406_1945.py | 4 +- .../migrations/0015_auto_20210407_0801.py | 1 - .../migrations/0016_auto_20210407_1559.py | 1 - .../migrations/0017_auto_20210416_0841.py | 3 +- .../apps/casas/migrations/0018_orgao_sigla.py | 1 - .../migrations/0019_auto_20210501_1058.py | 1 - .../migrations/0020_auto_20210611_0946.py | 1 - ...o_options_remove_orgao_recorte_and_more.py | 200 ++ sigi/apps/casas/models.py | 139 +- .../casas/casas_sem_convenio_pdf.html | 37 + .../casas/templates/casas/report_pdf.html | 132 - sigi/apps/casas/tests.py | 3 + sigi/apps/casas/urls.py | 12 +- sigi/apps/casas/views.py | 2163 +++++++++-------- sigi/settings/base.py | 4 + sigi/settings/development.py | 5 + sigi/static/img/logo-interlegis.png | Bin 0 -> 19505 bytes sigi/static/img/logo-senado.png | Bin 0 -> 31326 bytes .../templates}/change_list_with_cart.html | 2 +- sigi/templates/pdf/base.html | 45 + sigi/templates/pdf/base_report.html | 59 + sigi/urls.py | 1 + sigiStatic/img/logo-interlegis.png | Bin 1703 -> 0 bytes sigiStatic/img/logo-senado.png | Bin 30326 -> 0 bytes 42 files changed, 1872 insertions(+), 1699 deletions(-) create mode 100644 sigi/apps/casas/apps.py create mode 100644 sigi/apps/casas/filters.py create mode 100644 sigi/apps/casas/migrations/0021_alter_orgao_options_remove_orgao_recorte_and_more.py create mode 100644 sigi/apps/casas/templates/casas/casas_sem_convenio_pdf.html delete mode 100644 sigi/apps/casas/templates/casas/report_pdf.html create mode 100644 sigi/apps/casas/tests.py create mode 100644 sigi/static/img/logo-interlegis.png create mode 100644 sigi/static/img/logo-senado.png rename {templates => sigi/templates}/change_list_with_cart.html (87%) create mode 100644 sigi/templates/pdf/base.html create mode 100644 sigi/templates/pdf/base_report.html delete mode 100644 sigiStatic/img/logo-interlegis.png delete mode 100644 sigiStatic/img/logo-senado.png diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 5ae955a..4619552 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,6 +1,10 @@ ipython==7.30.1 +weasyprint==54.0 Django==4.0.1 +django-localflavor==3.1 django-extensions==3.1.5 +django-weasyprint==2.1.0 psycopg2==2.9.3 django-bootstrap5==21.3 Pillow==9.0.0 +django-localflavor==3.1 diff --git a/sigi/apps/casas/admin.py b/sigi/apps/casas/admin.py index 72796f7..4c2631e 100644 --- a/sigi/apps/casas/admin.py +++ b/sigi/apps/casas/admin.py @@ -1,53 +1,35 @@ -# -*- 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.contrib.admin.options import ModelAdmin +from django.contrib.contenttypes.admin import GenericTabularInline from django.http import HttpResponseRedirect -from django.shortcuts import render +from django.urls import reverse +from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ -#from geraldo.site.newsite.django_1_0.django.forms import extras -from image_cropping import ImageCroppingMixin - from sigi.apps.casas.forms import OrgaoForm from sigi.apps.casas.models import Orgao, Presidente, Funcionario, TipoOrgao -from sigi.apps.casas.views import report_complete, labels_report, export_csv, \ - labels_report_sem_presidente, report, \ - adicionar_casas_carrinho +# from sigi.apps.casas.views import report_complete, labels_report, export_csv, \ +# labels_report_sem_presidente, report, \ +# adicionar_casas_carrinho +from sigi.apps.casas.filters import GerentesInterlegisFilter from sigi.apps.contatos.models import Telefone -from sigi.apps.convenios.models import Convenio, Projeto -# from sigi.apps.diagnosticos.models import Diagnostico -# from sigi.apps.inventario.models import Bem -from sigi.apps.metas.models import PlanoDiretor -from sigi.apps.ocorrencias.models import Ocorrencia -# from sigi.apps.parlamentares.models import Legislatura -from sigi.apps.servicos.models import Servico, TipoServico -from sigi.apps.servidores.models import Servidor +# from sigi.apps.convenios.models import Convenio, Projeto +# from sigi.apps.ocorrencias.models import Ocorrencia +# from sigi.apps.servicos.models import Servico, TipoServico from sigi.apps.utils import queryset_ascii -from sigi.apps.utils.base_admin import BaseModelAdmin -class TelefonesInline(generic.GenericTabularInline): +class TelefonesInline(GenericTabularInline): model = Telefone readonly_fields = ('ult_alteracao',) extra = 1 - class PresidenteInline(admin.StackedInline): model = Presidente fields = ('nome', 'sexo', 'data_nascimento', 'nota', 'email', 'tempo_de_servico', 'ult_alteracao', 'endereco', 'municipio', 'bairro', 'cep', 'redes_sociais',) raw_id_fields = ('municipio',) - # fieldsets = ((None, { - # 'fields': ( - # ('nome', 'sexo', 'data_nascimento'), - # ('nota', 'email', 'tempo_de_servico'), - # ('ult_alteracao',), - # ) - # }),) -# exclude = ['setor', 'cargo', 'funcao'] readonly_fields = ('ult_alteracao',) extra = 1 max_num = 1 @@ -56,7 +38,8 @@ class PresidenteInline(admin.StackedInline): 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 + # 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): @@ -72,7 +55,8 @@ class ContatoInterlegisInline(admin.StackedInline): verbose_name_plural = _('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') + .extra(select={'ult_null': 'ult_alteracao is null'}).order_by( + '-ult_alteracao') ) def get_extra(self, request, obj=None , **kwargs): extra = 0 @@ -85,19 +69,6 @@ class FuncionariosInline(admin.StackedInline): 'endereco', 'municipio', 'bairro', 'cep', 'redes_sociais', 'desativado', 'observacoes') raw_id_fields = ('municipio',) - - # fieldsets = ((None, { - # 'fields': ( - # ('nome', 'sexo', 'data_nascimento'), - # ('nota', 'email'), - # ('cargo', 'funcao', 'setor'), - # ('tempo_de_servico', 'ult_alteracao'), - # ('endereco', 'municipio'), - # ('bairro', 'cep'), - # ('redes_sociais'), - # ('desativado', 'observacoes'), - # ) - # }),) readonly_fields = ('ult_alteracao',) extra = 1 inlines = (TelefonesInline,) @@ -105,304 +76,167 @@ class FuncionariosInline(admin.StackedInline): def get_queryset(self, request): return (self.model.objects.exclude(cargo='Presidente',) - .exclude(desativado=True).extra(select={'ult_null': 'ult_alteracao is null'}) + .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 + # 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_retorno_assinatura', 'data_pub_diario',), - ('get_anexos',), - ('link_convenio',), - )}), - ) - readonly_fields = ['link_convenio', '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', 'get_anexos'] - extra = 0 - can_delete = False - template = 'admin/casas/convenios_inline.html' - ordering = ('-data_retorno_assinatura',) - - def has_add_permission(self, request): - return False - -# def get_tramitacoes(self, obj): -# return '
'.join([t.__unicode__() for t in obj.tramitacao_set.all()]) -# -# get_tramitacoes.short_description = _('Tramitações') -# get_tramitacoes.allow_tags = True -# - def get_anexos(self, obj): - return '
'.join(['%s' % (a.arquivo.url, a.__unicode__()) for a in obj.anexo_set.all()]) - get_anexos.short_description = _('Anexos') - get_anexos.allow_tags = True -# -# def get_equipamentos(self, obj): -# return '
'.join([e.__unicode__() for e in obj.equipamentoprevisto_set.all()]) -# -# get_equipamentos.short_description = _('Equipamentos previstos') -# get_equipamentos.allow_tags = True - - def status_convenio(self, obj): - if obj.pk is None: - return "" - status = obj.get_status() - - if status in ["Vencido", "Desistência", "Cancelado"]: - label = r"danger" - elif status == "Vigente": - label = r"success" - elif status == "Pendente": - label = r"warning" - else: - label = r"info" - - return '

{status}

'.format(label=label, status=status) - status_convenio.short_description = _("Status do convênio") - status_convenio.allow_tags = True - - - def link_convenio(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_convenio.short_description = _('Editar convenio') - link_convenio.allow_tags = True - - 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 - -# class LegislaturaInline(admin.TabularInline): -# model = Legislatura -# fields = ['numero', 'data_inicio', 'data_fim', 'data_eleicao', 'total_parlamentares', 'link_parlamentares', ] -# readonly_fields = ['link_parlamentares', ] - -# def link_parlamentares(self, obj): +# class ConveniosInline(admin.TabularInline): +# model = Convenio +# fieldsets = ( +# (None, {'fields': ( +# ('link_sigad', 'status_convenio', 'num_convenio', +# 'projeto', 'observacao'), +# ('data_retorno_assinatura', 'data_pub_diario',), +# ('get_anexos',), +# ('link_convenio',), +# )}), +# ) +# readonly_fields = ['link_convenio', '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', 'get_anexos'] +# extra = 0 +# can_delete = False +# template = 'admin/casas/convenios_inline.html' +# ordering = ('-data_retorno_assinatura',) + +# def has_add_permission(self, request): +# return False + +# def get_anexos(self, obj): +# return mark_safe('
'.join( +# [f'{a}' +# for a in obj.anexo_set.all()]) +# ) +# get_anexos.short_description = _('Anexos') + +# def status_convenio(self, obj): +# if obj.pk is None: +# return "" +# status = obj.get_status() + +# if status in ["Vencido", "Desistência", "Cancelado"]: +# label = r"danger" +# elif status == "Vigente": +# label = r"success" +# elif status == "Pendente": +# label = r"warning" +# else: +# label = r"info" + +# return mark_safe(f'

{status}

') +# status_convenio.short_description = _("Status do convênio") + +# def link_convenio(self, obj): +# if obj.pk is None: +# return "" +# url = reverse( +# f'admin:{obj._meta.app_label}_{obj._meta.module_name}_change', +# args=[obj.pk] +# ) + '?_popup=1' +# return mark_safe( +# f'' +# f'' +# f'{_("Editar")}' +# ) +# link_convenio.short_description = _('Editar convenio') + +# def link_sigad(self, obj): # if obj.pk is None: # return "" -# from django.core.urlresolvers import reverse -# 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_parlamentares.short_description = _('Parlamentares') -# link_parlamentares.allow_tags = True - -# class DiagnosticoInline(admin.TabularInline): -# model = Diagnostico -# fields = ['data_visita_inicio', 'data_visita_fim', 'publicado', 'data_publicacao', 'responsavel', 'link_diagnostico', ] -# readonly_fields = ['data_visita_inicio', 'data_visita_fim', 'publicado', 'data_publicacao', 'responsavel', 'link_diagnostico', ] +# return mark_safe(obj.get_sigad_url()) +# link_sigad.short_description = _("Processo no Senado") + +# class ServicoInline(admin.TabularInline): +# model = Servico +# fields = ('link_url', 'contato_tecnico', 'contato_administrativo', +# 'hospedagem_interlegis', 'data_ativacao', 'data_alteracao', +# 'data_desativacao', 'link_servico') +# readonly_fields = ['link_url', 'contato_tecnico', 'contato_administrativo', +# 'hospedagem_interlegis', 'data_ativacao', +# 'data_alteracao', 'data_desativacao', 'link_servico'] # extra = 0 # max_num = 0 # can_delete = False +# ordering = ('-data_alteracao',) -# def link_diagnostico(self, obj): +# def link_url(self, servico): +# if servico.data_desativacao is not None: +# return servico.url +# return mark_safe( +# f'{servico.url}' +# ) +# link_url.short_description = _('URL do serviço') + +# 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=["%s.pdf" % obj.pk]) -# return """ -# -# Abrir PDF -# """ % (obj.pk, obj.pk, url) - -# link_diagnostico.short_description = _('Ver PDF') -# link_diagnostico.allow_tags = True - -# class BemInline(admin.TabularInline): -# model = Bem - -class ServicoInline(admin.TabularInline): - model = Servico - fields = ('link_url', 'contato_tecnico', 'contato_administrativo', - 'hospedagem_interlegis', 'data_ativacao', 'data_alteracao', - 'data_desativacao', 'link_servico') - readonly_fields = ['link_url', 'contato_tecnico', 'contato_administrativo', - 'hospedagem_interlegis', 'data_ativacao', - 'data_alteracao', 'data_desativacao', 'link_servico'] - extra = 0 - max_num = 0 - can_delete = False - - def link_url(self, servico): - if servico.data_desativacao is not None: - return servico.url - return '{url}'.format(url=servico.url) - link_url.short_description = _('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 = _('Editar Serviço') - link_servico.allow_tags = True - - def has_add_permission(self, request): - return False - -# class PlanoDiretorInline(admin.TabularInline): -# model = PlanoDiretor - -class OcorrenciaInline(admin.TabularInline): - model = Ocorrencia - fields = ('data_criacao', 'assunto', 'prioridade', 'status', 'data_modificacao', 'setor_responsavel', 'link_editar',) - readonly_fields = ('data_criacao', 'assunto', 'prioridade', 'status', 'data_modificacao', 'setor_responsavel', 'link_editar',) - extra = 0 - max_num = 0 - can_delete = False - template = 'admin/casas/ocorrencia_inline.html' - - ordering = ('-data_modificacao',) - - def link_editar(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]) - return """ - %s""" % (obj.pk, obj.pk, url, _('Editar')) - - link_editar.short_description = _('Editar') - link_editar.allow_tags = True - - -class GerentesInterlegisFilter(admin.filters.RelatedFieldListFilter): - - def __init__(self, *args, **kwargs): - super(GerentesInterlegisFilter, self).__init__(*args, **kwargs) - gerentes = Servidor.objects.filter(casas_que_gerencia__isnull=False).order_by('nome_completo').distinct() - self.lookup_choices = [(x.id, x) for x in gerentes] - - -class ConvenioFilter(admin.SimpleListFilter): - title = _("Tipo de convênio") - parameter_name = 'convenio' - - def lookups(self, request, model_admin): - return ( - ('SC', _("Sem nenhum convênio")), - ('CC', _("Com algum convênio")), - ) + tuple([(p.pk, p.sigla) for p in Projeto.objects.all()]) - - def queryset(self, request, queryset): - if self.value() is not None: - if self.value() == 'SC': - queryset = queryset.filter(convenio=None) - elif self.value() == 'CC': - queryset = queryset.exclude(convenio=None) - else: - queryset = queryset.filter(convenio__projeto_id=self.value()) - - return queryset.distinct('municipio__uf__nome', 'nome') - -class ExcluirConvenioFilter(admin.SimpleListFilter): - title=_("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 = _("Serviço") - parameter_name = 'servico' - - def lookups(self, request, model_admin): - return ( - ('SS', _("Sem nenhum serviço")), - ('CS', _("Com algum serviço")), - ('CH', _("Com algum serviço de hospedagem")), - ('CR', _("Apenas serviço de registro")), - ) + tuple([(p.pk, p.nome) for p in TipoServico.objects.all()]) - - def queryset(self, request, queryset): - if self.value() is not None: - if self.value() == 'SS': - queryset = queryset.filter(servico=None) - elif self.value() == 'CS': - queryset = queryset.exclude(servico=None).filter( - servico__data_desativacao__isnull=True) - elif self.value() == 'CR': - queryset = queryset.exclude(servico__tipo_servico__modo='H') \ - .exclude(servico=None) - elif self.value() == 'CH': - queryset = queryset.filter( - servico__tipo_servico__modo='H', - servico__data_desativacao__isnull=True - ) - else: - queryset = queryset.filter( - servico__tipo_servico_id=self.value() - ) - - return queryset.distinct('municipio__uf__nome', 'nome') - -class ServicoAtivoFilter(admin.SimpleListFilter): - title = _("Serviço ativo") - parameter_name = 'ativo' - - def lookups(self, request, model_admin): - return ( - ('ativo', _("Ativo")), - ('desativado', _("Desativado")), - ) +# url = reverse( +# f'admin:{obj._meta.app_label}_{obj._meta.module_name_change}', +# args=[obj.pk] +# ) + '?_popup=1' +# return mark_safe( +# f'' +# f'Editar' +# ) +# link_servico.short_description = _('Editar Serviço') + +# def has_add_permission(self, request): +# return False + +# class OcorrenciaInline(admin.TabularInline): +# model = Ocorrencia +# fields = ('data_criacao', 'assunto', 'prioridade', 'status', +# 'data_modificacao', 'setor_responsavel', 'link_editar',) +# readonly_fields = ('data_criacao', 'assunto', 'prioridade', 'status', +# 'data_modificacao', 'setor_responsavel', 'link_editar',) +# extra = 0 +# max_num = 0 +# can_delete = False +# template = 'admin/casas/ocorrencia_inline.html' +# ordering = ('-data_modificacao',) + +# def link_editar(self, obj): +# if obj.pk is None: +# return "" +# url = reverse( +# f'admin:{obj._meta.app_label}_{obj._meta.module_name}_change', +# args=[obj.pk] +# ) +# return mark_safe( +# f'' +# f'' +# f'{_("Editar")}' +# ) +# link_editar.short_description = _('Editar') + - 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): +class OrgaoAdmin(admin.ModelAdmin): form = OrgaoForm - actions = ['adicionar_casas', ] - inlines = (TelefonesInline, PresidenteInline, ContatoInterlegisInline, FuncionariosInline, - ConveniosInline, ServicoInline, OcorrenciaInline,) - list_display = ('id', 'sigla', 'nome', 'get_uf', 'get_gerentes', 'get_convenios', - 'get_servicos') + # actions = ['adicionar_casas', ] + 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, ServicoAtivoFilter, + # ExcluirConvenioFilter, ServicoFilter, 'inclusao_digital',) list_filter = ('tipo', ('gerentes_interlegis', GerentesInterlegisFilter), - 'municipio__uf__nome', ConvenioFilter, ServicoAtivoFilter, ExcluirConvenioFilter, ServicoFilter, - 'inclusao_digital',) + 'municipio__uf__nome', 'inclusao_digital',) ordering = ('municipio__uf__nome', 'nome') queryset = queryset_ascii fieldsets = ( @@ -435,23 +269,33 @@ class OrgaoAdmin(ImageCroppingMixin, BaseModelAdmin): get_uf.admin_order_field = 'municipio__uf__nome' def get_gerentes(self, obj): - return obj.lista_gerentes() + return mark_safe(obj.lista_gerentes()) get_gerentes.short_description = _('Gerente Interlegis') - get_gerentes.allow_tags = True def get_convenios(self, obj): - return '' + #TODO: Descomentar após migração da app Convênios + # return mark_safe( + # '' + # ) + return "TODO: Descomentar após migração da app Convênios" get_convenios.short_description = _('Convênios') - get_convenios.allow_tags = True def get_servicos(self, obj): - return '' + #TODO: Descomentar após migrar a app Servicos + # return mark_safe( + # '' + # ) + return "TODO: Descomentar após migrar a app Servicos" get_servicos.short_description = _('Serviços') - get_servicos.allow_tags = True def changelist_view(self, request, extra_context=None): return super(OrgaoAdmin, self).changelist_view( @@ -466,56 +310,55 @@ class OrgaoAdmin(ImageCroppingMixin, BaseModelAdmin): 'municipio__uf__codigo_ibge__exact', 'convenio__projeto__id__exact']) - def etiqueta(self, request, queryset): - return labels_report(request, queryset=queryset) - etiqueta.short_description = _("Gerar etiqueta(s) da(s) casa(s) " - "selecionada(s)") - - def etiqueta_sem_presidente(self, request, queryset): - return labels_report_sem_presidente(request, queryset=queryset) - etiqueta_sem_presidente.short_description = _("Gerar etiqueta(s) sem " - "presidente da(s) casa(s) " - "selecionada(s)") - - def relatorio(self, request, queryset): - return report(request, queryset=queryset) - relatorio.short_description = _("Exportar a(s) casa(s) selecionada(s) " - "para PDF") - - def relatorio_completo(self, request, queryset): - return report_complete(request, queryset=queryset) - relatorio_completo.short_description = _("Gerar relatório completo da(s) " - "casa(s) selecionada(s)") - - def relatorio_csv(self, request, queryset): - return export_csv(request) - relatorio_csv.short_description = _("Exportar casa(s) selecionada(s) " - "para CSV") - - def adicionar_casas(self, request, queryset): - if 'carrinho_casas' in request.session: - # if request.session.has_key('carrinho_casas'): - q1 = len(request.session['carrinho_casas']) - else: - q1 = 0 - response = adicionar_casas_carrinho(request, queryset=queryset) - q2 = len(request.session['carrinho_casas']) - quant = q2 - q1 - if quant: - self.message_user(request, str(q2 - q1) + " " + - _("Casas Legislativas adicionadas no carrinho")) - else: - self.message_user(request, _("As Casas Legislativas selecionadas " - "já foram adicionadas anteriormente")) - return HttpResponseRedirect('.') - - adicionar_casas.short_description = _("Armazenar casas no carrinho para " - "exportar") + #TODO: Resolver depois - sigi-boys??? + # def etiqueta(self, request, queryset): + # return labels_report(request, queryset=queryset) + # etiqueta.short_description = _("Gerar etiqueta(s) da(s) casa(s) " + # "selecionada(s)") + + # def etiqueta_sem_presidente(self, request, queryset): + # return labels_report_sem_presidente(request, queryset=queryset) + # etiqueta_sem_presidente.short_description = _("Gerar etiqueta(s) sem " + # "presidente da(s) casa(s) " + # "selecionada(s)") + + # def relatorio(self, request, queryset): + # return report(request, queryset=queryset) + # relatorio.short_description = _("Exportar a(s) casa(s) selecionada(s) " + # "para PDF") + + # def relatorio_completo(self, request, queryset): + # return report_complete(request, queryset=queryset) + # relatorio_completo.short_description = _("Gerar relatório completo da(s) " + # "casa(s) selecionada(s)") + + # def relatorio_csv(self, request, queryset): + # return export_csv(request) + # relatorio_csv.short_description = _("Exportar casa(s) selecionada(s) " + # "para CSV") + + # def adicionar_casas(self, request, queryset): + # if 'carrinho_casas' in request.session: + # # if request.session.has_key('carrinho_casas'): + # q1 = len(request.session['carrinho_casas']) + # else: + # q1 = 0 + # response = adicionar_casas_carrinho(request, queryset=queryset) + # q2 = len(request.session['carrinho_casas']) + # quant = q2 - q1 + # if quant: + # self.message_user(request, str(q2 - q1) + " " + + # _("Casas Legislativas adicionadas no carrinho")) + # else: + # self.message_user(request, _("As Casas Legislativas selecionadas " + # "já foram adicionadas anteriormente")) + # return HttpResponseRedirect('.') + + # adicionar_casas.short_description = _("Armazenar casas no carrinho para " + # "exportar") def get_actions(self, request): actions = super(OrgaoAdmin, self).get_actions(request) if 'delete_selected' in actions: del actions['delete_selected'] - return actions - -admin.site.register(TipoOrgao) + return actions \ No newline at end of file diff --git a/sigi/apps/casas/apps.py b/sigi/apps/casas/apps.py new file mode 100644 index 0000000..78c131f --- /dev/null +++ b/sigi/apps/casas/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + +class CasasConfig(AppConfig): + name = 'sigi.apps.casas' + verbose_name = _('casas legislativas') diff --git a/sigi/apps/casas/filters.py b/sigi/apps/casas/filters.py new file mode 100644 index 0000000..749a260 --- /dev/null +++ b/sigi/apps/casas/filters.py @@ -0,0 +1,97 @@ +from django.contrib import admin +from sigi.apps.servidores.models import Servidor + + +class GerentesInterlegisFilter(admin.filters.RelatedFieldListFilter): + + def __init__(self, *args, **kwargs): + super(GerentesInterlegisFilter, self).__init__(*args, **kwargs) + gerentes = Servidor.objects.filter(casas_que_gerencia__isnull=False).order_by('nome_completo').distinct() + self.lookup_choices = [(x.id, x) for x in gerentes] + +# class ConvenioFilter(admin.SimpleListFilter): +# title = _("Tipo de convênio") +# parameter_name = 'convenio' + +# def lookups(self, request, model_admin): +# return ( +# ('SC', _("Sem nenhum convênio")), +# ('CC', _("Com algum convênio")), +# ) + tuple([(p.pk, p.sigla) for p in Projeto.objects.all()]) + +# def queryset(self, request, queryset): +# if self.value() is not None: +# if self.value() == 'SC': +# queryset = queryset.filter(convenio=None) +# elif self.value() == 'CC': +# queryset = queryset.exclude(convenio=None) +# else: +# queryset = queryset.filter(convenio__projeto_id=self.value()) + +# return queryset.distinct('municipio__uf__nome', 'nome') + +# class ExcluirConvenioFilter(admin.SimpleListFilter): +# title=_("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 = _("Serviço") +# parameter_name = 'servico' + +# def lookups(self, request, model_admin): +# return ( +# ('SS', _("Sem nenhum serviço")), +# ('CS', _("Com algum serviço")), +# ('CH', _("Com algum serviço de hospedagem")), +# ('CR', _("Apenas serviço de registro")), +# ) + tuple([(p.pk, p.nome) for p in TipoServico.objects.all()]) + +# def queryset(self, request, queryset): +# if self.value() is not None: +# if self.value() == 'SS': +# queryset = queryset.filter(servico=None) +# elif self.value() == 'CS': +# queryset = queryset.exclude(servico=None).filter( +# servico__data_desativacao__isnull=True) +# elif self.value() == 'CR': +# queryset = queryset.exclude(servico__tipo_servico__modo='H') \ +# .exclude(servico=None) +# elif self.value() == 'CH': +# queryset = queryset.filter( +# servico__tipo_servico__modo='H', +# servico__data_desativacao__isnull=True +# ) +# else: +# queryset = queryset.filter( +# servico__tipo_servico_id=self.value() +# ) + +# return queryset.distinct('municipio__uf__nome', 'nome') + +# class ServicoAtivoFilter(admin.SimpleListFilter): +# title = _("Serviço ativo") +# parameter_name = 'ativo' + +# def lookups(self, request, model_admin): +# return ( +# ('ativo', _("Ativo")), +# ('desativado', _("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 diff --git a/sigi/apps/casas/forms.py b/sigi/apps/casas/forms.py index fb347d4..d2c1ce0 100644 --- a/sigi/apps/casas/forms.py +++ b/sigi/apps/casas/forms.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django import forms from django.utils.translation import gettext as _ from localflavor.br.forms import BRZipCodeField diff --git a/sigi/apps/casas/migrations/0001_initial.py b/sigi/apps/casas/migrations/0001_initial.py index 7e06ed2..4577a98 100644 --- a/sigi/apps/casas/migrations/0001_initial.py +++ b/sigi/apps/casas/migrations/0001_initial.py @@ -1,8 +1,6 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations -import image_cropping.fields import sigi.apps.utils @@ -30,12 +28,12 @@ class Migration(migrations.Migration): ('pagina_web', models.URLField(help_text=b'Exemplo: http://www.camarapains.mg.gov.br.', verbose_name='p\xe1gina web', blank=True)), ('ult_alt_endereco', models.DateTimeField(null=True, verbose_name='\xdaltima altera\xe7\xe3o do endere\xe7o', blank=True)), ('foto', models.ImageField(height_field=b'foto_altura', width_field=b'foto_largura', upload_to=b'imagens/casas', blank=True)), - (b'recorte', image_cropping.fields.ImageRatioField(b'foto', '400x300', hide_image_field=False, size_warning=True, allow_fullsize=False, free_crop=False, adapt_rotation=False, help_text=None, verbose_name=b'Recorte')), + ('recorte', models.CharField('foto', max_length=255)), ('foto_largura', models.SmallIntegerField(null=True, editable=False)), ('foto_altura', models.SmallIntegerField(null=True, editable=False)), ('data_instalacao', models.DateField(null=True, verbose_name='Data de instala\xe7\xe3o da Casa Legislativa', blank=True)), - ('gerente_contas', models.ForeignKey(verbose_name=b'Gerente de contas', blank=True, to='servidores.Servidor', null=True)), - ('municipio', models.ForeignKey(verbose_name=b'munic\xc3\xadpio', to='contatos.Municipio')), + ('gerente_contas', models.ForeignKey(verbose_name=b'Gerente de contas', blank=True, to='servidores.Servidor', null=True, on_delete=models.CASCADE)), + ('municipio', models.ForeignKey(verbose_name=b'munic\xc3\xadpio', to='contatos.Municipio', on_delete=models.CASCADE)), ], options={ 'ordering': ('nome',), @@ -57,7 +55,7 @@ class Migration(migrations.Migration): ('setor', models.CharField(default=b'outros', max_length=100, choices=[(b'presidente', b'Presidente'), (b'contato_interlegis', b'Contato Interlegis'), (b'infraestrutura_fisica', b'Infraestrutura F\xc3\xadsica'), (b'estrutura_de_ti', b'Estrutura de TI'), (b'organizacao_do_processo_legislativo', b'Organiza\xc3\xa7\xc3\xa3o do Processo Legislativo'), (b'producao_legislativa', b'Produ\xc3\xa7\xc3\xa3o Legislativa'), (b'estrutura_de_comunicacao_social', b'Estrutura de Comunica\xc3\xa7\xc3\xa3o Social'), (b'estrutura_de_recursos_humanos', b'Estrutura de Recursos Humanos'), (b'gestao', b'Gest\xc3\xa3o'), (b'outros', b'Outros')])), ('tempo_de_servico', models.CharField(max_length=50, null=True, verbose_name='tempo de servi\xe7o', blank=True)), ('ult_alteracao', models.DateTimeField(null=True, verbose_name='\xdaltima altera\xe7\xe3o', blank=True)), - ('casa_legislativa', models.ForeignKey(to='casas.CasaLegislativa')), + ('casa_legislativa', models.ForeignKey(to='casas.CasaLegislativa', on_delete=models.CASCADE)), ], options={ 'ordering': ('nome',), @@ -80,7 +78,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='casalegislativa', name='tipo', - field=models.ForeignKey(verbose_name=b'Tipo', to='casas.TipoCasaLegislativa'), + field=models.ForeignKey(verbose_name=b'Tipo', to='casas.TipoCasaLegislativa', on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterUniqueTogether( diff --git a/sigi/apps/casas/migrations/0002_auto_20150710_1247.py b/sigi/apps/casas/migrations/0002_auto_20150710_1247.py index 45a066a..070cea8 100644 --- a/sigi/apps/casas/migrations/0002_auto_20150710_1247.py +++ b/sigi/apps/casas/migrations/0002_auto_20150710_1247.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations @@ -33,13 +32,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='casalegislativa', name='pesquisador', - field=models.ForeignKey(verbose_name='Pesquisador', blank=True, to='servidores.Servidor', null=True), + field=models.ForeignKey(verbose_name='Pesquisador', blank=True, to='servidores.Servidor', null=True, on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterField( model_name='casalegislativa', name='gerente_contas', - field=models.ForeignKey(related_name='casas_que_gerencia', verbose_name=b'Gerente de contas', blank=True, to='servidores.Servidor', null=True), + field=models.ForeignKey(related_name='casas_que_gerencia', verbose_name=b'Gerente de contas', blank=True, to='servidores.Servidor', null=True, on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterField( diff --git a/sigi/apps/casas/migrations/0003_auto_20200207_0919.py b/sigi/apps/casas/migrations/0003_auto_20200207_0919.py index ffc534f..8b57026 100644 --- a/sigi/apps/casas/migrations/0003_auto_20200207_0919.py +++ b/sigi/apps/casas/migrations/0003_auto_20200207_0919.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0004_auto_20201015_0810.py b/sigi/apps/casas/migrations/0004_auto_20201015_0810.py index 39f3463..dd855bf 100644 --- a/sigi/apps/casas/migrations/0004_auto_20201015_0810.py +++ b/sigi/apps/casas/migrations/0004_auto_20201015_0810.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations @@ -14,7 +13,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='casalegislativa', name='gerente_contas', - field=models.ForeignKey(related_name='casas_que_gerencia_old', verbose_name=b'Gerente de contas', blank=True, to='servidores.Servidor', null=True), + field=models.ForeignKey(related_name='casas_que_gerencia_old', verbose_name=b'Gerente de contas', blank=True, to='servidores.Servidor', null=True, on_delete=models.CASCADE), preserve_default=True, ), ] diff --git a/sigi/apps/casas/migrations/0005_casalegislativa_gerentes_interlegis.py b/sigi/apps/casas/migrations/0005_casalegislativa_gerentes_interlegis.py index 56254f7..ad036ee 100644 --- a/sigi/apps/casas/migrations/0005_casalegislativa_gerentes_interlegis.py +++ b/sigi/apps/casas/migrations/0005_casalegislativa_gerentes_interlegis.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0006_remove_casalegislativa_gerente_contas.py b/sigi/apps/casas/migrations/0006_remove_casalegislativa_gerente_contas.py index 3d356eb..a9e3e7a 100644 --- a/sigi/apps/casas/migrations/0006_remove_casalegislativa_gerente_contas.py +++ b/sigi/apps/casas/migrations/0006_remove_casalegislativa_gerente_contas.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0007_auto_20201016_1632.py b/sigi/apps/casas/migrations/0007_auto_20201016_1632.py index 160bc5d..25fff60 100644 --- a/sigi/apps/casas/migrations/0007_auto_20201016_1632.py +++ b/sigi/apps/casas/migrations/0007_auto_20201016_1632.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations @@ -68,7 +67,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='casalegislativa', name='municipio', - field=models.ForeignKey(verbose_name='Munic\xedpio', to='contatos.Municipio'), + field=models.ForeignKey(verbose_name='Munic\xedpio', to='contatos.Municipio', on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterField( diff --git a/sigi/apps/casas/migrations/0008_auto_20210218_1007.py b/sigi/apps/casas/migrations/0008_auto_20210218_1007.py index a4294ff..b76582b 100644 --- a/sigi/apps/casas/migrations/0008_auto_20210218_1007.py +++ b/sigi/apps/casas/migrations/0008_auto_20210218_1007.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations @@ -33,7 +32,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='funcionario', name='municipio', - field=models.ForeignKey(verbose_name='Municipio', to='contatos.Municipio', null=True), + field=models.ForeignKey(verbose_name='Municipio', to='contatos.Municipio', null=True, on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( diff --git a/sigi/apps/casas/migrations/0009_auto_20210406_1055.py b/sigi/apps/casas/migrations/0009_auto_20210406_1055.py index e1b1c5e..19a280a 100644 --- a/sigi/apps/casas/migrations/0009_auto_20210406_1055.py +++ b/sigi/apps/casas/migrations/0009_auto_20210406_1055.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations @@ -14,7 +13,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='funcionario', name='municipio', - field=models.ForeignKey(verbose_name='Municipio', blank=True, to='contatos.Municipio', null=True), + field=models.ForeignKey(verbose_name='Municipio', blank=True, to='contatos.Municipio', null=True, on_delete=models.CASCADE), preserve_default=True, ), ] diff --git a/sigi/apps/casas/migrations/0010_auto_20210406_1101.py b/sigi/apps/casas/migrations/0010_auto_20210406_1101.py index dfc8436..b6b9876 100644 --- a/sigi/apps/casas/migrations/0010_auto_20210406_1101.py +++ b/sigi/apps/casas/migrations/0010_auto_20210406_1101.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0011_auto_20210406_1135.py b/sigi/apps/casas/migrations/0011_auto_20210406_1135.py index 276d3bb..763bd13 100644 --- a/sigi/apps/casas/migrations/0011_auto_20210406_1135.py +++ b/sigi/apps/casas/migrations/0011_auto_20210406_1135.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0012_auto_20210406_1420.py b/sigi/apps/casas/migrations/0012_auto_20210406_1420.py index 1e237c2..012326a 100644 --- a/sigi/apps/casas/migrations/0012_auto_20210406_1420.py +++ b/sigi/apps/casas/migrations/0012_auto_20210406_1420.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0013_auto_20210406_1428.py b/sigi/apps/casas/migrations/0013_auto_20210406_1428.py index 4b1851d..0cac340 100644 --- a/sigi/apps/casas/migrations/0013_auto_20210406_1428.py +++ b/sigi/apps/casas/migrations/0013_auto_20210406_1428.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0014_auto_20210406_1945.py b/sigi/apps/casas/migrations/0014_auto_20210406_1945.py index 32ee5a2..00033eb 100644 --- a/sigi/apps/casas/migrations/0014_auto_20210406_1945.py +++ b/sigi/apps/casas/migrations/0014_auto_20210406_1945.py @@ -1,8 +1,6 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations -import image_cropping.fields import sigi.apps.utils @@ -14,7 +12,7 @@ class Migration(migrations.Migration): ('servidores', '0001_initial'), # ('parlamentares', '0002_auto_20210406_1945'), # ('servicos', '0005_auto_20210406_1945'), - ('servicos', '0004_delete_casaatendida'), + # ('servicos', '0004_delete_casaatendida'), # ('inventario', '0002_auto_20210406_1945'), # ('convenios', '0003_auto_20210406_1945'), # ('ocorrencias', '0003_auto_20210406_1945'), diff --git a/sigi/apps/casas/migrations/0015_auto_20210407_0801.py b/sigi/apps/casas/migrations/0015_auto_20210407_0801.py index 93f7b4b..744c050 100644 --- a/sigi/apps/casas/migrations/0015_auto_20210407_0801.py +++ b/sigi/apps/casas/migrations/0015_auto_20210407_0801.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0016_auto_20210407_1559.py b/sigi/apps/casas/migrations/0016_auto_20210407_1559.py index 91b5347..a87b846 100644 --- a/sigi/apps/casas/migrations/0016_auto_20210407_1559.py +++ b/sigi/apps/casas/migrations/0016_auto_20210407_1559.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0017_auto_20210416_0841.py b/sigi/apps/casas/migrations/0017_auto_20210416_0841.py index 7f6cc71..a831992 100644 --- a/sigi/apps/casas/migrations/0017_auto_20210416_0841.py +++ b/sigi/apps/casas/migrations/0017_auto_20210416_0841.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations @@ -15,7 +14,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='funcionario', name='casa_legislativa', - field=models.ForeignKey(verbose_name='\xf3rg\xe3o', to='casas.Orgao'), + field=models.ForeignKey(verbose_name='\xf3rg\xe3o', to='casas.Orgao', on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterField( diff --git a/sigi/apps/casas/migrations/0018_orgao_sigla.py b/sigi/apps/casas/migrations/0018_orgao_sigla.py index fcc6370..70aaed7 100644 --- a/sigi/apps/casas/migrations/0018_orgao_sigla.py +++ b/sigi/apps/casas/migrations/0018_orgao_sigla.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0019_auto_20210501_1058.py b/sigi/apps/casas/migrations/0019_auto_20210501_1058.py index 0dc0e4b..9a406fa 100644 --- a/sigi/apps/casas/migrations/0019_auto_20210501_1058.py +++ b/sigi/apps/casas/migrations/0019_auto_20210501_1058.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0020_auto_20210611_0946.py b/sigi/apps/casas/migrations/0020_auto_20210611_0946.py index 378731e..2b4f310 100644 --- a/sigi/apps/casas/migrations/0020_auto_20210611_0946.py +++ b/sigi/apps/casas/migrations/0020_auto_20210611_0946.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations diff --git a/sigi/apps/casas/migrations/0021_alter_orgao_options_remove_orgao_recorte_and_more.py b/sigi/apps/casas/migrations/0021_alter_orgao_options_remove_orgao_recorte_and_more.py new file mode 100644 index 0000000..63421a9 --- /dev/null +++ b/sigi/apps/casas/migrations/0021_alter_orgao_options_remove_orgao_recorte_and_more.py @@ -0,0 +1,200 @@ +# Generated by Django 4.0.1 on 2022-01-11 18:44 + +from django.db import migrations, models +import django.db.models.deletion +import sigi.apps.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('servidores', '0008_alter_servico_id_alter_servidor_foto_and_more'), + ('contatos', '0005_alter_mesorregiao_options_alter_microrregiao_options_and_more'), + ('casas', '0020_auto_20210611_0946'), + ] + + operations = [ + migrations.AlterModelOptions( + name='orgao', + options={'ordering': ('nome',), 'verbose_name': 'órgão', 'verbose_name_plural': 'órgãos'}, + ), + migrations.RemoveField( + model_name='orgao', + name='recorte', + ), + migrations.AlterField( + model_name='funcionario', + name='bairro', + field=models.CharField(blank=True, max_length=100, verbose_name='bairro'), + ), + migrations.AlterField( + model_name='funcionario', + name='cargo', + field=models.CharField(blank=True, max_length=100, null=True, verbose_name='cargo'), + ), + migrations.AlterField( + model_name='funcionario', + name='data_nascimento', + field=models.DateField(blank=True, null=True, verbose_name='data de nascimento'), + ), + migrations.AlterField( + model_name='funcionario', + name='desativado', + field=models.BooleanField(default=False, verbose_name='desativado'), + ), + migrations.AlterField( + model_name='funcionario', + name='endereco', + field=models.CharField(blank=True, max_length=100, verbose_name='endereço'), + ), + migrations.AlterField( + model_name='funcionario', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='funcionario', + name='municipio', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='contatos.municipio', verbose_name='municipio'), + ), + migrations.AlterField( + model_name='funcionario', + name='nome', + field=models.CharField(max_length=60, verbose_name='nome completo'), + ), + migrations.AlterField( + model_name='funcionario', + name='nota', + field=models.CharField(blank=True, max_length=250, null=True, verbose_name='telefones'), + ), + migrations.AlterField( + model_name='funcionario', + name='observacoes', + field=models.TextField(blank=True, verbose_name='observações'), + ), + migrations.AlterField( + model_name='funcionario', + name='redes_sociais', + field=models.TextField(blank=True, help_text='Colocar um por linha', verbose_name='redes sociais'), + ), + migrations.AlterField( + model_name='funcionario', + name='setor', + field=models.CharField(choices=[('presidente', 'Presidente'), ('contato_interlegis', 'Contato Interlegis'), ('infraestrutura_fisica', 'Infraestrutura Física'), ('estrutura_de_ti', 'Estrutura de TI'), ('organizacao_do_processo_legislativo', 'Organização do Processo Legislativo'), ('producao_legislativa', 'Produção Legislativa'), ('estrutura_de_comunicacao_social', 'Estrutura de Comunicação Social'), ('estrutura_de_recursos_humanos', 'Estrutura de Recursos Humanos'), ('gestao', 'Gestão'), ('outros', 'Outros')], default='outros', max_length=100, verbose_name='setor'), + ), + migrations.AlterField( + model_name='funcionario', + name='sexo', + field=models.CharField(choices=[('M', 'Masculino'), ('F', 'Feminino')], default='M', max_length=1, verbose_name='sexo'), + ), + migrations.AlterField( + model_name='funcionario', + name='tempo_de_servico', + field=models.CharField(blank=True, max_length=50, null=True, verbose_name='tempo de serviço'), + ), + migrations.AlterField( + model_name='funcionario', + name='ult_alteracao', + field=models.DateTimeField(auto_now=True, null=True, verbose_name='última alteração'), + ), + migrations.AlterField( + model_name='orgao', + name='bairro', + field=models.CharField(blank=True, max_length=100, verbose_name='bairro'), + ), + migrations.AlterField( + model_name='orgao', + name='cnpj', + field=models.CharField(blank=True, max_length=32, verbose_name='CNPJ'), + ), + migrations.AlterField( + model_name='orgao', + name='codigo_interlegis', + field=models.CharField(blank=True, max_length=3, verbose_name='código Interlegis'), + ), + migrations.AlterField( + model_name='orgao', + name='data_instalacao', + field=models.DateField(blank=True, null=True, verbose_name='data de instalação da Casa Legislativa'), + ), + migrations.AlterField( + model_name='orgao', + name='data_levantamento', + field=models.DateTimeField(blank=True, null=True, verbose_name='data/hora da pesquisa'), + ), + migrations.AlterField( + model_name='orgao', + name='email', + field=models.EmailField(blank=True, max_length=128, verbose_name='e-mail'), + ), + migrations.AlterField( + model_name='orgao', + name='foto', + field=models.ImageField(blank=True, height_field='foto_altura', upload_to='imagens/casas', verbose_name='foto', width_field='foto_largura'), + ), + migrations.AlterField( + model_name='orgao', + name='horario_funcionamento', + field=models.CharField(blank=True, max_length=100, verbose_name='horário de funcionamento da Casa Legislativa'), + ), + migrations.AlterField( + model_name='orgao', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='orgao', + name='inclusao_digital', + field=models.CharField(choices=[('NAO PESQUISADO', 'Não pesquisado'), ('NAO POSSUI PORTAL', 'Não possui portal'), ('PORTAL MODELO', 'Possui Portal Modelo'), ('OUTRO PORTAL', 'Possui outro portal')], default='NAO PESQUISADO', max_length=30, verbose_name='inclusão digital'), + ), + migrations.AlterField( + model_name='orgao', + name='logradouro', + field=models.CharField(help_text='Avenida, rua, praça, jardim, parque...', max_length=100, verbose_name='logradouro'), + ), + migrations.AlterField( + model_name='orgao', + name='municipio', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contatos.municipio', verbose_name='município'), + ), + migrations.AlterField( + model_name='orgao', + name='nome', + field=models.CharField(help_text='Exemplo: Câmara Municipal de Pains.', max_length=60, verbose_name='nome'), + ), + migrations.AlterField( + model_name='orgao', + name='obs_pesquisa', + field=models.TextField(blank=True, verbose_name='observações do pesquisador'), + ), + migrations.AlterField( + model_name='orgao', + name='pagina_web', + field=models.URLField(blank=True, help_text='Exemplo: http://www.camarapains.mg.gov.br.', verbose_name='página web'), + ), + migrations.AlterField( + model_name='orgao', + name='pesquisador', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='servidores.servidor', verbose_name='pesquisador'), + ), + migrations.AlterField( + model_name='orgao', + name='search_text', + field=sigi.apps.utils.SearchField(editable=False, field_names=['nome']), + ), + migrations.AlterField( + model_name='orgao', + name='tipo', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='casas.tipoorgao', verbose_name='tipo'), + ), + migrations.AlterField( + model_name='orgao', + name='ult_alt_endereco', + field=models.DateTimeField(blank=True, null=True, verbose_name='última alteração do endereço'), + ), + migrations.AlterField( + model_name='tipoorgao', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/sigi/apps/casas/models.py b/sigi/apps/casas/models.py index f62c327..ce7f461 100644 --- a/sigi/apps/casas/models.py +++ b/sigi/apps/casas/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from datetime import datetime import random from string import ascii_uppercase @@ -7,19 +6,12 @@ from django.core.exceptions import ValidationError from django.utils.translation import gettext as _ from django.contrib.contenttypes.fields import GenericRelation from django.db import models -from image_cropping import ImageRatioField from sigi.apps.contatos.models import Municipio from sigi.apps.servidores.models import Servidor from sigi.apps.utils import SearchField class TipoOrgao(models.Model): - """ Modelo para representar o tipo da Casa Legislativa - - Geralmente: Câmara Municipal, Assembléia Legislativa, - Câmara Distrital ou Legislativo Federal - """ - sigla = models.CharField(_("Sigla"), max_length=5) nome = models.CharField(_("Nome"), max_length=100) legislativo = models.BooleanField(_("Poder legislativo"), default=False) @@ -29,13 +21,10 @@ class TipoOrgao(models.Model): verbose_name = _("Tipo de órgão") verbose_name_plural = _("Tipos de órgão") - def __unicode__(self): + def __str__(self): return self.nome class Orgao(models.Model): - """ Modelo para representar uma Casa Legislativa - """ - INCLUSAO_DIGITAL_CHOICES = ( ('NAO PESQUISADO', _('Não pesquisado')), ('NAO POSSUI PORTAL', _('Não possui portal')), @@ -44,7 +33,7 @@ class Orgao(models.Model): ) nome = models.CharField( - _("Nome"), + _("nome"), max_length=60, help_text=_('Exemplo: Câmara Municipal de Pains.') ) @@ -58,102 +47,93 @@ class Orgao(models.Model): tipo = models.ForeignKey( TipoOrgao, on_delete=models.PROTECT, - verbose_name=_("Tipo") + verbose_name=_("tipo") ) cnpj = models.CharField(_("CNPJ"), max_length=32, blank=True) observacoes = models.TextField(_('observações'), blank=True) horario_funcionamento = models.CharField( - _("Horário de funcionamento da Casa Legislativa"), + _("horário de funcionamento da Casa Legislativa"), max_length=100, blank=True, ) -# num_parlamentares = models.PositiveIntegerField('Número de parlamentares') codigo_interlegis = models.CharField( - _('Código Interlegis'), + _('código Interlegis'), max_length=3, blank=True ) - # codigo_interlegis.ts_filter = True - gerentes_interlegis = models.ManyToManyField( Servidor, verbose_name=_("Gerentes Interlegis"), related_name='casas_que_gerencia', blank=True, ) - # Informações de contato logradouro = models.CharField( - _("Logradouro"), + _("logradouro"), max_length=100, help_text=_('Avenida, rua, praça, jardim, parque...') ) - bairro = models.CharField(_("Bairro"), max_length=100, blank=True) - + bairro = models.CharField(_("bairro"), max_length=100, blank=True) municipio = models.ForeignKey( 'contatos.Municipio', on_delete=models.PROTECT, - verbose_name=_('Município') + verbose_name=_('município') ) - # municipio.uf_filter = True - cep = models.CharField(_("CEP"), max_length=32) - email = models.EmailField(_('E-mail'), max_length=128, blank=True) + email = models.EmailField(_('e-mail'), max_length=128, blank=True) pagina_web = models.URLField( - _('Página web'), + _('página web'), help_text=_('Exemplo: http://www.camarapains.mg.gov.br.'), blank=True, ) inclusao_digital = models.CharField( - _("Inclusão digital"), + _("inclusão digital"), max_length=30, choices=INCLUSAO_DIGITAL_CHOICES, default=INCLUSAO_DIGITAL_CHOICES[0][0] ) data_levantamento = models.DateTimeField( - _("Data/hora da pesquisa"), + _("data/hora da pesquisa"), null=True, blank=True ) pesquisador = models.ForeignKey( Servidor, on_delete=models.SET_NULL, - verbose_name=_("Pesquisador"), + verbose_name=_("pesquisador"), null=True, blank=True ) obs_pesquisa = models.TextField( - _("Observações do pesquisador"), + _("observações do pesquisador"), blank=True ) ult_alt_endereco = models.DateTimeField( - _('Última alteração do endereço'), + _('última alteração do endereço'), null=True, blank=True, editable=True ) telefones = GenericRelation('contatos.Telefone') - foto = models.ImageField( - _("Foto"), + _("foto"), upload_to='imagens/casas', width_field='foto_largura', height_field='foto_altura', blank=True ) - recorte = ImageRatioField('foto', '400x300', verbose_name=_("Recorte")) foto_largura = models.SmallIntegerField(editable=False, null=True) foto_altura = models.SmallIntegerField(editable=False, null=True) data_instalacao = models.DateField( - _('Data de instalação da Casa Legislativa'), + _('data de instalação da Casa Legislativa'), null=True, blank=True ) class Meta: ordering = ('nome',) - verbose_name = _('Órgão') - verbose_name_plural = _('Órgãos') + verbose_name = _('órgão') + verbose_name_plural = _('órgãos') def lista_gerentes(self, fmt='html'): if not self.gerentes_interlegis.exists(): @@ -168,15 +148,14 @@ class Orgao(models.Model): @property def num_parlamentares(self): - if not self.legislatura_set.exists(): - return 0 - return self.legislatura_set.latest('data_inicio').total_parlamentares + # TODO: Descomentar assim que a app Parlamentares for migrada + # if not self.legislatura_set.exists(): + # return 0 + # return self.legislatura_set.latest('data_inicio').total_parlamentares + return 0 @property def telefone(self): - """ Link para acessar diretamente o primeiro telefone cadastrado da casa - Util para relatorios antigos - """ telefones = self.telefones.all() if telefones: return telefones[0] @@ -184,9 +163,6 @@ class Orgao(models.Model): @property def presidente(self): - """ Link para acessar diretamente o contato do presidente da casa - Util para relatorios antigos - """ try: if self.funcionario_set.filter(setor='presidente').count() > 1: return self.funcionario_set.filter(setor='presidente')[0] @@ -197,9 +173,6 @@ class Orgao(models.Model): @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] @@ -208,23 +181,6 @@ class Orgao(models.Model): except Funcionario.DoesNotExist: return None - @property - def total_parlamentares(self): - """ - Calcula o total de parlamentares atual da Casa: - - O total de parlamentares da legislatura mais recente, ou - - num_parlamentares ou - - 0 se não tiver nenhuma das informações - """ - - if self.legislatura_set.exists(): - return self.legislatura_set.all()[0].total_parlamentares - - if self.num_parlamentares is not None: - return self.num_parlamentares - - return 0 - def gerarCodigoInterlegis(self): codigo = self.codigo_interlegis @@ -238,7 +194,8 @@ class Orgao(models.Model): return codigo # Se já existe, então trata a Assembleia como uma Casa qualquer. - cityName = normalize('NFKD', unicode(self.municipio.nome)).encode('ascii', 'ignore') + cityName = normalize('NFKD', self.municipio.nome).encode( + 'ascii', 'ignore') cityName = cityName.upper().strip() cityName = cityName.replace(' DA ', ' ') cityName = cityName.replace(' DE ', ' ') @@ -315,7 +272,7 @@ class Orgao(models.Model): return codigo - def __unicode__(self): + def __str__(self): return self.nome def clean(self): @@ -347,13 +304,7 @@ class Orgao(models.Model): return super(Orgao, self).save(*args, **kwargs) - class Funcionario(models.Model): - - """ Modelo para registrar contatos vinculados às - Casas Legislativas - """ - SETOR_CHOICES = [ ("presidente", _("Presidente")), ("contato_interlegis", _("Contato Interlegis")), @@ -379,42 +330,40 @@ class Funcionario(models.Model): verbose_name=_("órgão"), ) nome = models.CharField(_('nome completo'), max_length=60, blank=False) - # nome.alphabetic_filter = True sexo = models.CharField( - _("Sexo"), + _("sexo"), max_length=1, choices=SEXO_CHOICES, default="M" ) data_nascimento = models.DateField( - _("Data de nascimento"), + _("data de nascimento"), blank=True, null=True ) nota = models.CharField( - _("Telefones"), + _("telefones"), max_length=250, null=True, blank=True ) email = models.CharField(_('e-mail'), max_length=250, blank=True) - # endereco = generic.GenericRelation('contatos.Endereco') - endereco = models.CharField(_('Endereço'), max_length=100, blank=True) + endereco = models.CharField(_('endereço'), max_length=100, blank=True) municipio = models.ForeignKey( Municipio, on_delete=models.SET_NULL, - verbose_name=_('Municipio'), + verbose_name=_('municipio'), null=True, blank=True, ) - bairro = models.CharField(_('Bairro'), max_length=100, blank=True) + bairro = models.CharField(_('bairro'), max_length=100, blank=True) cep = models.CharField(_('CEP'), max_length=10, blank=True) redes_sociais = models.TextField( - _('Redes sociais'), + _('redes sociais'), help_text=_('Colocar um por linha'), blank=True ) - cargo = models.CharField(_("Cargo"), max_length=100, null=True, blank=True) + cargo = models.CharField(_("cargo"), max_length=100, null=True, blank=True) funcao = models.CharField( _('função'), max_length=100, @@ -422,46 +371,42 @@ class Funcionario(models.Model): blank=True ) setor = models.CharField( - _("Setor"), + _("setor"), max_length=100, choices=SETOR_CHOICES, default="outros" ) tempo_de_servico = models.CharField( - _('Tempo de serviço'), + _('tempo de serviço'), max_length=50, null=True, blank=True ) ult_alteracao = models.DateTimeField( - _('Última alteração'), + _('última alteração'), null=True, blank=True, editable=True, auto_now=True ) - desativado = models.BooleanField(_("Desativado"), default=False) - observacoes = models.TextField(_("Observações"), blank=True) + desativado = models.BooleanField(_("desativado"), default=False) + observacoes = models.TextField(_("observações"), blank=True) class Meta: ordering = ('nome',) verbose_name = _('contato da Casa Legislativa') verbose_name_plural = _('contatos da Casa Legislativa') - def __unicode__(self): + def __str__(self): return self.nome - class PresidenteManager(models.Manager): - def get_queryset(self): qs = super(PresidenteManager, self).get_queryset() qs = qs.filter(setor='presidente') return qs - class Presidente(Funcionario): - class Meta: proxy = True @@ -471,4 +416,4 @@ class Presidente(Funcionario): self.setor = 'presidente' self.cargo = 'Presidente' self.funcao = 'Presidente' - return super(Presidente, self).save(*args, **kwargs) + return super(Presidente, self).save(*args, **kwargs) \ No newline at end of file diff --git a/sigi/apps/casas/templates/casas/casas_sem_convenio_pdf.html b/sigi/apps/casas/templates/casas/casas_sem_convenio_pdf.html new file mode 100644 index 0000000..2d6abe8 --- /dev/null +++ b/sigi/apps/casas/templates/casas/casas_sem_convenio_pdf.html @@ -0,0 +1,37 @@ +{% extends 'pdf/base_report.html' %} +{% load static i18n %} + +{% block page_size %}A4 landscape{% endblock %} + +{% block main_content %} + + + + + + + + + + + + + + + {% for casa in casas %} + {% ifchanged casa.municipio.uf %} + + {% endifchanged %} + + + + + + + + + + + {% endfor %} +
{% trans 'Casa' %}{% trans 'Presidente' %}{% trans 'Tipo' %}{% trans 'Endereço' %}{% trans 'Bairro' %}{% trans 'CEP' %}{% trans 'Telefone' %}{% trans 'E-mail' %}

{{ casa.municipio.uf.nome }}

{{ casa.nome }}{{ casa.presidente }}{{ casa.tipo.sigla }}{{ casa.logradouro }}{{ casa.bairro }}{{ casa.cep }}{{ casa.telefone }}{{ casa.email }}
+{% endblock main_content %} \ No newline at end of file diff --git a/sigi/apps/casas/templates/casas/report_pdf.html b/sigi/apps/casas/templates/casas/report_pdf.html deleted file mode 100644 index 485e7de..0000000 --- a/sigi/apps/casas/templates/casas/report_pdf.html +++ /dev/null @@ -1,132 +0,0 @@ -{% load smart_if %} -{% load static from staticfiles %} -{% load i18n %} - - - - - Casa Legislativa - - - - - - - - - - - - - - - - - - - - {% for casa in casas %} - {% ifchanged casa.municipio.uf %} - - {% endifchanged %} - - - - - - - - - - - {% endfor %} -
{% trans 'Casa' %}{% trans 'Presidente' %}{% trans 'Tipo' %}{% trans 'Endereço' %}{% trans 'Bairro' %}{% trans 'CEP' %}{% trans 'Telefone' %}{% trans 'E-mail' %}

{{ casa.municipio.uf.nome }}

{{ casa.nome }}{{ casa.presidente }}{{ casa.tipo.sigla }}{{ casa.logradouro }}{{ casa.bairro }}{{ casa.cep }}{{ casa.telefone }}{{ casa.email }}
- - - - diff --git a/sigi/apps/casas/tests.py b/sigi/apps/casas/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/sigi/apps/casas/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/sigi/apps/casas/urls.py b/sigi/apps/casas/urls.py index 38f0687..db9a5d9 100644 --- a/sigi/apps/casas/urls.py +++ b/sigi/apps/casas/urls.py @@ -1,4 +1,13 @@ -# coding: utf-8 +from django.urls import path, include +from sigi.apps.casas.views import CasasSemConvenioReport + +urlpatterns = [ + path('orgao/casas_sem_convenio_report/', CasasSemConvenioReport.as_view(), + name='casas-sem-convenio-report'), +] + + +""" from django.conf.urls import patterns, url from django.contrib.auth.decorators import login_required from sigi.apps.casas.views import importa_casas @@ -55,3 +64,4 @@ urlpatterns = patterns( url(r'^gerentes/$', 'gerentes_interlegis', name='gerentes_interlegis'), ) +""" \ No newline at end of file diff --git a/sigi/apps/casas/views.py b/sigi/apps/casas/views.py index 4f2c549..0f64e62 100644 --- a/sigi/apps/casas/views.py +++ b/sigi/apps/casas/views.py @@ -1,320 +1,97 @@ -# -*- coding: utf-8 -*- 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 from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator, InvalidPage, EmptyPage from django.db.models import Count, Q -from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden +from django.http import (HttpResponse, HttpResponseRedirect, + HttpResponseForbidden) from django.shortcuts import render, get_object_or_404 -from django.utils.translation import gettext as _, ungettext +from django.utils.translation import gettext as _, ngettext from django.views.generic import View +from django_weasyprint.views import WeasyTemplateView from sigi.apps.casas.forms import PortfolioForm, AtualizaCasaForm from sigi.apps.casas.models import Orgao, TipoOrgao, Funcionario -from sigi.apps.casas.reports import (CasasLegislativasLabels, - CasasLegislativasLabelsSemPresidente) -from sigi.apps.contatos.models import (UnidadeFederativa, Municipio, - Mesorregiao, Microrregiao) -from sigi.apps.ocorrencias.models import Ocorrencia -from sigi.apps.parlamentares.reports import ParlamentaresLabels -from sigi.apps.servicos.models import TipoServico from sigi.apps.servidores.models import Servidor -from sigi.shortcuts import render_to_pdf - -class importa_casas(View): - errors = [] - total_registros = 0 - - TIPO = 'tipo' - MUNICIPIO = 'municipio' - UF = 'uf' - ORGAO_ENDERECO = 'orgao_endereco' - ORGAO_BAIRRO = 'orgao_bairro' - ORGAO_CEP = 'orgao_cep' - ORGAO_EMAIL = 'orgao_email' - ORGAO_PORTAL = 'orgao_portal' - ORGAO_TELEFONES = 'orgao_telefones' - PRESIDENTE_NOME = 'presidente_nome' - PRESIDENTE_DATA_NASCIMENTO = 'presidente_data_nascimento' - PRESIDENTE_TELEFONES = 'presidente_telefones' - PRESIDENTE_EMAILS = 'presidente_emails' - PRESIDENTE_ENDERECO = 'presidente_endereco' - PRESIDENTE_MUNICIPIO = 'presidente_municipio' - PRESIDENTE_BAIRRO = 'presidente_bairro' - PRESIDENTE_CEP = 'presidente_cep' - PRESIDENTE_REDES_SOCIAIS = 'presidente_redes_sociais' - SERVIDOR_NOME = 'contato_nome' - SERVIDOR_DATA_NASCIMENTO = 'contato_data_nascimento' - SERVIDOR_TELEFONES = 'contato_telefones' - SERVIDOR_EMAILS = 'contato_emails' - SERVIDOR_ENDERECO = 'contato_endereco' - SERVIDOR_MUNICIPIO = 'contato_municipio' - SERVIDOR_BAIRRO = 'contato_bairro' - SERVIDOR_CEP = 'contato_cep' - SERVIDOR_REDES_SOCIAIS = 'contato_redes_sociais' - ERROS = 'erros_importacao' - - fieldnames = [TIPO, MUNICIPIO, UF, ORGAO_ENDERECO, ORGAO_BAIRRO, ORGAO_CEP, - ORGAO_EMAIL, ORGAO_PORTAL, ORGAO_TELEFONES, PRESIDENTE_NOME, - PRESIDENTE_DATA_NASCIMENTO, PRESIDENTE_TELEFONES, - PRESIDENTE_EMAILS, PRESIDENTE_ENDERECO, PRESIDENTE_MUNICIPIO, - PRESIDENTE_BAIRRO, PRESIDENTE_CEP, PRESIDENTE_REDES_SOCIAIS, - SERVIDOR_NOME, SERVIDOR_DATA_NASCIMENTO, SERVIDOR_TELEFONES, - SERVIDOR_EMAILS, SERVIDOR_ENDERECO, SERVIDOR_MUNICIPIO, - SERVIDOR_BAIRRO, SERVIDOR_CEP, SERVIDOR_REDES_SOCIAIS, ERROS,] - - ID_FIELDS = {TIPO, MUNICIPIO, UF} - - ORGAO_FIELDS = { - ORGAO_ENDERECO: 'logradouro', - ORGAO_BAIRRO: 'bairro', - ORGAO_CEP: 'cep', - ORGAO_EMAIL: 'email', - ORGAO_PORTAL: 'pagina_web', - ORGAO_TELEFONES: 'telefones', - } - - PRESIDENTE_FIELDS = { - PRESIDENTE_NOME: 'nome', - PRESIDENTE_DATA_NASCIMENTO: 'data_nascimento', - PRESIDENTE_TELEFONES: 'nota', - PRESIDENTE_EMAILS: 'email', - PRESIDENTE_ENDERECO: 'endereco', - PRESIDENTE_MUNICIPIO: 'municipio_id', - PRESIDENTE_BAIRRO: 'bairro', - PRESIDENTE_CEP: 'cep', - PRESIDENTE_REDES_SOCIAIS: 'redes_sociais', - } - - SERVIDOR_FIELDS = { - SERVIDOR_NOME: 'nome', - SERVIDOR_DATA_NASCIMENTO: 'data_nascimento', - SERVIDOR_TELEFONES: 'nota', - SERVIDOR_EMAILS: 'email', - SERVIDOR_ENDERECO: 'endereco', - SERVIDOR_MUNICIPIO: 'municipio_id', - SERVIDOR_BAIRRO: 'bairro', - SERVIDOR_CEP: 'cep', - SERVIDOR_REDES_SOCIAIS: 'redes_sociais', - } - - def get(self, request): - if not request.user.is_superuser: - return HttpResponseForbidden() - - form = AtualizaCasaForm() - return render(request, 'casas/importar.html', {'form': form}) - - def post(self, request): - if not request.user.is_superuser: - return HttpResponseForbidden() - - form = AtualizaCasaForm(request.POST, request.FILES) - - if form.is_valid(): - file = form.cleaned_data['arquivo'] - reader = csv.DictReader(file) - if not self.ID_FIELDS.issubset(reader.fieldnames): - return render( - request, - 'casas/importar.html', - {'form': form, 'error': _("O arquivo não possui algum dos " - "campos obrigatórios")} - ) - - if self.importa(reader): - # Importação concluída com êxito - return render( - request, - 'casas/importar_result.html', - {'file_name': file.name, 'total': self.total_registros, - 'com_erros': 0} - ) - else: - # Importado com erros - file_name = "casas-erros-{:%Y-%m-%d-%H%M}.csv".format( - datetime.now()) - fields = self.fieldnames - for f in reader.fieldnames: - if f not in fields: - fields.append(f) - with open(settings.MEDIA_ROOT+'/temp/'+file_name, "w+") as f: - writer = csv.DictWriter(f, fieldnames=fields) - writer.writeheader() - writer.writerows(self.errors) - return render( - request, - 'casas/importar_result.html', - {'file_name': file.name, 'result_file': file_name, - 'total': self.total_registros, - 'com_erros': len(self.errors)} - ) - - response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = ( - 'attachment; filename="somefilename.csv"') - return response - else: - return render( - request, - 'casas/importar.html', - {'form': form, 'error': "Erro no preenchimento do formulário."} - ) - - # Atualiza ou cria funcionário - def funcionario_update(self, setor, fields, orgao, reg): - field_nome = (self.PRESIDENTE_NOME if setor == 'presidente' else - self.SERVIDOR_NOME) - - # Se não tem nome do contato (ou presidente), então não há nada a - # atualizar. Volta o reg inalterado. - if field_nome not in reg: - return reg - - funcionario = orgao.funcionario_set.filter( - setor=setor, - nome__iexact=reg[field_nome].strip() +# from sigi.shortcuts import render_to_pdf +# from sigi.apps.casas.reports import (CasasLegislativasLabels, +# CasasLegislativasLabelsSemPresidente) +# from sigi.apps.contatos.models import (UnidadeFederativa, Municipio, +# Mesorregiao, Microrregiao) +# from sigi.apps.ocorrencias.models import Ocorrencia +# from sigi.apps.parlamentares.reports import ParlamentaresLabels +# from sigi.apps.servicos.models import TipoServico + +class CasasSemConvenioReport(WeasyTemplateView): + template_name = "casas/casas_sem_convenio_pdf.html" + + def get_context_data(self, **kwargs): + # qs = Orgao.objects.filter(convenio=None).order_by( + # 'municipio__uf', + # 'nome' + # ) + qs = Orgao.objects.order_by( + 'municipio__uf', + 'nome' ) - if funcionario.count() == 0: - funcionario = Funcionario( - casa_legislativa=orgao, - nome=reg[field_nome].strip(), - setor=setor - ) - else: - funcionario = funcionario.first() #HACK: Sempre atualiza o primeiro - - for key in fields: - field_name = fields[key] - if key in reg: - value = reg[key].strip() - else: - value = "" - - if value != "": - if field_name == 'municipio_id': - if ',' in value: - municipio, uf = value.split(',') - else: - municipio = value - uf = reg[self.UF] - - try: - value = Municipio.objects.get( - nome__iexact=municipio.strip(), - uf__sigla=uf.strip()).pk - except: - value = None - reg[self.ERROS].append( - "Impossivel identificar o Municipio de " - "residencia do {contato}".format( - contato="Presidente" if setor == 'presidente' - else "Contato") - ) - continue - if field_name == 'redes_sociais': - value = value.replace(" ", "\r") - if field_name == 'data_nascimento': - sd = value.split('/') - if len(sd) < 3: - reg[self.ERROS].append( - "Data de nascimento do {contato} esta em um " - "formato nao reconhecido. Use DD/MM/AAAA".format( - contato="Presidente" if setor == 'presidente' - else "Contato" - ) - ) - continue - else: - value = "{ano}-{mes}-{dia}".format( - ano=sd[2], - mes=sd[1], - dia=sd[0] - ) - if value != getattr(funcionario, field_name): - setattr(funcionario, field_name, value) - try: - funcionario.save() - except Exception as e: - reg[self.ERROS].append( - "Erro salvando {contato}: '{message}'".format( - message=e.message, - contato="Presidente" if setor == 'presidente' - else "Contato") - ) - - return reg - - def importa(self, reader): - self.errors = [] - self.total_registros = 0 - - 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__search_text__icontains=nome_orgao, - municipio__uf__sigla=reg[self.UF] - ) - if orgao.count() == 0: - reg[self.ERROS].append("Nao existe orgao com esta identificacao") - self.errors.append(reg) - continue - elif orgao.count() > 1: - reg[self.ERROS].append("Existem {count} orgaos com esta mesma " - "identificacao").format(count=orgao.count()) - self.errors.append(reg) - continue - else: - orgao = orgao.get() - - # Atualiza os dados do órgão - for key in self.ORGAO_FIELDS: - field_name = self.ORGAO_FIELDS[key] - if key in reg: - value = reg[key].strip() - if key == self.ORGAO_TELEFONES: - for numero in value.split(";"): - numero = numero.strip() - try: - orgao.telefones.update_or_create(numero=numero) - except: - reg[self.ERROS].append( - 'Telefone {numero} não foi ' - 'atualizado'.format(numero=numero) - ) - elif value != "" and value != getattr(orgao, field_name): - setattr(orgao, field_name, value) - try: - orgao.save() - except Exception as e: - reg[self.ERROS].append( - "Erro salvando o orgao: '{message}'".format( - message=e.message) - ) - - # Atualiza o presidente - reg = self.funcionario_update("presidente", self.PRESIDENTE_FIELDS, - orgao, reg) - - # Atualiza o contato - reg = self.funcionario_update("outros", self.SERVIDOR_FIELDS, - orgao, reg) - - if len(reg[self.ERROS]) > 0: - self.errors.append(reg) - - return len(self.errors) == 0 + if self.request.GET: + qs = get_for_qs(self.request.GET, qs) + if not qs: + return HttpResponseRedirect('../') + + qs = qs.order_by('municipio__uf', 'nome') + return {'casas': qs, 'title': _("Casas sem convênio")} + +def get_for_qs(get, qs): + kwargs = {} + for k, v in get.items(): + if str(k) not in ('page', 'pop', 'q', '_popup', 'o', 'ot'): + kwargs[str(k)] = v + + # if 'convenio' in kwargs: + # if kwargs['convenio'] == 'SC': + # qs = qs.filter(convenio=None) + # elif kwargs['convenio'] == 'CC': + # qs = qs.exclude(convenio=None) + # else: + # qs = qs.filter(convenio__projeto_id=kwargs['convenio']) + + # qs = qs.distinct('municipio__uf__nome', 'nome') + # del(kwargs['convenio']) + + # if 'servico' in kwargs: + # if kwargs['servico'] == 'SS': + # qs = qs.filter(servico=None) + # elif kwargs['servico'] == 'CS': + # qs = qs.exclude(servico=None).filter( + # servico__data_desativacao__isnull=True) + # elif kwargs['servico'] == 'CR': + # qs = qs.exclude(servico__tipo_servico__modo='H') \ + # .exclude(servico=None) + # elif kwargs['servico'] == 'CH': + # qs = qs.filter( + # servico__tipo_servico__modo='H', + # servico__data_desativacao__isnull=True + # ) + # else: + # qs = qs.filter(servico__tipo_servico_id=kwargs['servico']) + + # qs = qs.distinct('municipio__uf__nome', 'nome') + + # del(kwargs['servico']) + + qs = qs.filter(**kwargs) + if 'o' in get: + qs = query_ordena(qs, get['o']) + + return qs # @param qs: queryset # @param o: (int) number of order field @@ -335,770 +112,1062 @@ def query_ordena(qs, o): return qs -def get_for_qs(get, qs): - """ - Verifica atributos do GET e retorna queryset correspondente - """ - kwargs = {} - for k, v in get.iteritems(): - if str(k) not in ('page', 'pop', 'q', '_popup', 'o', 'ot'): - kwargs[str(k)] = v - if 'convenio' in kwargs: - if kwargs['convenio'] == 'SC': - qs = qs.filter(convenio=None) - elif kwargs['convenio'] == 'CC': - qs = qs.exclude(convenio=None) - else: - qs = qs.filter(convenio__projeto_id=kwargs['convenio']) - - qs = qs.distinct('municipio__uf__nome', 'nome') - del(kwargs['convenio']) - - if 'servico' in kwargs: - if kwargs['servico'] == 'SS': - qs = qs.filter(servico=None) - elif kwargs['servico'] == 'CS': - qs = qs.exclude(servico=None).filter( - servico__data_desativacao__isnull=True) - elif kwargs['servico'] == 'CR': - qs = qs.exclude(servico__tipo_servico__modo='H') \ - .exclude(servico=None) - elif kwargs['servico'] == 'CH': - qs = qs.filter( - servico__tipo_servico__modo='H', - servico__data_desativacao__isnull=True - ) - else: - qs = qs.filter(servico__tipo_servico_id=kwargs['servico']) - - qs = qs.distinct('municipio__uf__nome', 'nome') - - del(kwargs['servico']) - qs = qs.filter(**kwargs) - if 'o' in get: - qs = query_ordena(qs, get['o']) +# class importa_casas(View): +# errors = [] +# total_registros = 0 + +# TIPO = 'tipo' +# MUNICIPIO = 'municipio' +# UF = 'uf' +# ORGAO_ENDERECO = 'orgao_endereco' +# ORGAO_BAIRRO = 'orgao_bairro' +# ORGAO_CEP = 'orgao_cep' +# ORGAO_EMAIL = 'orgao_email' +# ORGAO_PORTAL = 'orgao_portal' +# ORGAO_TELEFONES = 'orgao_telefones' +# PRESIDENTE_NOME = 'presidente_nome' +# PRESIDENTE_DATA_NASCIMENTO = 'presidente_data_nascimento' +# PRESIDENTE_TELEFONES = 'presidente_telefones' +# PRESIDENTE_EMAILS = 'presidente_emails' +# PRESIDENTE_ENDERECO = 'presidente_endereco' +# PRESIDENTE_MUNICIPIO = 'presidente_municipio' +# PRESIDENTE_BAIRRO = 'presidente_bairro' +# PRESIDENTE_CEP = 'presidente_cep' +# PRESIDENTE_REDES_SOCIAIS = 'presidente_redes_sociais' +# SERVIDOR_NOME = 'contato_nome' +# SERVIDOR_DATA_NASCIMENTO = 'contato_data_nascimento' +# SERVIDOR_TELEFONES = 'contato_telefones' +# SERVIDOR_EMAILS = 'contato_emails' +# SERVIDOR_ENDERECO = 'contato_endereco' +# SERVIDOR_MUNICIPIO = 'contato_municipio' +# SERVIDOR_BAIRRO = 'contato_bairro' +# SERVIDOR_CEP = 'contato_cep' +# SERVIDOR_REDES_SOCIAIS = 'contato_redes_sociais' +# ERROS = 'erros_importacao' + +# fieldnames = [TIPO, MUNICIPIO, UF, ORGAO_ENDERECO, ORGAO_BAIRRO, ORGAO_CEP, +# ORGAO_EMAIL, ORGAO_PORTAL, ORGAO_TELEFONES, PRESIDENTE_NOME, +# PRESIDENTE_DATA_NASCIMENTO, PRESIDENTE_TELEFONES, +# PRESIDENTE_EMAILS, PRESIDENTE_ENDERECO, PRESIDENTE_MUNICIPIO, +# PRESIDENTE_BAIRRO, PRESIDENTE_CEP, PRESIDENTE_REDES_SOCIAIS, +# SERVIDOR_NOME, SERVIDOR_DATA_NASCIMENTO, SERVIDOR_TELEFONES, +# SERVIDOR_EMAILS, SERVIDOR_ENDERECO, SERVIDOR_MUNICIPIO, +# SERVIDOR_BAIRRO, SERVIDOR_CEP, SERVIDOR_REDES_SOCIAIS, ERROS,] + +# ID_FIELDS = {TIPO, MUNICIPIO, UF} + +# ORGAO_FIELDS = { +# ORGAO_ENDERECO: 'logradouro', +# ORGAO_BAIRRO: 'bairro', +# ORGAO_CEP: 'cep', +# ORGAO_EMAIL: 'email', +# ORGAO_PORTAL: 'pagina_web', +# ORGAO_TELEFONES: 'telefones', +# } + +# PRESIDENTE_FIELDS = { +# PRESIDENTE_NOME: 'nome', +# PRESIDENTE_DATA_NASCIMENTO: 'data_nascimento', +# PRESIDENTE_TELEFONES: 'nota', +# PRESIDENTE_EMAILS: 'email', +# PRESIDENTE_ENDERECO: 'endereco', +# PRESIDENTE_MUNICIPIO: 'municipio_id', +# PRESIDENTE_BAIRRO: 'bairro', +# PRESIDENTE_CEP: 'cep', +# PRESIDENTE_REDES_SOCIAIS: 'redes_sociais', +# } + +# SERVIDOR_FIELDS = { +# SERVIDOR_NOME: 'nome', +# SERVIDOR_DATA_NASCIMENTO: 'data_nascimento', +# SERVIDOR_TELEFONES: 'nota', +# SERVIDOR_EMAILS: 'email', +# SERVIDOR_ENDERECO: 'endereco', +# SERVIDOR_MUNICIPIO: 'municipio_id', +# SERVIDOR_BAIRRO: 'bairro', +# SERVIDOR_CEP: 'cep', +# SERVIDOR_REDES_SOCIAIS: 'redes_sociais', +# } + +# def get(self, request): +# if not request.user.is_superuser: +# return HttpResponseForbidden() + +# form = AtualizaCasaForm() +# return render(request, 'casas/importar.html', {'form': form}) + +# def post(self, request): +# if not request.user.is_superuser: +# return HttpResponseForbidden() + +# form = AtualizaCasaForm(request.POST, request.FILES) + +# if form.is_valid(): +# file = form.cleaned_data['arquivo'] +# reader = csv.DictReader(file) +# if not self.ID_FIELDS.issubset(reader.fieldnames): +# return render( +# request, +# 'casas/importar.html', +# {'form': form, 'error': _("O arquivo não possui algum dos " +# "campos obrigatórios")} +# ) + +# if self.importa(reader): +# # Importação concluída com êxito +# return render( +# request, +# 'casas/importar_result.html', +# {'file_name': file.name, 'total': self.total_registros, +# 'com_erros': 0} +# ) +# else: +# # Importado com erros +# file_name = "casas-erros-{:%Y-%m-%d-%H%M}.csv".format( +# datetime.now()) +# fields = self.fieldnames +# for f in reader.fieldnames: +# if f not in fields: +# fields.append(f) +# with open(settings.MEDIA_ROOT+'/temp/'+file_name, "w+") as f: +# writer = csv.DictWriter(f, fieldnames=fields) +# writer.writeheader() +# writer.writerows(self.errors) +# return render( +# request, +# 'casas/importar_result.html', +# {'file_name': file.name, 'result_file': file_name, +# 'total': self.total_registros, +# 'com_erros': len(self.errors)} +# ) + +# response = HttpResponse(content_type='text/csv') +# response['Content-Disposition'] = ( +# 'attachment; filename="somefilename.csv"') +# return response +# else: +# return render( +# request, +# 'casas/importar.html', +# {'form': form, 'error': "Erro no preenchimento do formulário."} +# ) + +# # Atualiza ou cria funcionário +# def funcionario_update(self, setor, fields, orgao, reg): +# field_nome = (self.PRESIDENTE_NOME if setor == 'presidente' else +# self.SERVIDOR_NOME) + +# # Se não tem nome do contato (ou presidente), então não há nada a +# # atualizar. Volta o reg inalterado. +# if field_nome not in reg: +# return reg + +# funcionario = orgao.funcionario_set.filter( +# setor=setor, +# nome__iexact=reg[field_nome].strip() +# ) + +# if funcionario.count() == 0: +# funcionario = Funcionario( +# casa_legislativa=orgao, +# nome=reg[field_nome].strip(), +# setor=setor +# ) +# else: +# funcionario = funcionario.first() #HACK: Sempre atualiza o primeiro + +# for key in fields: +# field_name = fields[key] +# if key in reg: +# value = reg[key].strip() +# else: +# value = "" + +# if value != "": +# if field_name == 'municipio_id': +# if ',' in value: +# municipio, uf = value.split(',') +# else: +# municipio = value +# uf = reg[self.UF] + +# try: +# value = Municipio.objects.get( +# nome__iexact=municipio.strip(), +# uf__sigla=uf.strip()).pk +# except: +# value = None +# reg[self.ERROS].append( +# "Impossivel identificar o Municipio de " +# "residencia do {contato}".format( +# contato="Presidente" if setor == 'presidente' +# else "Contato") +# ) +# continue +# if field_name == 'redes_sociais': +# value = value.replace(" ", "\r") +# if field_name == 'data_nascimento': +# sd = value.split('/') +# if len(sd) < 3: +# reg[self.ERROS].append( +# "Data de nascimento do {contato} esta em um " +# "formato nao reconhecido. Use DD/MM/AAAA".format( +# contato="Presidente" if setor == 'presidente' +# else "Contato" +# ) +# ) +# continue +# else: +# value = "{ano}-{mes}-{dia}".format( +# ano=sd[2], +# mes=sd[1], +# dia=sd[0] +# ) +# if value != getattr(funcionario, field_name): +# setattr(funcionario, field_name, value) +# try: +# funcionario.save() +# except Exception as e: +# reg[self.ERROS].append( +# "Erro salvando {contato}: '{message}'".format( +# message=e.message, +# contato="Presidente" if setor == 'presidente' +# else "Contato") +# ) + +# return reg + +# def importa(self, reader): +# self.errors = [] +# self.total_registros = 0 + +# 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__search_text__icontains=nome_orgao, +# municipio__uf__sigla=reg[self.UF] +# ) +# if orgao.count() == 0: +# reg[self.ERROS].append("Nao existe orgao com esta identificacao") +# self.errors.append(reg) +# continue +# elif orgao.count() > 1: +# reg[self.ERROS].append("Existem {count} orgaos com esta mesma " +# "identificacao").format(count=orgao.count()) +# self.errors.append(reg) +# continue +# else: +# orgao = orgao.get() + +# # Atualiza os dados do órgão +# for key in self.ORGAO_FIELDS: +# field_name = self.ORGAO_FIELDS[key] +# if key in reg: +# value = reg[key].strip() +# if key == self.ORGAO_TELEFONES: +# for numero in value.split(";"): +# numero = numero.strip() +# try: +# orgao.telefones.update_or_create(numero=numero) +# except: +# reg[self.ERROS].append( +# 'Telefone {numero} não foi ' +# 'atualizado'.format(numero=numero) +# ) +# elif value != "" and value != getattr(orgao, field_name): +# setattr(orgao, field_name, value) +# try: +# orgao.save() +# except Exception as e: +# reg[self.ERROS].append( +# "Erro salvando o orgao: '{message}'".format( +# message=e.message) +# ) + +# # Atualiza o presidente +# reg = self.funcionario_update("presidente", self.PRESIDENTE_FIELDS, +# orgao, reg) + +# # Atualiza o contato +# reg = self.funcionario_update("outros", self.SERVIDOR_FIELDS, +# orgao, reg) + +# if len(reg[self.ERROS]) > 0: +# self.errors.append(reg) + +# return len(self.errors) == 0 + + + +# def get_for_qs(get, qs): +# """ +# Verifica atributos do GET e retorna queryset correspondente +# """ +# kwargs = {} +# for k, v in get.iteritems(): +# if str(k) not in ('page', 'pop', 'q', '_popup', 'o', 'ot'): +# kwargs[str(k)] = v + +# if 'convenio' in kwargs: +# if kwargs['convenio'] == 'SC': +# qs = qs.filter(convenio=None) +# elif kwargs['convenio'] == 'CC': +# qs = qs.exclude(convenio=None) +# else: +# qs = qs.filter(convenio__projeto_id=kwargs['convenio']) + +# qs = qs.distinct('municipio__uf__nome', 'nome') +# del(kwargs['convenio']) + +# if 'servico' in kwargs: +# if kwargs['servico'] == 'SS': +# qs = qs.filter(servico=None) +# elif kwargs['servico'] == 'CS': +# qs = qs.exclude(servico=None).filter( +# servico__data_desativacao__isnull=True) +# elif kwargs['servico'] == 'CR': +# qs = qs.exclude(servico__tipo_servico__modo='H') \ +# .exclude(servico=None) +# elif kwargs['servico'] == 'CH': +# qs = qs.filter( +# servico__tipo_servico__modo='H', +# servico__data_desativacao__isnull=True +# ) +# else: +# qs = qs.filter(servico__tipo_servico_id=kwargs['servico']) + +# qs = qs.distinct('municipio__uf__nome', 'nome') + +# del(kwargs['servico']) + +# qs = qs.filter(**kwargs) +# if 'o' in get: +# qs = query_ordena(qs, get['o']) + +# return qs + + +# def carrinhoOrGet_for_qs(request): +# """ +# Verifica se existe casas na sessão se não verifica get e retorna qs correspondente. +# """ +# if 'carrinho_casas' in request.session: +# ids = request.session['carrinho_casas'] +# qs = Orgao.objects.filter(pk__in=ids) +# else: +# qs = Orgao.objects.all() +# if request.GET: +# qs = get_for_qs(request.GET, qs) +# return qs + + +# def adicionar_casas_carrinho(request, queryset=None, id=None): +# if request.method == 'POST': +# ids_selecionados = request.POST.getlist('_selected_action') +# if 'carrinho_casas' not in request.session: +# request.session['carrinho_casas'] = ids_selecionados +# else: +# lista = request.session['carrinho_casas'] +# # Verifica se id já não está adicionado +# for id in ids_selecionados: +# if id not in lista: +# lista.append(id) +# request.session['carrinho_casas'] = lista + + +# @login_required +# def visualizar_carrinho(request): + +# qs = carrinhoOrGet_for_qs(request) + +# paginator = Paginator(qs, 100) + +# # Make sure page request is an int. If not, deliver first page. +# # Esteja certo de que o `page request` é um inteiro. Se não, mostre a primeira página. +# try: +# page = int(request.GET.get('page', '1')) +# except ValueError: +# page = 1 + +# # Se o page request (9999) está fora da lista, mostre a última página. +# try: +# paginas = paginator.page(page) +# except (EmptyPage, InvalidPage): +# paginas = paginator.page(paginator.num_pages) + +# carrinhoIsEmpty = not('carrinho_casas' in request.session) + +# return render( +# request, +# 'casas/carrinho.html', +# { +# 'carIsEmpty': carrinhoIsEmpty, +# 'paginas': paginas, +# 'query_str': '?' + request.META['QUERY_STRING'] +# } +# ) + + +# @login_required +# def excluir_carrinho(request): +# if 'carrinho_casas' in request.session: +# del request.session['carrinho_casas'] +# messages.info(request, 'O carrinho foi esvaziado') +# return HttpResponseRedirect('../../') + + +# @login_required +# def deleta_itens_carrinho(request): +# if request.method == 'POST': +# ids_selecionados = request.POST.getlist('_selected_action') +# if 'carrinho_casas' in request.session: +# lista = request.session['carrinho_casas'] +# for item in ids_selecionados: +# lista.remove(item) +# if lista: +# request.session['carrinho_casas'] = lista +# else: +# del lista +# del request.session['carrinho_casas'] + +# return HttpResponseRedirect('.') + + +# # @login_required +# # def labels_report(request, id=None, tipo=None, formato='3x9_etiqueta'): +# # """ TODO: adicionar suporte para resultado de pesquisa do admin. +# # """ + +# # if request.POST: +# # if 'tipo_etiqueta' in request.POST: +# # tipo = request.POST['tipo_etiqueta'] +# # if 'tamanho_etiqueta' in request.POST: +# # formato = request.POST['tamanho_etiqueta'] + +# # if tipo == 'sem_presidente': +# # return labels_report_sem_presidente(request, id, formato) + +# # if id: +# # qs = Orgao.objects.filter(pk=id) +# # else: +# # qs = carrinhoOrGet_for_qs(request) + +# # if not qs: +# # return HttpResponseRedirect('../') + +# # response = HttpResponse(content_type='application/pdf') +# # response['Content-Disposition'] = 'attachment; filename=casas.pdf' +# # report = CasasLegislativasLabels(queryset=qs, formato=formato) +# # report.generate_by(PDFGenerator, filename=response) - return qs +# # return response + + +# # @login_required +# # def labels_report_parlamentar(request, id=None, formato='3x9_etiqueta'): +# # """ TODO: adicionar suporte para resultado de pesquisa do admin. +# # """ +# # if request.POST: +# # if 'tamanho_etiqueta' in request.POST: +# # formato = request.POST['tamanho_etiqueta'] -def carrinhoOrGet_for_qs(request): - """ - Verifica se existe casas na sessão se não verifica get e retorna qs correspondente. - """ - if 'carrinho_casas' in request.session: - ids = request.session['carrinho_casas'] - qs = Orgao.objects.filter(pk__in=ids) - else: - qs = Orgao.objects.all() - if request.GET: - qs = get_for_qs(request.GET, qs) - return qs +# # if id: +# # legislaturas = [c.legislatura_set.latest('data_inicio') for c in Orgao.objects.filter(pk__in=id, legislatura__id__isnull=False).distinct()] +# # mandatos = reduce(lambda x, y: x | y, [l.mandato_set.all() for l in legislaturas]) +# # parlamentares = [m.parlamentar for m in mandatos] +# # qs = parlamentares +# # else: +# # qs = carrinhoOrGet_for_parlamentar_qs(request) -def adicionar_casas_carrinho(request, queryset=None, id=None): - if request.method == 'POST': - ids_selecionados = request.POST.getlist('_selected_action') - if 'carrinho_casas' not in request.session: - request.session['carrinho_casas'] = ids_selecionados - else: - lista = request.session['carrinho_casas'] - # Verifica se id já não está adicionado - for id in ids_selecionados: - if id not in lista: - lista.append(id) - request.session['carrinho_casas'] = lista - - -@login_required -def visualizar_carrinho(request): - - qs = carrinhoOrGet_for_qs(request) - - paginator = Paginator(qs, 100) - - # Make sure page request is an int. If not, deliver first page. - # Esteja certo de que o `page request` é um inteiro. Se não, mostre a primeira página. - try: - page = int(request.GET.get('page', '1')) - except ValueError: - page = 1 - - # Se o page request (9999) está fora da lista, mostre a última página. - try: - paginas = paginator.page(page) - except (EmptyPage, InvalidPage): - paginas = paginator.page(paginator.num_pages) - - carrinhoIsEmpty = not('carrinho_casas' in request.session) - - return render( - request, - 'casas/carrinho.html', - { - 'carIsEmpty': carrinhoIsEmpty, - 'paginas': paginas, - 'query_str': '?' + request.META['QUERY_STRING'] - } - ) - - -@login_required -def excluir_carrinho(request): - if 'carrinho_casas' in request.session: - del request.session['carrinho_casas'] - messages.info(request, 'O carrinho foi esvaziado') - return HttpResponseRedirect('../../') - - -@login_required -def deleta_itens_carrinho(request): - if request.method == 'POST': - ids_selecionados = request.POST.getlist('_selected_action') - if 'carrinho_casas' in request.session: - lista = request.session['carrinho_casas'] - for item in ids_selecionados: - lista.remove(item) - if lista: - request.session['carrinho_casas'] = lista - else: - del lista - del request.session['carrinho_casas'] - - return HttpResponseRedirect('.') - - -@login_required -def labels_report(request, id=None, tipo=None, formato='3x9_etiqueta'): - """ TODO: adicionar suporte para resultado de pesquisa do admin. - """ - - if request.POST: - if 'tipo_etiqueta' in request.POST: - tipo = request.POST['tipo_etiqueta'] - if 'tamanho_etiqueta' in request.POST: - formato = request.POST['tamanho_etiqueta'] - - if tipo == 'sem_presidente': - return labels_report_sem_presidente(request, id, formato) - - if id: - qs = Orgao.objects.filter(pk=id) - else: - qs = carrinhoOrGet_for_qs(request) - - if not qs: - return HttpResponseRedirect('../') - - response = HttpResponse(content_type='application/pdf') - response['Content-Disposition'] = 'attachment; filename=casas.pdf' - report = CasasLegislativasLabels(queryset=qs, formato=formato) - report.generate_by(PDFGenerator, filename=response) - - return response - - -@login_required -def labels_report_parlamentar(request, id=None, formato='3x9_etiqueta'): - """ TODO: adicionar suporte para resultado de pesquisa do admin. - """ - - if request.POST: - if 'tamanho_etiqueta' in request.POST: - formato = request.POST['tamanho_etiqueta'] - - if id: - legislaturas = [c.legislatura_set.latest('data_inicio') for c in Orgao.objects.filter(pk__in=id, legislatura__id__isnull=False).distinct()] - mandatos = reduce(lambda x, y: x | y, [l.mandato_set.all() for l in legislaturas]) - parlamentares = [m.parlamentar for m in mandatos] - qs = parlamentares - - else: - qs = carrinhoOrGet_for_parlamentar_qs(request) - - if not qs: - return HttpResponseRedirect('../') - - response = HttpResponse(content_type='application/pdf') - response['Content-Disposition'] = 'attachment; filename=casas.pdf' - report = ParlamentaresLabels(queryset=qs, formato=formato) - report.generate_by(PDFGenerator, filename=response) - - return response - - -def carrinhoOrGet_for_parlamentar_qs(request): - """ - Verifica se existe parlamentares na sessão se não verifica get e retorna qs correspondente. - """ - if 'carrinho_casas' in request.session: - ids = request.session['carrinho_casas'] - legislaturas = [c.legislatura_set.latest('data_inicio') for c in Orgao.objects.filter(pk__in=ids, legislatura__id__isnull=False).distinct()] - mandatos = reduce(lambda x, y: x | y, [l.mandato_set.all() for l in legislaturas]) - parlamentares = [m.parlamentar for m in mandatos] - qs = parlamentares - else: - legislaturas = [c.legislatura_set.latest('data_inicio') for c in Orgao.objects.all().distinct()] - mandatos = reduce(lambda x, y: x | y, [l.mandato_set.all() for l in legislaturas]) - parlamentares = [m.parlamentar for m in mandatos] - qs = parlamentares - if request.GET: - qs = get_for_qs(request.GET, qs) - return qs +# # if not qs: +# # return HttpResponseRedirect('../') +# # response = HttpResponse(content_type='application/pdf') +# # response['Content-Disposition'] = 'attachment; filename=casas.pdf' +# # report = ParlamentaresLabels(queryset=qs, formato=formato) +# # report.generate_by(PDFGenerator, filename=response) -@login_required -def labels_report_sem_presidente(request, id=None, formato='2x5_etiqueta'): - """ TODO: adicionar suporte para resultado de pesquisa do admin. - """ +# # return response - if id: - qs = Orgao.objects.filter(pk=id) - else: - qs = carrinhoOrGet_for_qs(request) - if not qs: - return HttpResponseRedirect('../') +# def carrinhoOrGet_for_parlamentar_qs(request): +# """ +# Verifica se existe parlamentares na sessão se não verifica get e retorna qs correspondente. +# """ +# if 'carrinho_casas' in request.session: +# ids = request.session['carrinho_casas'] +# legislaturas = [c.legislatura_set.latest('data_inicio') for c in Orgao.objects.filter(pk__in=ids, legislatura__id__isnull=False).distinct()] +# mandatos = reduce(lambda x, y: x | y, [l.mandato_set.all() for l in legislaturas]) +# parlamentares = [m.parlamentar for m in mandatos] +# qs = parlamentares +# else: +# legislaturas = [c.legislatura_set.latest('data_inicio') for c in Orgao.objects.all().distinct()] +# mandatos = reduce(lambda x, y: x | y, [l.mandato_set.all() for l in legislaturas]) +# parlamentares = [m.parlamentar for m in mandatos] +# qs = parlamentares +# if request.GET: +# qs = get_for_qs(request.GET, qs) +# return qs - response = HttpResponse(content_type='application/pdf') - response['Content-Disposition'] = 'attachment; filename=casas.pdf' - report = CasasLegislativasLabelsSemPresidente(queryset=qs, formato=formato) - report.generate_by(PDFGenerator, filename=response) - return response +# @login_required +# def labels_report_sem_presidente(request, id=None, formato='2x5_etiqueta'): +# """ TODO: adicionar suporte para resultado de pesquisa do admin. +# """ +# if id: +# qs = Orgao.objects.filter(pk=id) +# else: +# qs = carrinhoOrGet_for_qs(request) -@login_required -def report(request, id=None, tipo=None): +# if not qs: +# return HttpResponseRedirect('../') - if request.POST: - if 'tipo_relatorio' in request.POST: - tipo = request.POST['tipo_relatorio'] +# response = HttpResponse(content_type='application/pdf') +# response['Content-Disposition'] = 'attachment; filename=casas.pdf' +# report = CasasLegislativasLabelsSemPresidente(queryset=qs, formato=formato) +# report.generate_by(PDFGenerator, filename=response) - if tipo == 'completo': - return report_complete(request, id) +# return response - if id: - qs = Orgao.objects.filter(pk=id) - else: - qs = carrinhoOrGet_for_qs(request) - - if not qs: - return HttpResponseRedirect('../') - - qs = qs.order_by('municipio__uf', 'nome') - context = {'casas': qs, 'title': _("Relação de Casas Legislativas")} - - return render_to_pdf('casas/report_pdf.html', context) - - -@login_required -def report_complete(request, id=None): - - if id: - qs = Orgao.objects.filter(pk=id) - else: - qs = carrinhoOrGet_for_qs(request) - - if not qs: - return HttpResponseRedirect('../') - - return render_to_pdf('casas/report_complete_pdf.html', {'casas': qs}) - - -@login_required -def casas_sem_convenio_report(request): - qs = Orgao.objects.filter(convenio=None).order_by('municipio__uf', 'nome') - - if request.GET: - qs = get_for_qs(request.GET, qs) - if not qs: - return HttpResponseRedirect('../') - - qs = qs.order_by('municipio__uf', 'nome') - context = {'casas': qs, 'title': _("Casas sem convênio")} - - return render_to_pdf('casas/report_pdf.html', context) - - -@login_required -def export_csv(request): - response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = 'attachment; filename=casas.csv' - - writer = csv.writer(response) - - casas = carrinhoOrGet_for_qs(request) - if not casas or not request.POST: - return HttpResponseRedirect('../') - - atributos = request.POST.getlist("itens_csv_selected") - - try: - atributos.insert(atributos.index(_('Município')), _('UF')) - except ValueError: - pass - - atributos2 = [s.encode("utf-8") for s in atributos] - - writer.writerow(atributos2) - - for casa in casas: - lista = [] - contatos = casa.funcionario_set.exclude(nome="") - for atributo in atributos: - if _("CNPJ") == atributo: - lista.append(casa.cnpj.encode("utf-8")) - elif _("Código IBGE") == atributo: - lista.append(str(casa.municipio.codigo_ibge).encode("utf-8")) - elif _("Código TSE") == atributo: - lista.append(str(casa.municipio.codigo_tse).encode("utf-8")) - elif _("Nome") == atributo: - lista.append(casa.nome.encode("utf-8")) - elif _("Município") == atributo: - lista.append(unicode(casa.municipio.uf.sigla).encode("utf-8")) - lista.append(unicode(casa.municipio.nome).encode("utf-8")) - elif _("Presidente") == atributo: - # TODO: Esse encode deu erro em 25/04/2012. Comentei para que o usuário pudesse continuar seu trabalho - # É preciso descobrir o porque do erro e fazer a correção definitiva. - # lista.append(str(casa.presidente or "").encode("utf-8")) - lista.append(str(casa.presidente or "")) - elif _("Logradouro") == atributo: - lista.append(casa.logradouro.encode("utf-8")) - elif _("Bairro") == atributo: - lista.append(casa.bairro.encode("utf-8")) - elif _("CEP") == atributo: - lista.append(casa.cep.encode("utf-8")) - elif _("Telefone") == atributo: - lista.append(str(casa.telefone or "")) - elif _("Página web") == atributo: - lista.append(casa.pagina_web.encode("utf-8")) - elif _("Email") == atributo: - lista.append(casa.email.encode("utf-8")) - elif _("Número de parlamentares") == atributo: - lista.append(casa.total_parlamentares) - elif _("Última alteração de endereco") == atributo: - lista.append(casa.ult_alt_endereco) - elif _("Servicos SEIT") == atributo: - lista.append(", ".join([s.tipo_servico.nome.encode('utf-8') - for s in casa.servico_set.filter( - data_desativacao__isnull=True)]) - ) - elif _("Nome contato") == atributo: - if contatos: - nomes = ", ".join([c.nome for c in contatos]) - lista.append(nomes.encode("utf-8")) - else: - lista.append('') - elif _("Cargo contato") == atributo: - if contatos: - cargos = ", ".join([c.cargo if c.cargo else "?" - for c in contatos]) - lista.append(cargos.encode("utf-8")) - else: - lista.append('') - elif _("Email contato") == atributo: - if contatos: - emails = ", ".join([c.email if c.email else "?" - for c in contatos]) - lista.append(emails.encode("utf-8")) - else: - lista.append('') - else: - pass - - writer.writerow(lista) - - return response - - -@login_required -def portfolio(request): - page = request.GET.get('page', 1) - tipo = request.GET.get('tipo', None) - regiao = request.GET.get('regiao', None) - uf_id = request.GET.get('uf', None) - meso_id = request.GET.get('meso', None) - micro_id = request.GET.get('micro', None) - - data = {} - data['errors'] = [] - data['messages'] = [] - data['regioes'] = UnidadeFederativa.REGIAO_CHOICES - data['tipos_casas'] = TipoOrgao.objects.all() - casas = None - gerente = None - - if tipo: - data['tipo'] = tipo - - if micro_id: - microrregiao = get_object_or_404(Microrregiao, pk=micro_id) - mesorregiao = microrregiao.mesorregiao - uf = mesorregiao.uf - data['regiao'] = uf.regiao - data['uf_id'] = uf.pk - data['meso_id'] = mesorregiao.pk - data['micro_id'] = microrregiao.pk - data['ufs'] = UnidadeFederativa.objects.filter(regiao=uf.regiao) - data['mesorregioes'] = uf.mesorregiao_set.all() - data['microrregioes'] = mesorregiao.microrregiao_set.all() - data['form'] = PortfolioForm( - _('Atribuir casas da microrregiao {name} para').format( - name=unicode(microrregiao)) - ) - data['querystring'] = 'micro={0}'.format(microrregiao.pk) - casas = Orgao.objects.filter( - municipio__microrregiao=microrregiao - ) - elif meso_id: - mesorregiao = get_object_or_404(Mesorregiao, pk=meso_id) - uf = mesorregiao.uf - data['regiao'] = uf.regiao - data['uf_id'] = uf.pk - data['meso_id'] = mesorregiao.pk - data['ufs'] = UnidadeFederativa.objects.filter(regiao=uf.regiao) - data['mesorregioes'] = uf.mesorregiao_set.all() - data['microrregioes'] = mesorregiao.microrregiao_set.all() - data['form'] = PortfolioForm( - _('Atribuir casas da mesorregiao {name} para').format( - name=unicode(mesorregiao))) - data['querystring'] = 'meso={0}'.format(mesorregiao.pk) - casas = Orgao.objects.filter( - municipio__microrregiao__mesorregiao=mesorregiao - ) - elif uf_id: - uf = get_object_or_404(UnidadeFederativa, pk=uf_id) - data['regiao'] = uf.regiao - data['uf_id'] = uf.pk - data['ufs'] = UnidadeFederativa.objects.filter(regiao=uf.regiao) - data['mesorregioes'] = uf.mesorregiao_set.all() - data['form'] = PortfolioForm( - _('Atribuir casas do estado {name} para').format( - name=unicode(uf))) - data['querystring'] = 'uf={0}'.format(uf.pk) - casas = Orgao.objects.filter(municipio__uf=uf) - elif regiao: - data['regiao'] = regiao - data['ufs'] = UnidadeFederativa.objects.filter(regiao=regiao) - data['form'] = PortfolioForm( - _('Atribuir casas da região {name} para').format( - name=[x[1] for x in UnidadeFederativa.REGIAO_CHOICES if - x[0] == regiao][0])) - data['querystring'] = 'regiao={0}'.format(regiao) - casas = Orgao.objects.filter(municipio__uf__regiao=regiao) - - if casas: - casas = casas.order_by('municipio__uf', - 'municipio__microrregiao__mesorregiao', - 'municipio__microrregiao', 'municipio') - - casas.prefetch_related('municipio', 'municipio__uf', - 'municipio__microrregiao', - 'municipio__microrregiao__mesorregiao', - 'gerentes_interlegis') - - if tipo: - casas = casas.filter(tipo__sigla=tipo) - data['querystring'] += "&tipo={0}".format(tipo) - - if request.method == 'POST': - form = PortfolioForm(data=request.POST) - if form.is_valid(): - gerente = form.cleaned_data['gerente'] - acao = form.cleaned_data['acao'] - - count = casas.count() - - if acao == 'ADD': - gerente.casas_que_gerencia.add(*casas) - data['messages'].append(ungettext( - "{count} casa adicionada para {gerente}", - "{count} casas adicionadas para {gerente}", - count).format(count=count,gerente=gerente.nome_completo) - ) - elif acao == 'DEL': - gerente.casas_que_gerencia.remove(*casas) - data['messages'].append(ungettext( - "{count} casa removida de {gerente}", - "{count} casas removidas de {gerente}", - count).format(count=count,gerente=gerente.nome_completo) - ) - else: - data['errors'].append(_("Ação não definida")) - else: - data['errors'].append(_("Dados inválidos")) - - paginator = Paginator(casas, 30) - try: - pagina = paginator.page(page) - except (EmptyPage, InvalidPage): - pagina = paginator.page(paginator.num_pages) - data['page_obj'] = pagina - - return render(request, 'casas/portfolio.html', data) - - -def resumo_carteira(casas): - regioes = {r[0]: 0 for r in UnidadeFederativa.REGIAO_CHOICES} - regioes['total'] = 0 - total = regioes.copy() - sem_produto = regioes.copy() - tipos_servico = TipoServico.objects.all() - dados = {ts.id: regioes.copy() for ts in tipos_servico} - - for r in casas.values('municipio__uf__regiao').annotate(quantidade=Count('id')).order_by(): - regiao = r['municipio__uf__regiao'] - quantidade = r['quantidade'] - total[regiao] = quantidade - total['total'] += quantidade - - for r in casas.values('municipio__uf__regiao', 'servico__tipo_servico__id').annotate(quantidade=Count('id')).order_by(): - regiao = r['municipio__uf__regiao'] - servico = r['servico__tipo_servico__id'] - quantidade = r['quantidade'] - if servico is None: - sem_produto[regiao] = quantidade - sem_produto['total'] += quantidade - else: - dados[servico][regiao] = quantidade - dados[servico]['total'] += quantidade - - dados_ocorrencia = { - 'registradas': regioes.copy(), - 'pendentes': regioes.copy(), - 'sem': regioes.copy(), - 'media': regioes.copy(), - } - - for r in casas.values('ocorrencia__status', 'municipio__uf__regiao').annotate(quantidade=Count('id')).order_by(): - status = r['ocorrencia__status'] - regiao = r['municipio__uf__regiao'] - quantidade = r['quantidade'] - if status is None: - dados_ocorrencia['sem'][regiao] += quantidade - dados_ocorrencia['sem']['total'] += quantidade - else: - dados_ocorrencia['registradas'][regiao] += quantidade - dados_ocorrencia['registradas']['total'] += quantidade - if status in [Ocorrencia.STATUS_ABERTO, Ocorrencia.STATUS_REABERTO]: - dados_ocorrencia['pendentes'][regiao] += quantidade - dados_ocorrencia['pendentes']['total'] += quantidade - - for r in regioes: - if (total[r] - dados_ocorrencia['sem'][r]) == 0: - dados_ocorrencia['media'][r] = 0 - else: - dados_ocorrencia['media'][r] = (1.0 * dados_ocorrencia['registradas'][r] / (total[r] - dados_ocorrencia['sem'][r])) - - resumo = [[_("Item"), _("Total nacional")] + [r[1] for r in UnidadeFederativa.REGIAO_CHOICES]] - resumo.append([_("Casas em sua carteira"), total['total']] + [total[r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) - resumo.append({'subtitle': _("Uso dos produtos Interlegis")}) - resumo.append([_("Casas sem nenhum produto"), sem_produto['total']] + [sem_produto[r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) - resumo.extend([[ts.nome, dados[ts.id]['total']] + [dados[ts.id][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES] for ts in tipos_servico]) - resumo.append({'subtitle': _("Registros no sistema de ocorrências")}) - resumo.append([_("Casas que nunca registraram ocorrências"), dados_ocorrencia['sem']['total']] + [dados_ocorrencia['sem'][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) - resumo.append([_("Total de ocorrências registradas"), dados_ocorrencia['registradas']['total']] + [dados_ocorrencia['registradas'][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) - resumo.append([_("Total de ocorrências pendentes"), dados_ocorrencia['pendentes']['total']] + [dados_ocorrencia['pendentes'][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) - resumo.append([_("Média de ocorrências por casa"), round(dados_ocorrencia['media']['total'], 2)] + [round(dados_ocorrencia['media'][r[0]], 2) for r in UnidadeFederativa.REGIAO_CHOICES]) - - return resumo - - -def casas_carteira(request, casas, context): - servicos = request.GET.getlist('servico') - sigla_regiao = request.GET.get('r', None) - sigla_uf = request.GET.get('uf', None) - meso_id = request.GET.get('meso', None) - micro_id = request.GET.get('micro', None) - servicos = request.GET.getlist('servico') - tipos_servico = context['servicos'] - - context['qs_regiao'] = '' - - if micro_id is not None: - context['micro'] = get_object_or_404(Microrregiao, pk=micro_id) - context['qs_regiao'] = 'micro=%s' % micro_id - context['meso'] = context['micro'].mesorregiao - context['uf'] = context['meso'].uf - context['regiao'] = context['uf'].regiao - casas = casas.filter(municipio__microrregiao=context['micro']) - elif meso_id is not None: - context['meso'] = get_object_or_404(Mesorregiao, pk=meso_id) - context['qs_regiao'] = 'meso=%s' % meso_id - context['uf'] = context['meso'].uf - context['regiao'] = context['uf'].regiao - casas = casas.filter(municipio__microrregiao__mesorregiao=context['meso']) - elif sigla_uf is not None: - context['uf'] = get_object_or_404(UnidadeFederativa, sigla=sigla_uf) - context['qs_regiao'] = 'uf=%s' % sigla_uf - context['regiao'] = context['uf'].regiao - casas = casas.filter(municipio__uf=context['uf']) - elif sigla_regiao is not None: - context['regiao'] = sigla_regiao - context['qs_regiao'] = 'r=%s' % sigla_regiao - casas = casas.filter(municipio__uf__regiao=sigla_regiao) - - if 'regiao' in context: - context['ufs'] = UnidadeFederativa.objects.filter(regiao=context['regiao']) - - todos_servicos = ['_none_'] + [s.sigla for s in tipos_servico] - - if not servicos or set(servicos) == set(todos_servicos): - servicos = todos_servicos - context['qs_servico'] = '' - else: - if '_none_' in servicos: - casas = casas.filter(Q(servico=None) | Q(servico__tipo_servico__sigla__in=servicos)) - else: - casas = casas.filter(servico__tipo_servico__sigla__in=servicos) - casas = casas.distinct('nome', 'municipio__uf') - context['qs_servico'] = "&".join(['servico=%s' % s for s in servicos]) - - context['servicos_check'] = servicos - - casas = casas.select_related('municipio', 'municipio__uf', 'municipio__microrregiao', 'municipio__microrregiao__mesorregiao').prefetch_related('servico_set') - - return casas, context - - -@login_required -def painel_relacionamento(request): - page = request.GET.get('page', 1) - snippet = request.GET.get('snippet', '') - seletor = request.GET.get('s', None) - servidor = request.GET.get('servidor', None) - fmt = request.GET.get('f', 'html') - - if servidor is None: - gerente = request.user.servidor - elif servidor == '_all': - gerente = None - else: - gerente = get_object_or_404(Servidor, pk=servidor) - - if gerente is not None: - casas = gerente.casas_que_gerencia.all() - - if gerente is None or not casas.exists(): - casas = Orgao.objects.exclude(gerentes_interlegis=None) - gerente = None - - tipos_servico = TipoServico.objects.all() - regioes = UnidadeFederativa.REGIAO_CHOICES - - context = { - 'seletor': seletor, - 'snippet': snippet, - 'regioes': regioes, - 'servicos': tipos_servico, - 'gerentes': Servidor.objects.exclude(casas_que_gerencia=None), - 'gerente': gerente, - 'qs_servidor': ('servidor=%s' % gerente.pk) if gerente else '', - } - - if snippet != 'lista': - context['resumo'] = resumo_carteira(casas) - - if snippet != 'resumo': - casas, context = casas_carteira(request, casas, context) - paginator = Paginator(casas, 30) - try: - pagina = paginator.page(page) - except (EmptyPage, InvalidPage): - pagina = paginator.page(paginator.num_pages) - context['page_obj'] = pagina - - if snippet == 'lista': - if fmt == 'csv': - response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = 'attachment; filename=casas.csv' - writer = csv.writer(response) - writer.writerow([ - _("Casa legislativa").encode('utf8'), - _("Região").encode('utf8'), - _("Estado").encode('utf8'), - _("Mesorregião").encode('utf8'), - _("Microrregião").encode('utf8'), - _("Gerentes Interlegis").encode('utf8'), - _("Serviços").encode('utf8'), - ]) - for c in casas: - writer.writerow([ - c.nome.encode('utf8'), - c.municipio.uf.get_regiao_display().encode('utf8'), - c.municipio.uf.sigla.encode('utf8'), - c.municipio.microrregiao.mesorregiao.nome.encode('utf8'), - c.municipio.microrregiao.nome.encode('utf8'), - c.lista_gerentes(fmt='lista').encode('utf8'), - (", ".join([s.tipo_servico.nome for s in c.servico_set.filter(data_desativacao__isnull=True)])).encode('utf8'), - ]) - return response - return render(request, 'casas/lista_casas_carteira_snippet.html', context) - if snippet == 'resumo': - return render(request, 'casas/resumo_carteira_snippet.html', context) - - return render(request, 'casas/painel.html', context) - -@login_required -def gerentes_interlegis(request): - formato = request.GET.get('fmt', 'html') - inclui_casas = (request.GET.get('casas', 'no') == 'yes') - gerentes = Servidor.objects.exclude( - casas_que_gerencia=None).select_related('casas_que_gerencia') - dados = [] - for gerente in gerentes: - row = {'gerente': gerente, 'ufs': []} - for uf in (gerente.casas_que_gerencia.distinct('municipio__uf__sigla') - .order_by('municipio__uf__sigla') - .values_list('municipio__uf__sigla', 'municipio__uf__nome') - ): - row['ufs'].append(( - uf[0], - uf[1], - gerente.casas_que_gerencia.filter(municipio__uf__sigla=uf[0]) - )) - dados.append(row) - - if formato == 'pdf': - return render_to_pdf( - 'casas/gerentes_interlegis_pdf.html', - {'gerentes': dados} - ) - elif formato == 'csv': - response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = ('attachment; ' - 'filename="gerentes_interlegis.csv"') - fieldnames = ['gerente', 'total_casas', 'uf', 'total_casas_uf'] - if inclui_casas: - fieldnames.append('casa_legislativa') - writer = csv.DictWriter(response, fieldnames=fieldnames) - writer.writeheader() - for linha in dados: - rec = { - 'gerente': linha['gerente'].nome_completo.encode('utf8'), - 'total_casas': linha['gerente'].casas_que_gerencia.count() - } - for uf in linha['ufs']: - rec['uf'] = uf[1].encode('utf8') - rec['total_casas_uf'] = uf[2].count() - if inclui_casas: - for casa in uf[2]: - rec['casa_legislativa'] = casa.nome.encode('utf8') - writer.writerow(rec) - rec['gerente'] = '' - rec['total_casas'] = '' - rec['uf'] = '' - rec['total_casas_uf'] = '' - else: - writer.writerow(rec) - rec['gerente'] = '' - rec['total_casas'] = '' - return response - - return render( - request, - 'casas/gerentes_interlegis.html', - {'gerentes': dados} - ) + +# @login_required +# def report(request, id=None, tipo=None): + +# if request.POST: +# if 'tipo_relatorio' in request.POST: +# tipo = request.POST['tipo_relatorio'] + +# if tipo == 'completo': +# return report_complete(request, id) + +# if id: +# qs = Orgao.objects.filter(pk=id) +# else: +# qs = carrinhoOrGet_for_qs(request) + +# if not qs: +# return HttpResponseRedirect('../') + +# qs = qs.order_by('municipio__uf', 'nome') +# context = {'casas': qs, 'title': _("Relação de Casas Legislativas")} + +# return render_to_pdf('casas/report_pdf.html', context) + + +# @login_required +# def report_complete(request, id=None): + +# if id: +# qs = Orgao.objects.filter(pk=id) +# else: +# qs = carrinhoOrGet_for_qs(request) + +# if not qs: +# return HttpResponseRedirect('../') + +# return render_to_pdf('casas/report_complete_pdf.html', {'casas': qs}) + + +# @login_required +# def casas_sem_convenio_report(request): +# qs = Orgao.objects.filter(convenio=None).order_by('municipio__uf', 'nome') + +# if request.GET: +# qs = get_for_qs(request.GET, qs) +# if not qs: +# return HttpResponseRedirect('../') + +# qs = qs.order_by('municipio__uf', 'nome') +# context = {'casas': qs, 'title': _("Casas sem convênio")} + +# return render_to_pdf('casas/report_pdf.html', context) + + +# @login_required +# def export_csv(request): +# response = HttpResponse(content_type='text/csv') +# response['Content-Disposition'] = 'attachment; filename=casas.csv' + +# writer = csv.writer(response) + +# casas = carrinhoOrGet_for_qs(request) +# if not casas or not request.POST: +# return HttpResponseRedirect('../') + +# atributos = request.POST.getlist("itens_csv_selected") + +# try: +# atributos.insert(atributos.index(_('Município')), _('UF')) +# except ValueError: +# pass + +# atributos2 = [s.encode("utf-8") for s in atributos] + +# writer.writerow(atributos2) + +# for casa in casas: +# lista = [] +# contatos = casa.funcionario_set.exclude(nome="") +# for atributo in atributos: +# if _("CNPJ") == atributo: +# lista.append(casa.cnpj.encode("utf-8")) +# elif _("Código IBGE") == atributo: +# lista.append(str(casa.municipio.codigo_ibge).encode("utf-8")) +# elif _("Código TSE") == atributo: +# lista.append(str(casa.municipio.codigo_tse).encode("utf-8")) +# elif _("Nome") == atributo: +# lista.append(casa.nome.encode("utf-8")) +# elif _("Município") == atributo: +# lista.append(unicode(casa.municipio.uf.sigla).encode("utf-8")) +# lista.append(unicode(casa.municipio.nome).encode("utf-8")) +# elif _("Presidente") == atributo: +# # TODO: Esse encode deu erro em 25/04/2012. Comentei para que o usuário pudesse continuar seu trabalho +# # É preciso descobrir o porque do erro e fazer a correção definitiva. +# # lista.append(str(casa.presidente or "").encode("utf-8")) +# lista.append(str(casa.presidente or "")) +# elif _("Logradouro") == atributo: +# lista.append(casa.logradouro.encode("utf-8")) +# elif _("Bairro") == atributo: +# lista.append(casa.bairro.encode("utf-8")) +# elif _("CEP") == atributo: +# lista.append(casa.cep.encode("utf-8")) +# elif _("Telefone") == atributo: +# lista.append(str(casa.telefone or "")) +# elif _("Página web") == atributo: +# lista.append(casa.pagina_web.encode("utf-8")) +# elif _("Email") == atributo: +# lista.append(casa.email.encode("utf-8")) +# elif _("Número de parlamentares") == atributo: +# lista.append(casa.total_parlamentares) +# elif _("Última alteração de endereco") == atributo: +# lista.append(casa.ult_alt_endereco) +# elif _("Servicos SEIT") == atributo: +# lista.append(", ".join([s.tipo_servico.nome.encode('utf-8') +# for s in casa.servico_set.filter( +# data_desativacao__isnull=True)]) +# ) +# elif _("Nome contato") == atributo: +# if contatos: +# nomes = ", ".join([c.nome for c in contatos]) +# lista.append(nomes.encode("utf-8")) +# else: +# lista.append('') +# elif _("Cargo contato") == atributo: +# if contatos: +# cargos = ", ".join([c.cargo if c.cargo else "?" +# for c in contatos]) +# lista.append(cargos.encode("utf-8")) +# else: +# lista.append('') +# elif _("Email contato") == atributo: +# if contatos: +# emails = ", ".join([c.email if c.email else "?" +# for c in contatos]) +# lista.append(emails.encode("utf-8")) +# else: +# lista.append('') +# else: +# pass + +# writer.writerow(lista) + +# return response + + +# @login_required +# def portfolio(request): +# page = request.GET.get('page', 1) +# tipo = request.GET.get('tipo', None) +# regiao = request.GET.get('regiao', None) +# uf_id = request.GET.get('uf', None) +# meso_id = request.GET.get('meso', None) +# micro_id = request.GET.get('micro', None) + +# data = {} +# data['errors'] = [] +# data['messages'] = [] +# data['regioes'] = UnidadeFederativa.REGIAO_CHOICES +# data['tipos_casas'] = TipoOrgao.objects.all() +# casas = None +# gerente = None + +# if tipo: +# data['tipo'] = tipo + +# if micro_id: +# microrregiao = get_object_or_404(Microrregiao, pk=micro_id) +# mesorregiao = microrregiao.mesorregiao +# uf = mesorregiao.uf +# data['regiao'] = uf.regiao +# data['uf_id'] = uf.pk +# data['meso_id'] = mesorregiao.pk +# data['micro_id'] = microrregiao.pk +# data['ufs'] = UnidadeFederativa.objects.filter(regiao=uf.regiao) +# data['mesorregioes'] = uf.mesorregiao_set.all() +# data['microrregioes'] = mesorregiao.microrregiao_set.all() +# data['form'] = PortfolioForm( +# _('Atribuir casas da microrregiao {name} para').format( +# name=unicode(microrregiao)) +# ) +# data['querystring'] = 'micro={0}'.format(microrregiao.pk) +# casas = Orgao.objects.filter( +# municipio__microrregiao=microrregiao +# ) +# elif meso_id: +# mesorregiao = get_object_or_404(Mesorregiao, pk=meso_id) +# uf = mesorregiao.uf +# data['regiao'] = uf.regiao +# data['uf_id'] = uf.pk +# data['meso_id'] = mesorregiao.pk +# data['ufs'] = UnidadeFederativa.objects.filter(regiao=uf.regiao) +# data['mesorregioes'] = uf.mesorregiao_set.all() +# data['microrregioes'] = mesorregiao.microrregiao_set.all() +# data['form'] = PortfolioForm( +# _('Atribuir casas da mesorregiao {name} para').format( +# name=unicode(mesorregiao))) +# data['querystring'] = 'meso={0}'.format(mesorregiao.pk) +# casas = Orgao.objects.filter( +# municipio__microrregiao__mesorregiao=mesorregiao +# ) +# elif uf_id: +# uf = get_object_or_404(UnidadeFederativa, pk=uf_id) +# data['regiao'] = uf.regiao +# data['uf_id'] = uf.pk +# data['ufs'] = UnidadeFederativa.objects.filter(regiao=uf.regiao) +# data['mesorregioes'] = uf.mesorregiao_set.all() +# data['form'] = PortfolioForm( +# _('Atribuir casas do estado {name} para').format( +# name=unicode(uf))) +# data['querystring'] = 'uf={0}'.format(uf.pk) +# casas = Orgao.objects.filter(municipio__uf=uf) +# elif regiao: +# data['regiao'] = regiao +# data['ufs'] = UnidadeFederativa.objects.filter(regiao=regiao) +# data['form'] = PortfolioForm( +# _('Atribuir casas da região {name} para').format( +# name=[x[1] for x in UnidadeFederativa.REGIAO_CHOICES if +# x[0] == regiao][0])) +# data['querystring'] = 'regiao={0}'.format(regiao) +# casas = Orgao.objects.filter(municipio__uf__regiao=regiao) + +# if casas: +# casas = casas.order_by('municipio__uf', +# 'municipio__microrregiao__mesorregiao', +# 'municipio__microrregiao', 'municipio') + +# casas.prefetch_related('municipio', 'municipio__uf', +# 'municipio__microrregiao', +# 'municipio__microrregiao__mesorregiao', +# 'gerentes_interlegis') + +# if tipo: +# casas = casas.filter(tipo__sigla=tipo) +# data['querystring'] += "&tipo={0}".format(tipo) + +# if request.method == 'POST': +# form = PortfolioForm(data=request.POST) +# if form.is_valid(): +# gerente = form.cleaned_data['gerente'] +# acao = form.cleaned_data['acao'] + +# count = casas.count() + +# if acao == 'ADD': +# gerente.casas_que_gerencia.add(*casas) +# data['messages'].append(ungettext( +# "{count} casa adicionada para {gerente}", +# "{count} casas adicionadas para {gerente}", +# count).format(count=count,gerente=gerente.nome_completo) +# ) +# elif acao == 'DEL': +# gerente.casas_que_gerencia.remove(*casas) +# data['messages'].append(ungettext( +# "{count} casa removida de {gerente}", +# "{count} casas removidas de {gerente}", +# count).format(count=count,gerente=gerente.nome_completo) +# ) +# else: +# data['errors'].append(_("Ação não definida")) +# else: +# data['errors'].append(_("Dados inválidos")) + +# paginator = Paginator(casas, 30) +# try: +# pagina = paginator.page(page) +# except (EmptyPage, InvalidPage): +# pagina = paginator.page(paginator.num_pages) +# data['page_obj'] = pagina + +# return render(request, 'casas/portfolio.html', data) + + +# def resumo_carteira(casas): +# regioes = {r[0]: 0 for r in UnidadeFederativa.REGIAO_CHOICES} +# regioes['total'] = 0 +# total = regioes.copy() +# sem_produto = regioes.copy() +# tipos_servico = TipoServico.objects.all() +# dados = {ts.id: regioes.copy() for ts in tipos_servico} + +# for r in casas.values('municipio__uf__regiao').annotate(quantidade=Count('id')).order_by(): +# regiao = r['municipio__uf__regiao'] +# quantidade = r['quantidade'] +# total[regiao] = quantidade +# total['total'] += quantidade + +# for r in casas.values('municipio__uf__regiao', 'servico__tipo_servico__id').annotate(quantidade=Count('id')).order_by(): +# regiao = r['municipio__uf__regiao'] +# servico = r['servico__tipo_servico__id'] +# quantidade = r['quantidade'] +# if servico is None: +# sem_produto[regiao] = quantidade +# sem_produto['total'] += quantidade +# else: +# dados[servico][regiao] = quantidade +# dados[servico]['total'] += quantidade + +# dados_ocorrencia = { +# 'registradas': regioes.copy(), +# 'pendentes': regioes.copy(), +# 'sem': regioes.copy(), +# 'media': regioes.copy(), +# } + +# for r in casas.values('ocorrencia__status', 'municipio__uf__regiao').annotate(quantidade=Count('id')).order_by(): +# status = r['ocorrencia__status'] +# regiao = r['municipio__uf__regiao'] +# quantidade = r['quantidade'] +# if status is None: +# dados_ocorrencia['sem'][regiao] += quantidade +# dados_ocorrencia['sem']['total'] += quantidade +# else: +# dados_ocorrencia['registradas'][regiao] += quantidade +# dados_ocorrencia['registradas']['total'] += quantidade +# if status in [Ocorrencia.STATUS_ABERTO, Ocorrencia.STATUS_REABERTO]: +# dados_ocorrencia['pendentes'][regiao] += quantidade +# dados_ocorrencia['pendentes']['total'] += quantidade + +# for r in regioes: +# if (total[r] - dados_ocorrencia['sem'][r]) == 0: +# dados_ocorrencia['media'][r] = 0 +# else: +# dados_ocorrencia['media'][r] = (1.0 * dados_ocorrencia['registradas'][r] / (total[r] - dados_ocorrencia['sem'][r])) + +# resumo = [[_("Item"), _("Total nacional")] + [r[1] for r in UnidadeFederativa.REGIAO_CHOICES]] +# resumo.append([_("Casas em sua carteira"), total['total']] + [total[r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) +# resumo.append({'subtitle': _("Uso dos produtos Interlegis")}) +# resumo.append([_("Casas sem nenhum produto"), sem_produto['total']] + [sem_produto[r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) +# resumo.extend([[ts.nome, dados[ts.id]['total']] + [dados[ts.id][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES] for ts in tipos_servico]) +# resumo.append({'subtitle': _("Registros no sistema de ocorrências")}) +# resumo.append([_("Casas que nunca registraram ocorrências"), dados_ocorrencia['sem']['total']] + [dados_ocorrencia['sem'][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) +# resumo.append([_("Total de ocorrências registradas"), dados_ocorrencia['registradas']['total']] + [dados_ocorrencia['registradas'][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) +# resumo.append([_("Total de ocorrências pendentes"), dados_ocorrencia['pendentes']['total']] + [dados_ocorrencia['pendentes'][r[0]] for r in UnidadeFederativa.REGIAO_CHOICES]) +# resumo.append([_("Média de ocorrências por casa"), round(dados_ocorrencia['media']['total'], 2)] + [round(dados_ocorrencia['media'][r[0]], 2) for r in UnidadeFederativa.REGIAO_CHOICES]) + +# return resumo + + +# def casas_carteira(request, casas, context): +# servicos = request.GET.getlist('servico') +# sigla_regiao = request.GET.get('r', None) +# sigla_uf = request.GET.get('uf', None) +# meso_id = request.GET.get('meso', None) +# micro_id = request.GET.get('micro', None) +# servicos = request.GET.getlist('servico') +# tipos_servico = context['servicos'] + +# context['qs_regiao'] = '' + +# if micro_id is not None: +# context['micro'] = get_object_or_404(Microrregiao, pk=micro_id) +# context['qs_regiao'] = 'micro=%s' % micro_id +# context['meso'] = context['micro'].mesorregiao +# context['uf'] = context['meso'].uf +# context['regiao'] = context['uf'].regiao +# casas = casas.filter(municipio__microrregiao=context['micro']) +# elif meso_id is not None: +# context['meso'] = get_object_or_404(Mesorregiao, pk=meso_id) +# context['qs_regiao'] = 'meso=%s' % meso_id +# context['uf'] = context['meso'].uf +# context['regiao'] = context['uf'].regiao +# casas = casas.filter(municipio__microrregiao__mesorregiao=context['meso']) +# elif sigla_uf is not None: +# context['uf'] = get_object_or_404(UnidadeFederativa, sigla=sigla_uf) +# context['qs_regiao'] = 'uf=%s' % sigla_uf +# context['regiao'] = context['uf'].regiao +# casas = casas.filter(municipio__uf=context['uf']) +# elif sigla_regiao is not None: +# context['regiao'] = sigla_regiao +# context['qs_regiao'] = 'r=%s' % sigla_regiao +# casas = casas.filter(municipio__uf__regiao=sigla_regiao) + +# if 'regiao' in context: +# context['ufs'] = UnidadeFederativa.objects.filter(regiao=context['regiao']) + +# todos_servicos = ['_none_'] + [s.sigla for s in tipos_servico] + +# if not servicos or set(servicos) == set(todos_servicos): +# servicos = todos_servicos +# context['qs_servico'] = '' +# else: +# if '_none_' in servicos: +# casas = casas.filter(Q(servico=None) | Q(servico__tipo_servico__sigla__in=servicos)) +# else: +# casas = casas.filter(servico__tipo_servico__sigla__in=servicos) +# casas = casas.distinct('nome', 'municipio__uf') +# context['qs_servico'] = "&".join(['servico=%s' % s for s in servicos]) + +# context['servicos_check'] = servicos + +# casas = casas.select_related('municipio', 'municipio__uf', 'municipio__microrregiao', 'municipio__microrregiao__mesorregiao').prefetch_related('servico_set') + +# return casas, context + + +# @login_required +# def painel_relacionamento(request): +# page = request.GET.get('page', 1) +# snippet = request.GET.get('snippet', '') +# seletor = request.GET.get('s', None) +# servidor = request.GET.get('servidor', None) +# fmt = request.GET.get('f', 'html') + +# if servidor is None: +# gerente = request.user.servidor +# elif servidor == '_all': +# gerente = None +# else: +# gerente = get_object_or_404(Servidor, pk=servidor) + +# if gerente is not None: +# casas = gerente.casas_que_gerencia.all() + +# if gerente is None or not casas.exists(): +# casas = Orgao.objects.exclude(gerentes_interlegis=None) +# gerente = None + +# tipos_servico = TipoServico.objects.all() +# regioes = UnidadeFederativa.REGIAO_CHOICES + +# context = { +# 'seletor': seletor, +# 'snippet': snippet, +# 'regioes': regioes, +# 'servicos': tipos_servico, +# 'gerentes': Servidor.objects.exclude(casas_que_gerencia=None), +# 'gerente': gerente, +# 'qs_servidor': ('servidor=%s' % gerente.pk) if gerente else '', +# } + +# if snippet != 'lista': +# context['resumo'] = resumo_carteira(casas) + +# if snippet != 'resumo': +# casas, context = casas_carteira(request, casas, context) +# paginator = Paginator(casas, 30) +# try: +# pagina = paginator.page(page) +# except (EmptyPage, InvalidPage): +# pagina = paginator.page(paginator.num_pages) +# context['page_obj'] = pagina + +# if snippet == 'lista': +# if fmt == 'csv': +# response = HttpResponse(content_type='text/csv') +# response['Content-Disposition'] = 'attachment; filename=casas.csv' +# writer = csv.writer(response) +# writer.writerow([ +# _("Casa legislativa").encode('utf8'), +# _("Região").encode('utf8'), +# _("Estado").encode('utf8'), +# _("Mesorregião").encode('utf8'), +# _("Microrregião").encode('utf8'), +# _("Gerentes Interlegis").encode('utf8'), +# _("Serviços").encode('utf8'), +# ]) +# for c in casas: +# writer.writerow([ +# c.nome.encode('utf8'), +# c.municipio.uf.get_regiao_display().encode('utf8'), +# c.municipio.uf.sigla.encode('utf8'), +# c.municipio.microrregiao.mesorregiao.nome.encode('utf8'), +# c.municipio.microrregiao.nome.encode('utf8'), +# c.lista_gerentes(fmt='lista').encode('utf8'), +# (", ".join([s.tipo_servico.nome for s in c.servico_set.filter(data_desativacao__isnull=True)])).encode('utf8'), +# ]) +# return response +# return render(request, 'casas/lista_casas_carteira_snippet.html', context) +# if snippet == 'resumo': +# return render(request, 'casas/resumo_carteira_snippet.html', context) + +# return render(request, 'casas/painel.html', context) + +# @login_required +# def gerentes_interlegis(request): +# formato = request.GET.get('fmt', 'html') +# inclui_casas = (request.GET.get('casas', 'no') == 'yes') +# gerentes = Servidor.objects.exclude( +# casas_que_gerencia=None).select_related('casas_que_gerencia') +# dados = [] +# for gerente in gerentes: +# row = {'gerente': gerente, 'ufs': []} +# for uf in (gerente.casas_que_gerencia.distinct('municipio__uf__sigla') +# .order_by('municipio__uf__sigla') +# .values_list('municipio__uf__sigla', 'municipio__uf__nome') +# ): +# row['ufs'].append(( +# uf[0], +# uf[1], +# gerente.casas_que_gerencia.filter(municipio__uf__sigla=uf[0]) +# )) +# dados.append(row) + +# if formato == 'pdf': +# return render_to_pdf( +# 'casas/gerentes_interlegis_pdf.html', +# {'gerentes': dados} +# ) +# elif formato == 'csv': +# response = HttpResponse(content_type='text/csv') +# response['Content-Disposition'] = ('attachment; ' +# 'filename="gerentes_interlegis.csv"') +# fieldnames = ['gerente', 'total_casas', 'uf', 'total_casas_uf'] +# if inclui_casas: +# fieldnames.append('casa_legislativa') +# writer = csv.DictWriter(response, fieldnames=fieldnames) +# writer.writeheader() +# for linha in dados: +# rec = { +# 'gerente': linha['gerente'].nome_completo.encode('utf8'), +# 'total_casas': linha['gerente'].casas_que_gerencia.count() +# } +# for uf in linha['ufs']: +# rec['uf'] = uf[1].encode('utf8') +# rec['total_casas_uf'] = uf[2].count() +# if inclui_casas: +# for casa in uf[2]: +# rec['casa_legislativa'] = casa.nome.encode('utf8') +# writer.writerow(rec) +# rec['gerente'] = '' +# rec['total_casas'] = '' +# rec['uf'] = '' +# rec['total_casas_uf'] = '' +# else: +# writer.writerow(rec) +# rec['gerente'] = '' +# rec['total_casas'] = '' +# return response + +# return render( +# request, +# 'casas/gerentes_interlegis.html', +# {'gerentes': dados} +# ) diff --git a/sigi/settings/base.py b/sigi/settings/base.py index 85289e1..1724944 100644 --- a/sigi/settings/base.py +++ b/sigi/settings/base.py @@ -21,7 +21,9 @@ BASE_DIR = Path(__file__).resolve().parent.parent INSTALLED_APPS = [ 'sigi.apps.servidores', 'sigi.apps.contatos', + 'sigi.apps.casas', 'django_bootstrap5', + 'localflavor', 'django.forms', 'django.contrib.admin', 'django.contrib.auth', @@ -85,6 +87,8 @@ USE_THOUSAND_SEPARATOR = True # https://docs.djangoproject.com/en/4.0/howto/static-files/ STATIC_URL = 'static/' +STATICFILES_DIRS = [BASE_DIR / "static",] +STATIC_ROOT = '/var/www/sigi/static/' # Default primary key field type # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field diff --git a/sigi/settings/development.py b/sigi/settings/development.py index e7f3df7..97edc29 100644 --- a/sigi/settings/development.py +++ b/sigi/settings/development.py @@ -50,3 +50,8 @@ AUTH_PASSWORD_VALIDATORS = [ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.0/howto/static-files/ + +STATIC_ROOT = BASE_DIR / '../static/' \ No newline at end of file diff --git a/sigi/static/img/logo-interlegis.png b/sigi/static/img/logo-interlegis.png new file mode 100644 index 0000000000000000000000000000000000000000..042ffac380d3ef6e455eb87861af0f5e83a39872 GIT binary patch literal 19505 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 MyQj;GlfgIs4}Hy!H~;_u literal 0 HcmV?d00001 diff --git a/sigi/static/img/logo-senado.png b/sigi/static/img/logo-senado.png new file mode 100644 index 0000000000000000000000000000000000000000..248e796cef9f6752f9c5443d126d5c2d909ba7f1 GIT binary patch literal 31326 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 literal 0 HcmV?d00001 diff --git a/templates/change_list_with_cart.html b/sigi/templates/change_list_with_cart.html similarity index 87% rename from templates/change_list_with_cart.html rename to sigi/templates/change_list_with_cart.html index 14cdf1c..bfaa2f4 100644 --- a/templates/change_list_with_cart.html +++ b/sigi/templates/change_list_with_cart.html @@ -1,5 +1,5 @@ {% extends "admin/change_list.html" %} -{% load admin_list i18n reporting_tags %} +{% load admin_list i18n %} {% block object-tools-items %}
  • diff --git a/sigi/templates/pdf/base.html b/sigi/templates/pdf/base.html new file mode 100644 index 0000000..b771339 --- /dev/null +++ b/sigi/templates/pdf/base.html @@ -0,0 +1,45 @@ +{% load static i18n %} + + + + + + + + {% block extra_head %}{% endblock extra_head %} + {% block title %}{% endblock title %} + + + {% block body_content %}{% endblock body_content %} + + diff --git a/sigi/templates/pdf/base_report.html b/sigi/templates/pdf/base_report.html new file mode 100644 index 0000000..74fd9d4 --- /dev/null +++ b/sigi/templates/pdf/base_report.html @@ -0,0 +1,59 @@ +{% extends 'pdf/base.html' %} +{% load static i18n %} + +{% block title %}{{ title }}{% endblock title %} +{% block extra_style %} +h1, h2, h3, h4, h5, h6 { + margin: 0; +} +h1 {font-size: 1.6em;} +h2 {font-size: 1.5em;} +h3 {font-size: 1.4em;} +h4 {font-size: 1.3em;} +h5 {font-size: 1.2em;} +h6 {font-size: 1.1em;} +header { + font-size: 1.4em; + font-weight: bold; + text-align: center; +} +header p { + margin: 5px; +} +.report_name { + font-size: 1.6em; +} + +table { + border: 2px white; + width: 100%; +} +th,td { + padding: 4px; +} +th { + background-color: #007433; + color: white; +} +tr:nth-child(even) { + background-color: #d2d2d2; +} +.title_row { + background-color: #b2b2b2; +} +{% endblock extra_style %} + +{% block body_content %} +
    {% block header %} +

    {% trans 'SENADO FEDERAL' %}

    +

    {% trans 'Instituto Legislativo Brasileiro - ILB' %}

    +

    {% trans "INTERLEGIS" %}

    +

    {{ title|upper }}

    {% endblock header %} +
    + +
    {% block footer %} +

    {% trans 'Emitido em ' %}{% now "DATETIME_FORMAT" %}

    {% endblock footer %} +
    + + {% block main_content %}{% endblock main_content %} +{% endblock body_content %} \ No newline at end of file diff --git a/sigi/urls.py b/sigi/urls.py index 40febb3..14875ef 100644 --- a/sigi/urls.py +++ b/sigi/urls.py @@ -18,6 +18,7 @@ from django.urls import path, include from django.conf import settings urlpatterns = [ + path('admin/casas/', include('sigi.apps.casas.urls')), path('admin/', admin.site.urls), ] diff --git a/sigiStatic/img/logo-interlegis.png b/sigiStatic/img/logo-interlegis.png deleted file mode 100644 index 3f4830246fe7b147b4544de6b123a0b675cd40bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1703 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

    D+_{Kn5N<|%;UYQ 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 bk{Y(76euZoqGRFbF>GYS4bqmc76