diff --git a/sigi/apps/casas/admin.py b/sigi/apps/casas/admin.py index 4c2631e..bd242a1 100644 --- a/sigi/apps/casas/admin.py +++ b/sigi/apps/casas/admin.py @@ -6,18 +6,58 @@ from django.http import HttpResponseRedirect from django.urls import reverse from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ +from import_export import resources +from import_export.fields import Field 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.filters import GerentesInterlegisFilter +from sigi.apps.casas.filters import (GerentesInterlegisFilter, ConvenioFilter, + ExcluirConvenioFilter) from sigi.apps.contatos.models import Telefone -# from sigi.apps.convenios.models import Convenio, Projeto +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.mixins import CartExportMixin + + +class OrgaoExportResourse(resources.ModelResource): + presidente = Field(column_name='presidente') + telefone = Field(column_name='telefone') + num_parlamentares = Field(column_name='num_parlamentares') + # servicos_seit = Field(column_name='servicos_seit') + contato = Field(column_name='contato') + class Meta: + model = Orgao + fields = ('municipio__codigo_ibge', 'cnpj', 'municipio__codigo_tse', + 'nome', 'municipio__nome', 'municipio__uf__sigla', + 'presidente', 'logradouro', 'bairro', 'cep', 'telefone', + 'pagina_web', 'email', 'telefone', 'num_parlamentares', + 'ult_alt_endereco', 'contato') + export_order = fields + + def dehydrate_presidente(self, orgao): + return orgao.presidente + + def dehydrate_telefone(self, orgao): + return orgao.telefone + + def dehydrate_num_parlamentares(self, orgao): + return orgao.num_parlamentares + + # def dehydrate_servicos_seit(self, orgao): + # servicos = [s.tipo_servico.nome for s in orgao.servico_set.filter( + # data_desativacao__isnull=True)] + # return ", ".join(servicos) + + def dehydrate_contato(self, orgao): + return ", ".join( + [f"{c.cargo if c.cargo else 'Sem cargo'}: {c.nome} ({c.email})" + for c in orgao.funcionario_set.filter(desativado=False) + ] + ) class TelefonesInline(GenericTabularInline): model = Telefone @@ -83,76 +123,76 @@ class FuncionariosInline(admin.StackedInline): # 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_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') +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 "" -# return mark_safe(obj.get_sigad_url()) -# link_sigad.short_description = _("Processo no Senado") + def link_sigad(self, obj): + if obj.pk is None: + return "" + return mark_safe(obj.get_sigad_url()) + link_sigad.short_description = _("Processo no Senado") # class ServicoInline(admin.TabularInline): # model = Servico @@ -223,8 +263,9 @@ class FuncionariosInline(admin.StackedInline): @admin.register(Orgao) -class OrgaoAdmin(admin.ModelAdmin): +class OrgaoAdmin(CartExportMixin, admin.ModelAdmin): form = OrgaoForm + resource_class = OrgaoExportResourse # actions = ['adicionar_casas', ] inlines = (TelefonesInline, PresidenteInline, ContatoInterlegisInline, FuncionariosInline, ) #ConveniosInline, ServicoInline, @@ -236,7 +277,8 @@ class OrgaoAdmin(admin.ModelAdmin): # 'municipio__uf__nome', ConvenioFilter, ServicoAtivoFilter, # ExcluirConvenioFilter, ServicoFilter, 'inclusao_digital',) list_filter = ('tipo', ('gerentes_interlegis', GerentesInterlegisFilter), - 'municipio__uf__nome', 'inclusao_digital',) + 'municipio__uf__nome', ConvenioFilter, ExcluirConvenioFilter, + 'inclusao_digital',) ordering = ('municipio__uf__nome', 'nome') queryset = queryset_ascii fieldsets = ( @@ -273,13 +315,11 @@ class OrgaoAdmin(admin.ModelAdmin): get_gerentes.short_description = _('Gerente Interlegis') def get_convenios(self, obj): - #TODO: Descomentar após migração da app Convênios - # return mark_safe( - # '' - # ) - return "TODO: Descomentar após migração da app Convênios" + return mark_safe( + '' + ) get_convenios.short_description = _('Convênios') def get_servicos(self, obj): diff --git a/sigi/apps/casas/filters.py b/sigi/apps/casas/filters.py index 749a260..2905b7e 100644 --- a/sigi/apps/casas/filters.py +++ b/sigi/apps/casas/filters.py @@ -1,5 +1,7 @@ from django.contrib import admin +from django.utils.translation import gettext as _ from sigi.apps.servidores.models import Servidor +from sigi.apps.convenios.models import Convenio, Projeto class GerentesInterlegisFilter(admin.filters.RelatedFieldListFilter): @@ -9,40 +11,40 @@ class GerentesInterlegisFilter(admin.filters.RelatedFieldListFilter): 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 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") diff --git a/sigi/apps/casas/templates/admin/casas/change_list.html b/sigi/apps/casas/templates/admin/casas/change_list.html index a135fc3..096895b 100644 --- a/sigi/apps/casas/templates/admin/casas/change_list.html +++ b/sigi/apps/casas/templates/admin/casas/change_list.html @@ -1,4 +1,4 @@ -{% extends "change_list_with_cart.html" %} +{% extends "cart/change_list.html" %} {% load i18n %} {% block object-tools-items %} diff --git a/sigi/apps/casas/views.py b/sigi/apps/casas/views.py index 0f64e62..5e9f07a 100644 --- a/sigi/apps/casas/views.py +++ b/sigi/apps/casas/views.py @@ -30,12 +30,13 @@ from sigi.apps.servidores.models import Servidor class CasasSemConvenioReport(WeasyTemplateView): template_name = "casas/casas_sem_convenio_pdf.html" + pdf_filename = 'casas_sem_convenio.pdf' def get_context_data(self, **kwargs): - # qs = Orgao.objects.filter(convenio=None).order_by( - # 'municipio__uf', - # 'nome' - # ) + qs = Orgao.objects.filter(convenio=None).order_by( + 'municipio__uf', + 'nome' + ) qs = Orgao.objects.order_by( 'municipio__uf', 'nome' diff --git a/sigi/apps/convenios/models.py b/sigi/apps/convenios/models.py index 86ddfa5..c3e5736 100644 --- a/sigi/apps/convenios/models.py +++ b/sigi/apps/convenios/models.py @@ -5,6 +5,7 @@ from django.db import models from django.db.models import Q, fields from django.core.mail import send_mail from django.urls import reverse +from django.utils.formats import date_format from django.utils.translation import gettext as _ from sigi.apps.utils import to_ascii from sigi.apps.casas.models import Orgao @@ -253,22 +254,23 @@ class Convenio(models.Model): project=self.projeto.sigla if ((self.data_retorno_assinatura is None) and (self.equipada and self.data_termo_aceite is not None)): - date=self.data_termo_aceite.strftime(SDF) + date = date_format(self.data_termo_aceite, SDF) return _(f"{project} nº {number} - equipada em {date}") elif self.data_retorno_assinatura is None: - date = self.data_adesao.strftime(SDF) if self.data_adesao else "" + date = (date_format(self.data_adesao, SDF) + if self.data_adesao else "") return _(f"{project}, nº {number}, início em {date}") if ((self.data_retorno_assinatura is not None) and not (self.equipada and self.data_termo_aceite is not None)): - date=self.data_retorno_assinatura.strftime(SDF) + date = date_format(self.data_retorno_assinatura, SDF) status=self.get_status() return _( f"{project}, nº {number}, inicio em {date}. Status: {status}" ) if ((self.data_retorno_assinatura is not None) and (self.equipada and self.data_termo_aceite is not None)): - date=self.data_retorno_assinatura.strftime(SDF) - equipped_date=self.data_termo_aceite.strftime(SDF) + date = date_format(self.data_retorno_assinatura, SDF) + equipped_date=date_format(self.data_termo_aceite, SDF) return _( f"{project}, nº {number}, início em {date} e equipada em " f"{equipped_date}. Status: {self.get_status()}" diff --git a/sigi/settings/base.py b/sigi/settings/base.py index d2afb54..a3c4230 100644 --- a/sigi/settings/base.py +++ b/sigi/settings/base.py @@ -21,11 +21,13 @@ BASE_DIR = Path(__file__).resolve().parent.parent INSTALLED_APPS = [ 'sigi.apps.servidores', 'sigi.apps.contatos', + 'sigi.apps.utils', 'sigi.apps.casas', 'sigi.apps.convenios', 'sigi.apps.inventario', - 'django_bootstrap5', 'localflavor', + 'import_export', + 'django_bootstrap5', 'django.forms', 'django.contrib.admin', 'django.contrib.auth', @@ -96,3 +98,9 @@ STATIC_ROOT = '/var/www/sigi/static/' # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +# Django import-export settings +# https://django-import-export.readthedocs.io/en/latest/installation.html#settings + +IMPORT_EXPORT_USE_TRANSACTIONS = True +IMPORT_EXPORT_SKIP_ADMIN_LOG = True \ No newline at end of file