Browse Source

Merge branch 'stable/2.2'

unstable/3.0
Sesostris Vieira 4 years ago
parent
commit
ae57e58bd0
  1. 1
      .gitignore
  2. 36
      etc/migracao/migra.py
  3. 2
      locale/en/LC_MESSAGES/django.po
  4. 24
      moodlerouter.py
  5. 50
      scripts/importa_pesquisa.py
  6. 5592
      scripts/setgerentes/dados_gerentes.py
  7. 16
      scripts/setgerentes/set_gerentes.py
  8. 4
      scripts/verificacao_arquivos_faltando_media.py
  9. 392
      sigi/apps/casas/admin.py
  10. 43
      sigi/apps/casas/forms.py
  11. 62
      sigi/apps/casas/management/commands/importa_gerentes.py
  12. 26
      sigi/apps/casas/migrations/0003_auto_20200207_0919.py
  13. 20
      sigi/apps/casas/migrations/0004_auto_20201015_0810.py
  14. 21
      sigi/apps/casas/migrations/0005_casalegislativa_gerentes_interlegis.py
  15. 18
      sigi/apps/casas/migrations/0006_remove_casalegislativa_gerente_contas.py
  16. 128
      sigi/apps/casas/migrations/0007_auto_20201016_1632.py
  17. 45
      sigi/apps/casas/migrations/0008_auto_20210218_1007.py
  18. 20
      sigi/apps/casas/migrations/0009_auto_20210406_1055.py
  19. 18
      sigi/apps/casas/migrations/0010_auto_20210406_1101.py
  20. 18
      sigi/apps/casas/migrations/0011_auto_20210406_1135.py
  21. 18
      sigi/apps/casas/migrations/0012_auto_20210406_1420.py
  22. 18
      sigi/apps/casas/migrations/0013_auto_20210406_1428.py
  23. 31
      sigi/apps/casas/migrations/0014_auto_20210406_1945.py
  24. 28
      sigi/apps/casas/migrations/0015_auto_20210407_0801.py
  25. 20
      sigi/apps/casas/migrations/0016_auto_20210407_1559.py
  26. 45
      sigi/apps/casas/migrations/0017_auto_20210416_0841.py
  27. 20
      sigi/apps/casas/migrations/0018_orgao_sigla.py
  28. 26
      sigi/apps/casas/migrations/0019_auto_20210501_1058.py
  29. 18
      sigi/apps/casas/migrations/0020_auto_20210611_0946.py
  30. 295
      sigi/apps/casas/models.py
  31. 406
      sigi/apps/casas/reports.py
  32. 6
      sigi/apps/casas/templates/admin/casas/convenios_inline.html
  33. 164
      sigi/apps/casas/templates/admin/casas/ocorrencia_inline.html
  34. 6
      sigi/apps/casas/templates/casas/carrinho.html
  35. 57
      sigi/apps/casas/templates/casas/gerentes_interlegis.html
  36. 143
      sigi/apps/casas/templates/casas/gerentes_interlegis_pdf.html
  37. 81
      sigi/apps/casas/templates/casas/importar.html
  38. 18
      sigi/apps/casas/templates/casas/importar_result.html
  39. 10
      sigi/apps/casas/templates/casas/lista_casas_carteira_snippet.html
  40. 46
      sigi/apps/casas/templates/casas/portfolio.html
  41. 237
      sigi/apps/casas/templates/casas/report_complete_pdf.html
  42. 132
      sigi/apps/casas/templates/casas/report_pdf.html
  43. 4
      sigi/apps/casas/test_casas.py
  44. 47
      sigi/apps/casas/urls.py
  45. 694
      sigi/apps/casas/views.py
  46. 39
      sigi/apps/contatos/migrations/0003_auto_20210416_0841.py
  47. 24
      sigi/apps/contatos/migrations/0004_auto_20210611_0946.py
  48. 58
      sigi/apps/contatos/models.py
  49. 116
      sigi/apps/convenios/admin.py
  50. 0
      sigi/apps/convenios/management/__init__.py
  51. 0
      sigi/apps/convenios/management/commands/__init__.py
  52. 26
      sigi/apps/convenios/management/commands/duracao_act.py
  53. 20
      sigi/apps/convenios/migrations/0002_convenio_duracao.py
  54. 21
      sigi/apps/convenios/migrations/0003_auto_20210406_1945.py
  55. 78
      sigi/apps/convenios/migrations/0004_auto_20210407_1928.py
  56. 26
      sigi/apps/convenios/migrations/0005_auto_20210409_0842.py
  57. 33
      sigi/apps/convenios/migrations/0006_auto_20210416_0841.py
  58. 40
      sigi/apps/convenios/migrations/0007_auto_20210416_0918.py
  59. 34
      sigi/apps/convenios/migrations/0008_auto_20210422_1907.py
  60. 18
      sigi/apps/convenios/migrations/0009_auto_20210611_0946.py
  61. 259
      sigi/apps/convenios/models.py
  62. 166
      sigi/apps/convenios/templates/convenios/carrinho.html
  63. 76
      sigi/apps/convenios/templates/convenios/change_list.html
  64. 45
      sigi/apps/convenios/views.py
  65. 10
      sigi/apps/diagnosticos/forms.py
  66. 0
      sigi/apps/diagnosticos/management/__init__.py
  67. 0
      sigi/apps/diagnosticos/management/commands/__init__.py
  68. 275
      sigi/apps/diagnosticos/management/commands/ls_export.py
  69. 22
      sigi/apps/diagnosticos/migrations/0002_auto_20170407_1024.py
  70. 20
      sigi/apps/diagnosticos/migrations/0003_auto_20201101_2240.py
  71. 21
      sigi/apps/diagnosticos/migrations/0004_auto_20210406_1945.py
  72. 51
      sigi/apps/diagnosticos/migrations/0005_auto_20210416_0841.py
  73. 67
      sigi/apps/diagnosticos/models.py
  74. 6
      sigi/apps/diagnosticos/views.py
  75. 64
      sigi/apps/eventos/admin.py
  76. 18
      sigi/apps/eventos/migrations/0004_remove_evento_curso_moodle_id.py
  77. 27
      sigi/apps/eventos/migrations/0005_auto_20210406_1945.py
  78. 57
      sigi/apps/eventos/migrations/0006_auto_20210416_0841.py
  79. 38
      sigi/apps/eventos/migrations/0007_auto_20210417_0744.py
  80. 141
      sigi/apps/eventos/models.py
  81. 1
      sigi/apps/eventos/templates/admin/eventos/change_list.html
  82. 63
      sigi/apps/eventos/templates/eventos/carrinho.html
  83. 9
      sigi/apps/eventos/urls.py
  84. 234
      sigi/apps/eventos/views.py
  85. 6
      sigi/apps/financeiro/models.py
  86. 2
      sigi/apps/home/templates/home/sem_convenio.html
  87. 170
      sigi/apps/home/templatetags/menu_conf.yaml
  88. 95
      sigi/apps/home/views.py
  89. 21
      sigi/apps/inventario/migrations/0002_auto_20210406_1945.py
  90. 39
      sigi/apps/inventario/migrations/0003_auto_20210416_0841.py
  91. 20
      sigi/apps/inventario/models.py
  92. 3
      sigi/apps/mdl/admin.py
  93. 6007
      sigi/apps/mdl/base_models.py
  94. 116
      sigi/apps/mdl/migrations/0001_initial.py
  95. 360
      sigi/apps/mdl/models.py
  96. 3
      sigi/apps/mdl/views.py
  97. 21
      sigi/apps/metas/migrations/0002_auto_20210406_1945.py
  98. 21
      sigi/apps/metas/models.py
  99. 58
      sigi/apps/metas/static/metas/css/openmap.css
  100. 93
      sigi/apps/metas/templates/metas/lista_casas.html

1
.gitignore

@ -44,6 +44,7 @@ db.*
.project .project
.pydevproject .pydevproject
.settings .settings
.vscode/
.vagrant .vagrant
sigi/settings/prod.py sigi/settings/prod.py

36
etc/migracao/migra.py

@ -60,7 +60,7 @@ def migra_assembleias(filename):
reader = csv.reader(open(filename, 'r'), delimiter='|', skipinitialspace=True) reader = csv.reader(open(filename, 'r'), delimiter='|', skipinitialspace=True)
header = reader.next() header = reader.next()
tipo_casa = TipoCasaLegislativa.objects.filter(sigla='AL').get() tipo_casa = TipoOrgao.objects.filter(sigla='AL').get()
for line in reader: for line in reader:
uf = UnidadeFederativa.objects.get(sigla=line[UF_COL]) uf = UnidadeFederativa.objects.get(sigla=line[UF_COL])
@ -71,7 +71,7 @@ def migra_assembleias(filename):
bairro = aux_end[1].replace(' ', '', 1) bairro = aux_end[1].replace(' ', '', 1)
else: else:
bairro = '' bairro = ''
casa = CasaLegislativa( casa = Orgao(
municipio=municipio, municipio=municipio,
nome=line[NOME_COL], nome=line[NOME_COL],
tipo=tipo_casa, tipo=tipo_casa,
@ -85,7 +85,7 @@ def migra_assembleias(filename):
telefone=line[FONE_1_COL] telefone=line[FONE_1_COL]
) )
if line[UF_COL] == 'DF': if line[UF_COL] == 'DF':
casa.tipo = TipoCasaLegislativa.objects.filter(sigla='CT').get() casa.tipo = TipoOrgao.objects.filter(sigla='CT').get()
casa.save() casa.save()
if line[FONE_2_COL]: if line[FONE_2_COL]:
@ -141,7 +141,7 @@ def migra_casas(filename):
reader = csv.reader(open(filename, 'r'), delimiter='|', skipinitialspace=True) reader = csv.reader(open(filename, 'r'), delimiter='|', skipinitialspace=True)
header = reader.next() header = reader.next()
tipo_casa = TipoCasaLegislativa.objects.filter(sigla='CM').get() tipo_casa = TipoOrgao.objects.filter(sigla='CM').get()
linenum = 1 linenum = 1
for line in reader: for line in reader:
@ -160,7 +160,7 @@ def migra_casas(filename):
bairro = '' bairro = ''
if(aux_end.__len__() > 1): if(aux_end.__len__() > 1):
bairro = aux_end[1].replace(' ', '', 1) bairro = aux_end[1].replace(' ', '', 1)
casa = CasaLegislativa( casa = Orgao(
municipio=municipio, municipio=municipio,
nome='Câmara Municipal de ' + line[NOME_COL], nome='Câmara Municipal de ' + line[NOME_COL],
tipo=tipo_casa, tipo=tipo_casa,
@ -214,11 +214,11 @@ def migra_cnpj(filename):
linenum += 1 linenum += 1
try: try:
casa = CasaLegislativa.objects.get(municipio__codigo_tse=line[COD_TSE_COL]) casa = Orgao.objects.get(municipio__codigo_tse=line[COD_TSE_COL])
except CasaLegislativa.DoesNotExist: except Orgao.DoesNotExist:
print ERROR_MSG_1 % (filename, linenum) print ERROR_MSG_1 % (filename, linenum)
continue continue
except CasaLegislativa.MultipleObjectsReturned: except Orgao.MultipleObjectsReturned:
print ERROR_MSG_1 % (filename, linenum) print ERROR_MSG_1 % (filename, linenum)
continue continue
except ValueError: except ValueError:
@ -271,12 +271,12 @@ def migra_convenios_casas(filename):
linenum += 1 linenum += 1
try: try:
casa = CasaLegislativa.objects.get(municipio__codigo_ibge=line[COD_IBGE_COL]) casa = Orgao.objects.get(municipio__codigo_ibge=line[COD_IBGE_COL])
except CasaLegislativa.DoesNotExist: except Orgao.DoesNotExist:
print "Erro ao inserir convênio. Casa não existe" print "Erro ao inserir convênio. Casa não existe"
print ERROR_MSG_1 % (filename, linenum) print ERROR_MSG_1 % (filename, linenum)
continue continue
except CasaLegislativa.MultipleObjectsReturned: except Orgao.MultipleObjectsReturned:
print ERROR_MSG_1 % (filename, linenum) print ERROR_MSG_1 % (filename, linenum)
continue continue
except ValueError: except ValueError:
@ -368,16 +368,16 @@ def migra_convenios_assembleias(filename):
reader = csv.reader(open(filename, 'r'), delimiter='|', skipinitialspace=True) reader = csv.reader(open(filename, 'r'), delimiter='|', skipinitialspace=True)
header = reader.next() header = reader.next()
linenum = 1 linenum = 1
tipo_casa = TipoCasaLegislativa.objects.filter(sigla='AL').get() tipo_casa = TipoOrgao.objects.filter(sigla='AL').get()
for line in reader: for line in reader:
linenum += 1 linenum += 1
try: try:
assembleia = CasaLegislativa.objects.get(municipio__uf__sigla=line[SIGLA_COL], tipo=tipo_casa) assembleia = Orgao.objects.get(municipio__uf__sigla=line[SIGLA_COL], tipo=tipo_casa)
except CasaLegislativa.DoesNotExist: except Orgao.DoesNotExist:
print ERROR_MSG_1 % (filename, linenum) print ERROR_MSG_1 % (filename, linenum)
continue continue
except CasaLegislativa.MultipleObjectsReturned: except Orgao.MultipleObjectsReturned:
print ERROR_MSG_1 % (filename, linenum) print ERROR_MSG_1 % (filename, linenum)
continue continue
except ValueError: except ValueError:
@ -417,11 +417,11 @@ def popula():
projeto3 = Projeto(sigla='PML', nome='Projeto Modernização Legislativo') projeto3 = Projeto(sigla='PML', nome='Projeto Modernização Legislativo')
projeto3.save() projeto3.save()
tipo1 = TipoCasaLegislativa(sigla='CM', nome='Câmara Municipal') tipo1 = TipoOrgao(sigla='CM', nome='Câmara Municipal')
tipo1.save() tipo1.save()
tipo2 = TipoCasaLegislativa(sigla='AL', nome='Assembléia Legislativa') tipo2 = TipoOrgao(sigla='AL', nome='Assembléia Legislativa')
tipo2.save() tipo2.save()
tipo3 = TipoCasaLegislativa(sigla='CT', nome='Câmara Distrital') tipo3 = TipoOrgao(sigla='CT', nome='Câmara Distrital')
tipo3.save() tipo3.save()

2
locale/en/LC_MESSAGES/django.po

@ -901,7 +901,7 @@ msgid "Data de Aceite"
msgstr "" msgstr ""
#: sigi/apps/convenios/reports.py:143 #: sigi/apps/convenios/reports.py:143
msgid "CasaLegislativa: " msgid "Orgao: "
msgstr "" msgstr ""
#: sigi/apps/convenios/reports.py:250 #: sigi/apps/convenios/reports.py:250

24
moodlerouter.py

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
class MoodleRouter(object):
def db_for_read(self, model, **hints):
if model._meta.app_label == 'mdl':
return 'moodle'
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == 'mdl':
return 'moodle'
return None
def allow_relation(self, obj1, obj2, **hints):
if obj1._meta.app_label == 'mdl' and obj2._meta.app_label == 'mdl':
return True
return None
def allow_migrate(self, db, model):
if model._meta.app_label == 'mdl':
return False
return None

50
scripts/importa_pesquisa.py

@ -26,16 +26,16 @@ import csv
import urlparse import urlparse
from datetime import datetime from datetime import datetime
from sigi.apps.casas.models import CasaLegislativa from sigi.apps.casas.models import Orgao
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
def importa(file_list): def importa(file_list):
''' Este script importa dados de um arquivo CSV e dá carga no model casas.CasaLegislativa ''' Este script importa dados de um arquivo CSV e dá carga no model casas.Orgao
O arquivo CSV esperado tem um cabeçalho de campos na primeira linha, com os seguintes campos: O arquivo CSV esperado tem um cabeçalho de campos na primeira linha, com os seguintes campos:
Indicação de data e hora,Pesquisador,Câmara,Possui portal,Portal Modelo,URL,Observações Indicação de data e hora,Pesquisador,Câmara,Possui portal,Portal Modelo,URL,Observações
Indicação de data e hora: Uma string datetime no formato %d/%m/%y %H:%M Indicação de data e hora: Uma string datetime no formato %d/%m/%y %H:%M
Pesquisador: O nome do servidor que realizou a pesquisa, conforme cadastrado no SIGI Pesquisador: O nome do servidor que realizou a pesquisa, conforme cadastrado no SIGI
Câmara: A sigla da UF seguida de um espaço, seguido de um caracter - seguido de um espaço seguido do nome do município, Câmara: A sigla da UF seguida de um espaço, seguido de um caracter - seguido de um espaço seguido do nome do município,
@ -43,19 +43,19 @@ def importa(file_list):
Possui portal: Deve constar "sim" ou "não" indicando se a casa possui ou não portal. Possui portal: Deve constar "sim" ou "não" indicando se a casa possui ou não portal.
Portal Modelo: Deve constar "sim" ou "não" indicando se o portal da casa é o portal modelo ou não. Portal Modelo: Deve constar "sim" ou "não" indicando se o portal da casa é o portal modelo ou não.
URL: Deve conter a URL do portal da Casa. Opcionalmente pode ter alguma observação do pesquisador URL: Deve conter a URL do portal da Casa. Opcionalmente pode ter alguma observação do pesquisador
Observações: Deve conter as observações do pesquisador, caso existam.''' Observações: Deve conter as observações do pesquisador, caso existam.'''
for filename in file_list: for filename in file_list:
print 'Importando '+filename+'.csv' print 'Importando '+filename+'.csv'
with open(filename+'.csv', 'rb') as infile: with open(filename+'.csv', 'rb') as infile:
with open(filename+'.out', 'wb') as outfile: with open(filename+'.out', 'wb') as outfile:
indata = csv.reader(infile, delimiter=',', quotechar='"') indata = csv.reader(infile, delimiter=',', quotechar='"')
outdata = csv.writer(outfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL) outdata = csv.writer(outfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
head = next(indata) head = next(indata)
head.append('Erros encontrados') head.append('Erros encontrados')
outdata.writerow(head) outdata.writerow(head)
for row in indata: for row in indata:
data = row[0].strip() data = row[0].strip()
pesquisador = row[1].strip() pesquisador = row[1].strip()
@ -64,32 +64,32 @@ def importa(file_list):
pmodelo = row[4].strip() pmodelo = row[4].strip()
url = row[5].strip() url = row[5].strip()
obs = row[6].strip() obs = row[6].strip()
if data == '': if data == '':
data = None data = None
else: else:
data = datetime.strptime(data, '%d/%m/%y %H:%M') data = datetime.strptime(data, '%d/%m/%y %H:%M')
uf = uf_cidade[:2] uf = uf_cidade[:2]
cidade = uf_cidade[5:] cidade = uf_cidade[5:]
if tem_portal.lower() == 'não': if tem_portal.lower() == 'não':
inclusao = CasaLegislativa.INCLUSAO_DIGITAL_CHOICES[1][0] inclusao = Orgao.INCLUSAO_DIGITAL_CHOICES[1][0]
elif pmodelo.lower() == 'não': elif pmodelo.lower() == 'não':
inclusao = CasaLegislativa.INCLUSAO_DIGITAL_CHOICES[3][0] inclusao = Orgao.INCLUSAO_DIGITAL_CHOICES[3][0]
else: else:
inclusao = CasaLegislativa.INCLUSAO_DIGITAL_CHOICES[2][0] inclusao = Orgao.INCLUSAO_DIGITAL_CHOICES[2][0]
l = url.splitlines() l = url.splitlines()
url = '' url = ''
for s in l: for s in l:
p = urlparse.urlparse(s) p = urlparse.urlparse(s)
if p.netloc: if p.netloc:
url = s url = s
else: else:
obs = obs + '\n' + s obs = obs + '\n' + s
if pesquisador == '': if pesquisador == '':
servidor = None servidor = None
else: else:
@ -101,8 +101,8 @@ def importa(file_list):
continue continue
else: else:
servidor = servidor[0] servidor = servidor[0]
casa = CasaLegislativa.objects.filter(tipo_id=1, municipio__uf__sigla=uf, municipio__nome__iexact=cidade) casa = Orgao.objects.filter(tipo_id=1, municipio__uf__sigla=uf, municipio__nome__iexact=cidade)
cc = casa.count() cc = casa.count()
if cc == 0: if cc == 0:
row.append('Municipio nao foi encontrado') row.append('Municipio nao foi encontrado')
@ -114,18 +114,18 @@ def importa(file_list):
continue continue
else: else:
casa = casa[0] casa = casa[0]
casa.inclusao_digital = inclusao casa.inclusao_digital = inclusao
casa.data_levantamento = data casa.data_levantamento = data
casa.pesquisador = servidor casa.pesquisador = servidor
if casa.pagina_web == '': if casa.pagina_web == '':
casa.pagina_web = url casa.pagina_web = url
else: else:
obs = url + '\n' + obs obs = url + '\n' + obs
casa.obs_pesquisa = obs casa.obs_pesquisa = obs
casa.save() casa.save()
print 'O arquivo '+filename+'.out foi criado com os registros que nao puderam ser importados' print 'O arquivo '+filename+'.out foi criado com os registros que nao puderam ser importados'

5592
scripts/setgerentes/dados_gerentes.py

File diff suppressed because it is too large

16
scripts/setgerentes/set_gerentes.py

@ -1,16 +0,0 @@
# -*- coding: utf-8 -*-
from dados_gerentes import atrib, gerentes
from sigi.apps.casas.models import CasaLegislativa
def salvar():
for cod, abrev_gerente in atrib:
casas = CasaLegislativa.objects.filter(municipio__codigo_ibge=cod, tipo__sigla='CM')
if not casas:
print '############################# SEM CASA: ', cod
elif len(casas) > 1:
print '############################# VÁRIAS CASAS: ', cod, casas
else:
[c] = casas
c.gerente_contas = gerentes[abrev_gerente]
c.save()

4
scripts/verificacao_arquivos_faltando_media.py

@ -9,7 +9,7 @@ from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from terminaltables import AsciiTable from terminaltables import AsciiTable
from sigi.apps.casas.models import CasaLegislativa from sigi.apps.casas.models import Orgao
from sigi.apps.convenios.models import Anexo as AnexoConvenios from sigi.apps.convenios.models import Anexo as AnexoConvenios
from sigi.apps.diagnosticos.models import Anexo as AnexoDiagnosticos from sigi.apps.diagnosticos.models import Anexo as AnexoDiagnosticos
from sigi.apps.ocorrencias.models import Anexo as AnexoOcorrencias from sigi.apps.ocorrencias.models import Anexo as AnexoOcorrencias
@ -31,7 +31,7 @@ def url(obj):
# IMAGENS FALTANDO # IMAGENS FALTANDO
imagens_faltando = [[u"SITUAÇÃO DO ARQUIVO DA FOTO ", "URL", "OBJETO"]] imagens_faltando = [[u"SITUAÇÃO DO ARQUIVO DA FOTO ", "URL", "OBJETO"]]
for cl in (CasaLegislativa, Parlamentar, Servidor): for cl in (Orgao, Parlamentar, Servidor):
for a in cl.objects.all(): for a in cl.objects.all():
if a.foto: if a.foto:
imagens_faltando.append([ imagens_faltando.append([

392
sigi/apps/casas/admin.py

@ -1,24 +1,26 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.core.urlresolvers import reverse
from django.contrib import admin from django.contrib import admin
from django.contrib.contenttypes import generic from django.contrib.contenttypes import generic
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from image_cropping import ImageCroppingMixin from image_cropping import ImageCroppingMixin
from sigi.apps.casas.forms import CasaLegislativaForm from sigi.apps.casas.forms import OrgaoForm
from sigi.apps.casas.models import CasaLegislativa, Presidente, Funcionario, TipoCasaLegislativa from sigi.apps.casas.models import Orgao, Presidente, Funcionario, TipoOrgao
from sigi.apps.casas.views import report_complete, labels_report, export_csv, \ from sigi.apps.casas.views import report_complete, labels_report, export_csv, \
labels_report_sem_presidente, report, \ labels_report_sem_presidente, report, \
adicionar_casas_carrinho adicionar_casas_carrinho
from sigi.apps.contatos.models import Telefone from sigi.apps.contatos.models import Telefone
from sigi.apps.convenios.models import Convenio from sigi.apps.convenios.models import Convenio, Projeto
from sigi.apps.diagnosticos.models import Diagnostico # from sigi.apps.diagnosticos.models import Diagnostico
from sigi.apps.inventario.models import Bem # from sigi.apps.inventario.models import Bem
from sigi.apps.metas.models import PlanoDiretor from sigi.apps.metas.models import PlanoDiretor
from sigi.apps.ocorrencias.models import Ocorrencia from sigi.apps.ocorrencias.models import Ocorrencia
from sigi.apps.parlamentares.models import Legislatura # from sigi.apps.parlamentares.models import Legislatura
from sigi.apps.servicos.models import Servico from sigi.apps.servicos.models import Servico, TipoServico
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from sigi.apps.utils import queryset_ascii from sigi.apps.utils import queryset_ascii
from sigi.apps.utils.base_admin import BaseModelAdmin from sigi.apps.utils.base_admin import BaseModelAdmin
@ -32,58 +34,118 @@ class TelefonesInline(generic.GenericTabularInline):
class PresidenteInline(admin.StackedInline): class PresidenteInline(admin.StackedInline):
model = Presidente model = Presidente
exclude = ['cargo', 'funcao'] 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',) readonly_fields = ('ult_alteracao',)
extra = 1 extra = 1
max_num = 1 max_num = 1
inlines = (TelefonesInline) verbose_name_plural = _(u'Presidente')
class FuncionariosInline(admin.StackedInline): class FuncionariosInline(admin.StackedInline):
model = Funcionario model = Funcionario
fieldsets = ((None, { fields = ('nome', 'sexo', 'data_nascimento', 'nota', 'email', 'cargo',
'fields': (('nome', 'sexo', 'nota', 'email'), ('cargo', 'funcao', 'setor', 'tempo_de_servico'), 'ult_alteracao') 'funcao', 'setor', 'tempo_de_servico', 'ult_alteracao',
}),) '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',) readonly_fields = ('ult_alteracao',)
extra = 1 extra = 1
inlines = (TelefonesInline,) inlines = (TelefonesInline,)
def get_queryset(self, request): def get_queryset(self, request):
return self.model.objects.exclude(cargo=_(u"Presidente")) return (self.model.objects.exclude(
cargo='Presidente').exclude(desativado=True)
)
class ConveniosInline(admin.StackedInline): class ConveniosInline(admin.TabularInline):
model = Convenio model = Convenio
fieldsets = ( fieldsets = (
(None, {'fields': (('link_convenio', 'num_processo_sf', 'num_convenio', 'projeto', 'observacao'), (None, {'fields': (
('data_adesao', 'data_retorno_assinatura', 'data_termo_aceite', 'data_pub_diario', 'data_devolucao_via', 'data_postagem_correio'), ('link_sigad', 'status_convenio', 'num_convenio',
('data_devolucao_sem_assinatura', 'data_retorno_sem_assinatura',), 'projeto', 'observacao'),
('get_tramitacoes', 'get_anexos', 'get_equipamentos',), ('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',),
('link_convenio',),
)}),
) )
readonly_fields = ['get_tramitacoes', 'get_anexos', 'get_equipamentos', '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 extra = 0
can_delete = False
template = 'admin/casas/convenios_inline.html'
def get_tramitacoes(self, obj): def has_add_permission(self, request):
return '<br/>'.join([t.__unicode__() for t in obj.tramitacao_set.all()]) return False
get_tramitacoes.short_description = _(u'Tramitações')
get_tramitacoes.allow_tags = True
# def get_tramitacoes(self, obj):
# return '<br/>'.join([t.__unicode__() for t in obj.tramitacao_set.all()])
#
# get_tramitacoes.short_description = _(u'Tramitações')
# get_tramitacoes.allow_tags = True
#
def get_anexos(self, obj): def get_anexos(self, obj):
return '<br/>'.join(['<a href="%s" target="_blank">%s</a>' % (a.arquivo.url, a.__unicode__()) for a in obj.anexo_set.all()]) return '<br/>'.join(['<a href="%s" target="_blank">%s</a>' % (a.arquivo.url, a.__unicode__()) for a in obj.anexo_set.all()])
get_anexos.short_description = _(u'Anexos') get_anexos.short_description = _(u'Anexos')
get_anexos.allow_tags = True get_anexos.allow_tags = True
#
# def get_equipamentos(self, obj):
# return '<br/>'.join([e.__unicode__() for e in obj.equipamentoprevisto_set.all()])
#
# get_equipamentos.short_description = _(u'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 [u"Vencido", u"Desistência", u"Cancelado"]:
label = r"danger"
elif status == u"Vigente":
label = r"success"
elif status == u"Pendente":
label = r"warning"
else:
label = r"info"
return u'<p class="label label-{label}">{status}</p>'.format(label=label, status=status)
status_convenio.short_description = _(u"Status do convênio")
status_convenio.allow_tags = True
def get_equipamentos(self, obj):
return '<br/>'.join([e.__unicode__() for e in obj.equipamentoprevisto_set.all()])
get_equipamentos.short_description = _(u'Equipamentos previstos')
get_equipamentos.allow_tags = True
def link_convenio(self, obj): def link_convenio(self, obj):
if obj.pk is None: if obj.pk is None:
return "" 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 = reverse('admin:%s_%s_change' % (obj._meta.app_label, obj._meta.module_name), args=[obj.pk])
url = url + '?_popup=1' url = url + '?_popup=1'
return """<input id="edit_convenio-%s" type="hidden"/> return """<input id="edit_convenio-%s" type="hidden"/>
@ -94,64 +156,77 @@ class ConveniosInline(admin.StackedInline):
link_convenio.short_description = _(u'Editar convenio') link_convenio.short_description = _(u'Editar convenio')
link_convenio.allow_tags = True link_convenio.allow_tags = True
def link_sigad(self, obj):
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):
if obj.pk is None: if obj.pk is None:
return "" return ""
from django.core.urlresolvers import reverse return obj.get_sigad_url()
url = reverse('admin:%s_%s_change' % (obj._meta.app_label, obj._meta.module_name), args=[obj.pk])
url = url + '?_popup=1' link_sigad.short_description = _("Processo no Senado")
return """<input id="edit_legislatura-%s" type="hidden"/> link_sigad.allow_tags = True
<a id="lookup_edit_legislatura-%s" href="%s" class="changelink" onclick="return showRelatedObjectLookupPopup(this)">
Editar # class LegislaturaInline(admin.TabularInline):
</a>""" % (obj.pk, obj.pk, url) # model = Legislatura
# fields = ['numero', 'data_inicio', 'data_fim', 'data_eleicao', 'total_parlamentares', 'link_parlamentares', ]
link_parlamentares.short_description = _(u'Parlamentares') # readonly_fields = ['link_parlamentares', ]
link_parlamentares.allow_tags = True
# def link_parlamentares(self, obj):
# if obj.pk is None:
class DiagnosticoInline(admin.TabularInline): # return ""
model = Diagnostico # from django.core.urlresolvers import reverse
fields = ['data_visita_inicio', 'data_visita_fim', 'publicado', 'data_publicacao', 'responsavel', 'link_diagnostico', ] # url = reverse('admin:%s_%s_change' % (obj._meta.app_label, obj._meta.module_name), args=[obj.pk])
readonly_fields = ['data_visita_inicio', 'data_visita_fim', 'publicado', 'data_publicacao', 'responsavel', 'link_diagnostico', ] # url = url + '?_popup=1'
extra = 0 # return """<input id="edit_legislatura-%s" type="hidden"/>
max_num = 0 # <a id="lookup_edit_legislatura-%s" href="%s" class="changelink" onclick="return showRelatedObjectLookupPopup(this)">
can_delete = False # Editar
# </a>""" % (obj.pk, obj.pk, url)
def link_diagnostico(self, obj):
if obj.pk is None: # link_parlamentares.short_description = _(u'Parlamentares')
return "" # link_parlamentares.allow_tags = True
url = reverse('admin:%s_%s_change' % (obj._meta.app_label, obj._meta.module_name), args=["%s.pdf" % obj.pk])
return """<input id="edit_diagnostico-%s" type="hidden"/> # class DiagnosticoInline(admin.TabularInline):
<a id="lookup_edit_diagnostico-%s" href="%s" class="button" target="_blank"> # model = Diagnostico
Abrir PDF # fields = ['data_visita_inicio', 'data_visita_fim', 'publicado', 'data_publicacao', 'responsavel', 'link_diagnostico', ]
</a>""" % (obj.pk, obj.pk, url) # readonly_fields = ['data_visita_inicio', 'data_visita_fim', 'publicado', 'data_publicacao', 'responsavel', 'link_diagnostico', ]
# extra = 0
link_diagnostico.short_description = _(u'Ver PDF') # max_num = 0
link_diagnostico.allow_tags = True # can_delete = False
# def link_diagnostico(self, obj):
class BemInline(admin.TabularInline): # if obj.pk is None:
model = Bem # return ""
# url = reverse('admin:%s_%s_change' % (obj._meta.app_label, obj._meta.module_name), args=["%s.pdf" % obj.pk])
# return """<input id="edit_diagnostico-%s" type="hidden"/>
# <a id="lookup_edit_diagnostico-%s" href="%s" class="button" target="_blank">
# Abrir PDF
# </a>""" % (obj.pk, obj.pk, url)
# link_diagnostico.short_description = _(u'Ver PDF')
# link_diagnostico.allow_tags = True
# class BemInline(admin.TabularInline):
# model = Bem
class ServicoInline(admin.TabularInline): class ServicoInline(admin.TabularInline):
model = Servico model = Servico
fields = ['url', 'contato_tecnico', 'contato_administrativo', 'hospedagem_interlegis', 'data_ativacao', 'data_alteracao', 'data_desativacao'] fields = ('link_url', 'contato_tecnico', 'contato_administrativo',
readonly_fields = ['url', 'contato_tecnico', 'contato_administrativo', 'hospedagem_interlegis', 'data_ativacao', 'data_alteracao', 'data_desativacao'] 'hospedagem_interlegis', 'data_ativacao', 'data_alteracao',
'data_desativacao')
readonly_fields = ['link_url', 'contato_tecnico', 'contato_administrativo',
'hospedagem_interlegis', 'data_ativacao',
'data_alteracao', 'data_desativacao']
extra = 0 extra = 0
max_num = 0 max_num = 0
can_delete = False can_delete = False
def link_url(self, servico):
if servico.data_desativacao is not None:
return servico.url
return u'<a href="{url}" target="_blank">{url}</a>'.format(url=servico.url)
link_url.short_description = _(u'URL do serviço')
link_url.allow_tags = True
class PlanoDiretorInline(admin.TabularInline): # class PlanoDiretorInline(admin.TabularInline):
model = PlanoDiretor # model = PlanoDiretor
class OcorrenciaInline(admin.TabularInline): class OcorrenciaInline(admin.TabularInline):
model = Ocorrencia model = Ocorrencia
@ -160,8 +235,8 @@ class OcorrenciaInline(admin.TabularInline):
extra = 0 extra = 0
max_num = 0 max_num = 0
can_delete = False can_delete = False
template = 'casas/ocorrencia_inline.html' template = 'admin/casas/ocorrencia_inline.html'
def link_editar(self, obj): def link_editar(self, obj):
if obj.pk is None: if obj.pk is None:
return "" return ""
@ -173,80 +248,171 @@ class OcorrenciaInline(admin.TabularInline):
link_editar.short_description = _(u'Editar') link_editar.short_description = _(u'Editar')
link_editar.allow_tags = True link_editar.allow_tags = True
class GerentesContasFilter(admin.filters.RelatedFieldListFilter):
class GerentesInterlegisFilter(admin.filters.RelatedFieldListFilter):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(GerentesContasFilter, self).__init__(*args, **kwargs) super(GerentesInterlegisFilter, self).__init__(*args, **kwargs)
gerentes = Servidor.objects.filter(casas_que_gerencia__isnull=False).order_by('nome_completo').distinct() gerentes = Servidor.objects.filter(casas_que_gerencia__isnull=False).order_by('nome_completo').distinct()
self.lookup_choices = [(x.id, x) for x in gerentes] self.lookup_choices = [(x.id, x) for x in gerentes]
class CasaLegislativaAdmin(ImageCroppingMixin, BaseModelAdmin): class ConvenioFilter(admin.SimpleListFilter):
form = CasaLegislativaForm title = _(u"Tipo de convênio")
parameter_name = 'convenio'
def lookups(self, request, model_admin):
return (
('SC', _(u"Sem nenhum convênio")),
('CC', _(u"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 ServicoFilter(admin.SimpleListFilter):
title = _(u"Serviço")
parameter_name = 'servico'
def lookups(self, request, model_admin):
return (
('SS', _(u"Sem nenhum serviço")),
('CS', _(u"Com algum serviço")),
('CH', _(u"Com algum serviço de hospedagem")),
('CR', _(u"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')
@admin.register(Orgao)
class OrgaoAdmin(ImageCroppingMixin, BaseModelAdmin):
form = OrgaoForm
actions = ['adicionar_casas', ] actions = ['adicionar_casas', ]
inlines = (TelefonesInline, PresidenteInline, FuncionariosInline, ConveniosInline, LegislaturaInline, inlines = (TelefonesInline, PresidenteInline, FuncionariosInline,
DiagnosticoInline, BemInline, ServicoInline, PlanoDiretorInline, OcorrenciaInline, ) ConveniosInline, ServicoInline, OcorrenciaInline,)
list_display = ('nome', 'municipio', 'gerente_contas', 'get_convenios') list_display = ('id', 'sigla', 'nome', 'get_uf', 'get_gerentes', 'get_convenios',
list_display_links = ('nome',) 'get_servicos')
list_filter = ('tipo', ('gerente_contas', GerentesContasFilter), 'municipio__uf__nome', 'convenio__projeto', list_display_links = ('sigla', 'nome',)
list_filter = ('tipo', ('gerentes_interlegis', GerentesInterlegisFilter),
'municipio__uf__nome', ConvenioFilter, ServicoFilter,
'inclusao_digital',) 'inclusao_digital',)
ordering = ('nome', 'municipio__uf') ordering = ('municipio__uf__nome', 'nome')
queyrset = queryset_ascii queryset = queryset_ascii
fieldsets = ( fieldsets = (
(None, { (None, {
'fields': ('tipo', 'nome', 'cnpj', 'num_parlamentares', 'gerente_contas') 'fields': ('tipo', 'nome', 'sigla', 'cnpj', 'num_parlamentares',
'gerentes_interlegis')
}), }),
(_(u'Endereço'), { (_(u'Endereço'), {
'fields': ('data_instalacao', 'logradouro', 'bairro', 'fields': ('data_instalacao', 'logradouro', 'bairro',
'municipio', 'cep', 'ult_alt_endereco'), 'municipio', 'cep', 'ult_alt_endereco'),
}), }),
(_(u'Presença na Internet'), { (_(u'Presença na Internet'), {
'fields': ('inclusao_digital', 'data_levantamento', 'pesquisador', 'pagina_web', 'email', 'obs_pesquisa',) 'fields': ('inclusao_digital', 'data_levantamento', 'pesquisador',
'pagina_web', 'email', 'obs_pesquisa',)
}), }),
(_(u'Outras informações'), { (_(u'Outras informações'), {
'fields': ('observacoes', 'foto', 'recorte'), 'fields': ('observacoes', 'horario_funcionamento', 'foto',
'recorte'),
}), }),
) )
raw_id_fields = ('municipio',) raw_id_fields = ('municipio',)
readonly_fields = ['num_parlamentares', ] readonly_fields = ['num_parlamentares', 'gerentes_interlegis',]
search_fields = ('search_text', 'cnpj', 'bairro', 'logradouro', search_fields = ('search_text', 'sigla', 'cnpj', 'bairro', 'logradouro',
'cep', 'municipio__nome', 'municipio__uf__nome', 'cep', 'municipio__nome', 'municipio__uf__nome',
'municipio__codigo_ibge', 'pagina_web', 'observacoes') 'municipio__codigo_ibge', 'pagina_web', 'observacoes')
def get_uf(self, obj):
return obj.municipio.uf.nome
get_uf.short_description = _(u'Unidade da Federação')
get_uf.admin_order_field = 'municipio__uf__nome'
def get_gerentes(self, obj):
return obj.lista_gerentes()
get_gerentes.short_description = _(u'Gerente Interlegis')
get_gerentes.allow_tags = True
def get_convenios(self, obj): def get_convenios(self, obj):
return '<ul>' + ''.join(['<li>%s</li>' % c.__unicode__() for c in obj.convenio_set.all()]) + '</ul>' return '<ul>' + ''.join(['<li>%s</li>' % c.__unicode__()
for c in obj.convenio_set.all()]) + '</ul>'
get_convenios.short_description = _(u'Convênios') get_convenios.short_description = _(u'Convênios')
get_convenios.allow_tags = True get_convenios.allow_tags = True
def get_servicos(self, obj):
return u'<ul>' + u''.join(
[u'<li><a href="{url}" target="_blank">{servico}</a></li>'.format(
url=s.url, servico=s.__unicode__()) for s in
obj.servico_set.filter(data_desativacao__isnull=True)]) + u'</ul>'
get_servicos.short_description = _(u'Serviços')
get_servicos.allow_tags = True
def changelist_view(self, request, extra_context=None): def changelist_view(self, request, extra_context=None):
return super(CasaLegislativaAdmin, self).changelist_view( return super(OrgaoAdmin, self).changelist_view(
request, request,
extra_context={'query_str': '?' + request.META['QUERY_STRING']} extra_context={'query_str': '?' + request.META['QUERY_STRING']}
) )
def lookup_allowed(self, lookup, value): def lookup_allowed(self, lookup, value):
return super(CasaLegislativaAdmin, self).lookup_allowed(lookup, value) or \ return (super(OrgaoAdmin, self).lookup_allowed(lookup, value) or
lookup in ['municipio__uf__codigo_ibge__exact', 'convenio__projeto__id__exact'] lookup in ['tipo__legislativo__exact',
'tipo__sigla__exact',
'municipio__uf__codigo_ibge__exact',
'convenio__projeto__id__exact'])
def etiqueta(self, request, queryset): def etiqueta(self, request, queryset):
return labels_report(request, queryset=queryset) return labels_report(request, queryset=queryset)
etiqueta.short_description = _(u"Gerar etiqueta(s) da(s) casa(s) selecionada(s)") etiqueta.short_description = _(u"Gerar etiqueta(s) da(s) casa(s) "
u"selecionada(s)")
def etiqueta_sem_presidente(self, request, queryset): def etiqueta_sem_presidente(self, request, queryset):
return labels_report_sem_presidente(request, queryset=queryset) return labels_report_sem_presidente(request, queryset=queryset)
etiqueta_sem_presidente.short_description = _(u"Gerar etiqueta(s) sem presidente da(s) casa(s) selecionada(s)") etiqueta_sem_presidente.short_description = _(u"Gerar etiqueta(s) sem "
u"presidente da(s) casa(s) "
u"selecionada(s)")
def relatorio(self, request, queryset): def relatorio(self, request, queryset):
return report(request, queryset=queryset) return report(request, queryset=queryset)
relatorio.short_description = _(u"Exportar a(s) casa(s) selecionada(s) para PDF") relatorio.short_description = _(u"Exportar a(s) casa(s) selecionada(s) "
u"para PDF")
def relatorio_completo(self, request, queryset): def relatorio_completo(self, request, queryset):
return report_complete(request, queryset=queryset) return report_complete(request, queryset=queryset)
relatorio_completo.short_description = _(u"Gerar relatório completo da(s) casa(s) selecionada(s)") relatorio_completo.short_description = _(u"Gerar relatório completo da(s) "
u"casa(s) selecionada(s)")
def relatorio_csv(self, request, queryset): def relatorio_csv(self, request, queryset):
return export_csv(request) return export_csv(request)
relatorio_csv.short_description = _(u"Exportar casa(s) selecionada(s) para CSV") relatorio_csv.short_description = _(u"Exportar casa(s) selecionada(s) "
u"para CSV")
def adicionar_casas(self, request, queryset): def adicionar_casas(self, request, queryset):
if 'carrinho_casas' in request.session: if 'carrinho_casas' in request.session:
@ -258,18 +424,20 @@ class CasaLegislativaAdmin(ImageCroppingMixin, BaseModelAdmin):
q2 = len(request.session['carrinho_casas']) q2 = len(request.session['carrinho_casas'])
quant = q2 - q1 quant = q2 - q1
if quant: if quant:
self.message_user(request, str(q2 - q1) + " " + _(u"Casas Legislativas adicionadas no carrinho")) self.message_user(request, str(q2 - q1) + " " +
_(u"Casas Legislativas adicionadas no carrinho"))
else: else:
self.message_user(request, _(u"As Casas Legislativas selecionadas já foram adicionadas anteriormente")) self.message_user(request, _(u"As Casas Legislativas selecionadas "
u"já foram adicionadas anteriormente"))
return HttpResponseRedirect('.') return HttpResponseRedirect('.')
adicionar_casas.short_description = _(u"Armazenar casas no carrinho para exportar") adicionar_casas.short_description = _(u"Armazenar casas no carrinho para "
u"exportar")
def get_actions(self, request): def get_actions(self, request):
actions = super(CasaLegislativaAdmin, self).get_actions(request) actions = super(OrgaoAdmin, self).get_actions(request)
if 'delete_selected' in actions: if 'delete_selected' in actions:
del actions['delete_selected'] del actions['delete_selected']
return actions return actions
admin.site.register(CasaLegislativa, CasaLegislativaAdmin) admin.site.register(TipoOrgao)
admin.site.register(TipoCasaLegislativa)

43
sigi/apps/casas/forms.py

@ -3,11 +3,17 @@ from django import forms
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from localflavor.br.forms import BRZipCodeField from localflavor.br.forms import BRZipCodeField
from sigi.apps.casas.models import CasaLegislativa from sigi.apps.casas.models import Orgao
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
class AtualizaCasaForm(forms.Form):
arquivo = forms.FileField(
required=True,
label=_(u"arquivo a importar"),
help_text=_(u"Envie um arquivo no formato CSV"),
)
class CasaLegislativaForm(forms.ModelForm): class OrgaoForm(forms.ModelForm):
# cnpj = BRCNPJField( # cnpj = BRCNPJField(
# label=_(u'CNPJ'), # label=_(u'CNPJ'),
# required=False, # required=False,
@ -16,12 +22,33 @@ class CasaLegislativaForm(forms.ModelForm):
cep = BRZipCodeField(label=_(u'CEP'), help_text=_(u'Formato') + ': <em>XXXXX-XXX</em>.') cep = BRZipCodeField(label=_(u'CEP'), help_text=_(u'Formato') + ': <em>XXXXX-XXX</em>.')
class Meta: class Meta:
model = CasaLegislativa model = Orgao
fields = '__all__' fields = '__all__'
# def clean(self):
# cleaned_data = super(OrgaoForm, self).clean()
# tipo = cleaned_data.get('tipo')
# municipio = cleaned_data.get('municipio')
# if tipo.legislativo:
# if Orgao.objects.filter(tipo=tipo)
class PortfolioForm(forms.Form): class PortfolioForm(forms.Form):
gerente_contas = forms.ModelChoiceField(queryset=Servidor.objects.all(), label=_(u"Atribuir casas para")) ACAO_CHOICES = (
('ADD', _(u"Adicionar")),
def __init__(self, label=_(u"Atribuir casas para"), *args, **kwargs): ('DEL', _(u"Remover"))
)
acao = forms.ChoiceField(
label=_(u"Ação"),
choices=ACAO_CHOICES,
initial='ADD',
widget=forms.RadioSelect
)
gerente = forms.ModelChoiceField(
queryset=Servidor.objects.all(),
label=_(u"Atribuir para")
)
# O label precisa ser trocado dependendo da região que se está visualizando
def __init__(self, label=_(u"Atribuir para"), *args, **kwargs):
super(PortfolioForm, self).__init__(*args, **kwargs) super(PortfolioForm, self).__init__(*args, **kwargs)
self.fields['gerente_contas'].label = label self.fields['gerente'].label = label

62
sigi/apps/casas/management/commands/importa_gerentes.py

@ -25,60 +25,74 @@
import csv import csv
import os import os
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from sigi.apps.casas.models import CasaLegislativa from sigi.apps.casas.models import Orgao
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from sigi.apps.contatos.models import Municipio from sigi.apps.contatos.models import Municipio
class Command(BaseCommand): class Command(BaseCommand):
args = u"data_file.csv" args = u"data_file.csv"
help = u"""Importa dados de atribuição de gerencia de relacionamentos de um arquivo CSV. help = u"""Importa dados de atribuição de gerencia de relacionamentos de um arquivo CSV.
A primeira linha do arquivo deve possuir um cabeçalho com os seguintes campos obrigatórios: A primeira linha do arquivo deve possuir um cabeçalho com os seguintes campos obrigatórios:
- cod_municipio : Código IBGE do município - cod_municipio : Código IBGE do município
- user_id : Nome de usuário (usado no login) do gerente de relacionamento da Casa - user_id : Nome de usuário (usado no login) do gerente de relacionamento da Casa
* Os nomes dos campos devem ser grafados exatamente como descrito.""" * Os nomes dos campos devem ser grafados exatamente como descrito."""
campos = {'cod_municipio', 'user_id'} campos = {'cod_municipio', 'user_id'}
def handle(self, *args, **options): def handle(self, *args, **options):
if len(args) != 1: if len(args) != 1:
raise CommandError(u"Informe UM arquivo csv a importar") raise CommandError(u"Informe UM arquivo csv a importar")
file_name = args[0] file_name = args[0]
if not os.path.isfile(file_name): if not os.path.isfile(file_name):
raise CommandError(u"Arquivo %s não encontrado" % [file_name,]) raise CommandError(u"Arquivo %s não encontrado" % [file_name,])
with open(file_name, 'rb') as csvfile: with open(file_name, 'rb') as csvfile:
reader = csv.DictReader(csvfile) reader = csv.DictReader(csvfile)
if not self.campos.issubset(reader.fieldnames): if not self.campos.issubset(reader.fieldnames):
raise CommandError(u"O arquivo não possui todos os campos obrigatórios") raise CommandError(u"O arquivo não possui todos os campos obrigatórios")
CasaLegislativa.objects.update(gerente_contas=None) Orgao.gerentes_interlegis.through.objects.all().delete()
erros = 0 erros = 0
for reg in reader: for reg in reader:
try: try:
municipio = Municipio.objects.get(codigo_ibge=reg['cod_municipio']) municipio = Municipio.objects.get(
codigo_ibge=reg['cod_municipio']
)
except Municipio.DoesNotExist: except Municipio.DoesNotExist:
self.stdout.write(u"(Linha %s): não existe Município com código IBGE '%s'" % self.stdout.write(u"{linha}: não existe Município com "
(reader.line_num, reg['cod_municipio'],)) u"código IBGE {ibge}'".format(
linha=reader.line_num,
ibge=reg['cod_municipio'])
)
erros = erros + 1 erros = erros + 1
continue continue
try: try:
gerente = Servidor.objects.get(user__username=reg['user_id']) gerente = Servidor.objects.get(
user__username=reg['user_id']
)
except Servidor.DoesNotExist: except Servidor.DoesNotExist:
self.stdout.write(u"(Linha %s): não existe Servidor com userid '%s'" % self.stdout.write(u"({linha}): não existe Servidor com "
(reader.line_num, reg['user_id'],)) u"userid {userid}".format(
linha=reader.line_num,
userid=reg['user_id'])
)
erros = erros + 1 erros = erros + 1
continue continue
for casa in municipio.casalegislativa_set.filter(tipo__sigla__in=['AL', 'CM']): for casa in municipio.orgao_set.filter(
casa.gerente_contas = gerente tipo__sigla__in=['AL', 'CM']):
casa.gerentes_interlegis.add(gerente)
casa.save() casa.save()
self.stdout.write(u"Importação concluída. %s erros em %s linhas" % (erros, reader.line_num,)) self.stdout.write(u"Importação concluída. {erros} erros em {linhas}"
u" linhas".format(erros=erros,
linhas=reader.line_num)
)

26
sigi/apps/casas/migrations/0003_auto_20200207_0919.py

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0002_auto_20150710_1247'),
]
operations = [
migrations.AddField(
model_name='casalegislativa',
name='horario_funcionamento',
field=models.CharField(max_length=100, verbose_name='Hor\xe1rio de funcionamento da Casa Legislativa', blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='funcionario',
name='data_nascimento',
field=models.DateField(null=True, verbose_name='Data de nascimento', blank=True),
preserve_default=True,
),
]

20
sigi/apps/casas/migrations/0004_auto_20201015_0810.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0003_auto_20200207_0919'),
]
operations = [
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),
preserve_default=True,
),
]

21
sigi/apps/casas/migrations/0005_casalegislativa_gerentes_interlegis.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('servidores', '0001_initial'),
('casas', '0004_auto_20201015_0810'),
]
operations = [
migrations.AddField(
model_name='casalegislativa',
name='gerentes_interlegis',
field=models.ManyToManyField(related_name='casas_que_gerencia', verbose_name=b'Gerentes Interlegis', to='servidores.Servidor'),
preserve_default=True,
),
]

18
sigi/apps/casas/migrations/0006_remove_casalegislativa_gerente_contas.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0005_casalegislativa_gerentes_interlegis'),
]
operations = [
migrations.RemoveField(
model_name='casalegislativa',
name='gerente_contas',
),
]

128
sigi/apps/casas/migrations/0007_auto_20201016_1632.py

@ -0,0 +1,128 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0006_remove_casalegislativa_gerente_contas'),
]
operations = [
migrations.AddField(
model_name='funcionario',
name='desativado',
field=models.BooleanField(default=False, verbose_name='Desativado'),
preserve_default=True,
),
migrations.AddField(
model_name='funcionario',
name='observacoes',
field=models.TextField(verbose_name='Observa\xe7\xf5es', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='bairro',
field=models.CharField(max_length=100, verbose_name='Bairro', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='cep',
field=models.CharField(max_length=32, verbose_name='CEP'),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='codigo_interlegis',
field=models.CharField(max_length=3, verbose_name='C\xf3digo Interlegis', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='email',
field=models.EmailField(max_length=128, verbose_name='E-mail', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='foto',
field=models.ImageField(upload_to=b'imagens/casas', width_field=b'foto_largura', height_field=b'foto_altura', blank=True, verbose_name='Foto'),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='inclusao_digital',
field=models.CharField(default=b'NAO PESQUISADO', max_length=30, verbose_name='Inclus\xe3o digital', choices=[(b'NAO PESQUISADO', 'N\xe3o pesquisado'), (b'NAO POSSUI PORTAL', 'N\xe3o possui portal'), (b'PORTAL MODELO', 'Possui Portal Modelo'), (b'OUTRO PORTAL', 'Possui outro portal')]),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='logradouro',
field=models.CharField(help_text='Avenida, rua, pra\xe7a, jardim, parque...', max_length=100, verbose_name='Logradouro'),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='municipio',
field=models.ForeignKey(verbose_name='Munic\xedpio', to='contatos.Municipio'),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='nome',
field=models.CharField(help_text='Exemplo: <em>C\xe2mara Municipal de Pains</em>.', max_length=60, verbose_name='Nome'),
preserve_default=True,
),
migrations.AlterField(
model_name='casalegislativa',
name='pagina_web',
field=models.URLField(help_text='Exemplo: <em>http://www.camarapains.mg.gov.br</em>.', verbose_name='P\xe1gina web', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='funcionario',
name='cargo',
field=models.CharField(max_length=100, null=True, verbose_name='Cargo', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='funcionario',
name='nota',
field=models.CharField(max_length=70, null=True, verbose_name='Telefones', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='funcionario',
name='setor',
field=models.CharField(default=b'outros', max_length=100, verbose_name='Setor', choices=[(b'presidente', 'Presidente'), (b'contato_interlegis', 'Contato Interlegis'), (b'infraestrutura_fisica', 'Infraestrutura F\xedsica'), (b'estrutura_de_ti', 'Estrutura de TI'), (b'organizacao_do_processo_legislativo', 'Organiza\xe7\xe3o do Processo Legislativo'), (b'producao_legislativa', 'Produ\xe7\xe3o Legislativa'), (b'estrutura_de_comunicacao_social', 'Estrutura de Comunica\xe7\xe3o Social'), (b'estrutura_de_recursos_humanos', 'Estrutura de Recursos Humanos'), (b'gestao', 'Gest\xe3o'), (b'outros', 'Outros')]),
preserve_default=True,
),
migrations.AlterField(
model_name='funcionario',
name='sexo',
field=models.CharField(default=b'M', max_length=1, verbose_name='Sexo', choices=[(b'M', 'Masculino'), (b'F', 'Feminino')]),
preserve_default=True,
),
migrations.AlterField(
model_name='funcionario',
name='tempo_de_servico',
field=models.CharField(max_length=50, null=True, verbose_name='Tempo de servi\xe7o', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='tipocasalegislativa',
name='nome',
field=models.CharField(max_length=100, verbose_name='Nome'),
preserve_default=True,
),
migrations.AlterField(
model_name='tipocasalegislativa',
name='sigla',
field=models.CharField(max_length=5, verbose_name='Sigla'),
preserve_default=True,
),
]

45
sigi/apps/casas/migrations/0008_auto_20210218_1007.py

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('contatos', '0002_auto_20151104_0810'),
('casas', '0007_auto_20201016_1632'),
]
operations = [
migrations.AddField(
model_name='funcionario',
name='bairro',
field=models.CharField(max_length=100, verbose_name='Bairro', blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='funcionario',
name='cep',
field=models.CharField(max_length=10, verbose_name='CEP', blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='funcionario',
name='endereco',
field=models.CharField(max_length=100, verbose_name='Endere\xe7o', blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='funcionario',
name='municipio',
field=models.ForeignKey(verbose_name='Municipio', to='contatos.Municipio', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='funcionario',
name='redes_sociais',
field=models.TextField(help_text='Colocar um por linha', verbose_name='Redes sociais', blank=True),
preserve_default=True,
),
]

20
sigi/apps/casas/migrations/0009_auto_20210406_1055.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0008_auto_20210218_1007'),
]
operations = [
migrations.AlterField(
model_name='funcionario',
name='municipio',
field=models.ForeignKey(verbose_name='Municipio', blank=True, to='contatos.Municipio', null=True),
preserve_default=True,
),
]

18
sigi/apps/casas/migrations/0010_auto_20210406_1101.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0009_auto_20210406_1055'),
]
operations = [
migrations.RenameModel(
old_name='TipoCasaLegislativa',
new_name='TipoOrgao',
),
]

18
sigi/apps/casas/migrations/0011_auto_20210406_1135.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0010_auto_20210406_1101'),
]
operations = [
migrations.AlterModelOptions(
name='tipoorgao',
options={'verbose_name': 'Tipo de \xf3rg\xe3o', 'verbose_name_plural': 'Tipos de \xf3rg\xe3o'},
),
]

18
sigi/apps/casas/migrations/0012_auto_20210406_1420.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0011_auto_20210406_1135'),
]
operations = [
migrations.AlterModelOptions(
name='tipoorgao',
options={},
),
]

18
sigi/apps/casas/migrations/0013_auto_20210406_1428.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0012_auto_20210406_1420'),
]
operations = [
migrations.AlterModelOptions(
name='tipoorgao',
options={'verbose_name': 'Tipo de \xf3rg\xe3o', 'verbose_name_plural': 'Tipos de \xf3rg\xe3o'},
),
]

31
sigi/apps/casas/migrations/0014_auto_20210406_1945.py

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import image_cropping.fields
import sigi.apps.utils
class Migration(migrations.Migration):
dependencies = [
# ('metas', '0002_auto_20210406_1945'),
('contatos', '0002_auto_20151104_0810'),
('servidores', '0001_initial'),
# ('parlamentares', '0002_auto_20210406_1945'),
# ('servicos', '0005_auto_20210406_1945'),
('servicos', '0004_delete_casaatendida'),
# ('inventario', '0002_auto_20210406_1945'),
# ('convenios', '0003_auto_20210406_1945'),
# ('ocorrencias', '0003_auto_20210406_1945'),
# ('diagnosticos', '0004_auto_20210406_1945'),
# ('eventos', '0005_auto_20210406_1945'),
('casas', '0013_auto_20210406_1428'),
]
operations = [
migrations.RenameModel(
old_name='CasaLegislativa',
new_name='Orgao',
),
]

28
sigi/apps/casas/migrations/0015_auto_20210407_0801.py

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0014_auto_20210406_1945'),
]
operations = [
migrations.AlterModelOptions(
name='orgao',
options={'ordering': ('nome',), 'verbose_name': '\xd3rg\xe3o', 'verbose_name_plural': '\xd3rg\xe3os'},
),
migrations.AddField(
model_name='tipoorgao',
name='legislativo',
field=models.BooleanField(default=False, verbose_name='Poder legislativo'),
preserve_default=True,
),
migrations.AlterUniqueTogether(
name='orgao',
unique_together=set([]),
),
]

20
sigi/apps/casas/migrations/0016_auto_20210407_1559.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0015_auto_20210407_0801'),
]
operations = [
migrations.AlterField(
model_name='orgao',
name='gerentes_interlegis',
field=models.ManyToManyField(related_name='casas_que_gerencia', verbose_name='Gerentes Interlegis', to='servidores.Servidor', blank=True),
preserve_default=True,
),
]

45
sigi/apps/casas/migrations/0017_auto_20210416_0841.py

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('casas', '0016_auto_20210407_1559'),
]
operations = [
migrations.AlterField(
model_name='funcionario',
name='casa_legislativa',
field=models.ForeignKey(verbose_name='\xf3rg\xe3o', to='casas.Orgao'),
preserve_default=True,
),
migrations.AlterField(
model_name='funcionario',
name='municipio',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='Municipio', blank=True, to='contatos.Municipio', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='orgao',
name='municipio',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Munic\xedpio', to='contatos.Municipio'),
preserve_default=True,
),
migrations.AlterField(
model_name='orgao',
name='pesquisador',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='Pesquisador', blank=True, to='servidores.Servidor', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='orgao',
name='tipo',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Tipo', to='casas.TipoOrgao'),
preserve_default=True,
),
]

20
sigi/apps/casas/migrations/0018_orgao_sigla.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0017_auto_20210416_0841'),
]
operations = [
migrations.AddField(
model_name='orgao',
name='sigla',
field=models.CharField(max_length=30, verbose_name='sigla do \xf3rg\xe3o', blank=True),
preserve_default=True,
),
]

26
sigi/apps/casas/migrations/0019_auto_20210501_1058.py

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0018_orgao_sigla'),
]
operations = [
migrations.AlterField(
model_name='funcionario',
name='email',
field=models.CharField(max_length=250, verbose_name='e-mail', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='funcionario',
name='nota',
field=models.CharField(max_length=250, null=True, verbose_name='Telefones', blank=True),
preserve_default=True,
),
]

18
sigi/apps/casas/migrations/0020_auto_20210611_0946.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('casas', '0019_auto_20210501_1058'),
]
operations = [
migrations.AlterModelOptions(
name='tipoorgao',
options={'ordering': ('nome',), 'verbose_name': 'Tipo de \xf3rg\xe3o', 'verbose_name_plural': 'Tipos de \xf3rg\xe3o'},
),
]

295
sigi/apps/casas/models.py

@ -1,108 +1,170 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from datetime import datetime
import random import random
from string import ascii_uppercase from string import ascii_uppercase
from unicodedata import normalize from unicodedata import normalize
from django.core.exceptions import ValidationError
from datetime import datetime from django.utils.translation import ugettext as _
from django.contrib.contenttypes import generic from django.contrib.contenttypes import generic
from django.db import models from django.db import models
from image_cropping import ImageRatioField from image_cropping import ImageRatioField
from sigi.apps.contatos.models import Municipio
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from sigi.apps.utils import SearchField from sigi.apps.utils import SearchField
class TipoOrgao(models.Model):
class TipoCasaLegislativa(models.Model):
""" Modelo para representar o tipo da Casa Legislativa """ Modelo para representar o tipo da Casa Legislativa
Geralmente: Câmara Municipal, Assembléia Legislativa, Geralmente: Câmara Municipal, Assembléia Legislativa,
Câmara Distrital ou Legislativo Federal Câmara Distrital ou Legislativo Federal
""" """
sigla = models.CharField( sigla = models.CharField(_(u"Sigla"), max_length=5)
max_length=5 nome = models.CharField(_(u"Nome"), max_length=100)
) legislativo = models.BooleanField(_(u"Poder legislativo"), default=False)
nome = models.CharField(
max_length=100 class Meta:
) ordering = ('nome',)
verbose_name = _(u"Tipo de órgão")
verbose_name_plural = _(u"Tipos de órgão")
def __unicode__(self): def __unicode__(self):
return self.nome return self.nome
class Orgao(models.Model):
class CasaLegislativa(models.Model):
""" Modelo para representar uma Casa Legislativa """ Modelo para representar uma Casa Legislativa
""" """
INCLUSAO_DIGITAL_CHOICES = ( INCLUSAO_DIGITAL_CHOICES = (
('NAO PESQUISADO', u'Não pesquisado'), ('NAO PESQUISADO', _(u'Não pesquisado')),
('NAO POSSUI PORTAL', u'Não possui portal'), ('NAO POSSUI PORTAL', _(u'Não possui portal')),
('PORTAL MODELO', u'Possui Portal Modelo'), ('PORTAL MODELO', _(u'Possui Portal Modelo')),
('OUTRO PORTAL', u'Possui outro portal'), ('OUTRO PORTAL', _(u'Possui outro portal')),
) )
nome = models.CharField( nome = models.CharField(
_(u"Nome"),
max_length=60, max_length=60,
help_text='Exemplo: <em>Câmara Municipal de Pains</em>.' help_text=_(u'Exemplo: <em>Câmara Municipal de Pains</em>.')
)
sigla = models.CharField(
_(u"sigla do órgão"),
max_length=30,
blank=True
) )
# Guarda um campo para ser usado em buscas em caixa baixa e sem acento # Guarda um campo para ser usado em buscas em caixa baixa e sem acento
search_text = SearchField(field_names=['nome']) search_text = SearchField(field_names=['nome'])
# search_text.projeto_filter = True tipo = models.ForeignKey(
tipo = models.ForeignKey(TipoCasaLegislativa, verbose_name="Tipo") TipoOrgao,
cnpj = models.CharField('CNPJ', max_length=32, blank=True) on_delete=models.PROTECT,
observacoes = models.TextField(u'observações', blank=True) verbose_name=_(u"Tipo")
)
cnpj = models.CharField(_(u"CNPJ"), max_length=32, blank=True)
observacoes = models.TextField(_(u'observações'), blank=True)
horario_funcionamento = models.CharField(
_(u"Horário de funcionamento da Casa Legislativa"),
max_length=100,
blank=True,
)
# num_parlamentares = models.PositiveIntegerField('Número de parlamentares') # num_parlamentares = models.PositiveIntegerField('Número de parlamentares')
codigo_interlegis = models.CharField('Código Interlegis', max_length=3, blank=True) codigo_interlegis = models.CharField(
_(u'Código Interlegis'),
max_length=3,
blank=True
)
# codigo_interlegis.ts_filter = True # codigo_interlegis.ts_filter = True
gerente_contas = models.ForeignKey(Servidor, verbose_name="Gerente de contas", null=True, blank=True, related_name='casas_que_gerencia') gerentes_interlegis = models.ManyToManyField(
Servidor,
verbose_name=_(u"Gerentes Interlegis"),
related_name='casas_que_gerencia',
blank=True,
)
# Informações de contato # Informações de contato
logradouro = models.CharField( logradouro = models.CharField(
_(u"Logradouro"),
max_length=100, max_length=100,
help_text='Avenida, rua, praça, jardim, parque...' help_text=_(u'Avenida, rua, praça, jardim, parque...')
) )
bairro = models.CharField(max_length=100, blank=True) bairro = models.CharField(_(u"Bairro"), max_length=100, blank=True)
municipio = models.ForeignKey( municipio = models.ForeignKey(
'contatos.Municipio', 'contatos.Municipio',
verbose_name='município' on_delete=models.PROTECT,
verbose_name=_(u'Município')
) )
# municipio.uf_filter = True # municipio.uf_filter = True
cep = models.CharField(max_length=32) cep = models.CharField(_(u"CEP"), max_length=32)
email = models.EmailField('e-mail', max_length=128, blank=True) email = models.EmailField(_(u'E-mail'), max_length=128, blank=True)
pagina_web = models.URLField( pagina_web = models.URLField(
u'página web', _(u'Página web'),
help_text='Exemplo: <em>http://www.camarapains.mg.gov.br</em>.', help_text=_(u'Exemplo: <em>http://www.camarapains.mg.gov.br</em>.'),
blank=True,
)
inclusao_digital = models.CharField(
_(u"Inclusão digital"),
max_length=30,
choices=INCLUSAO_DIGITAL_CHOICES,
default=INCLUSAO_DIGITAL_CHOICES[0][0]
)
data_levantamento = models.DateTimeField(
_(u"Data/hora da pesquisa"),
null=True,
blank=True
)
pesquisador = models.ForeignKey(
Servidor,
on_delete=models.SET_NULL,
verbose_name=_(u"Pesquisador"),
null=True,
blank=True
)
obs_pesquisa = models.TextField(
_(u"Observações do pesquisador"),
blank=True
)
ult_alt_endereco = models.DateTimeField(
_(u'Última alteração do endereço'),
null=True,
blank=True, blank=True,
editable=True
) )
inclusao_digital = models.CharField(max_length=30, choices=INCLUSAO_DIGITAL_CHOICES, default=INCLUSAO_DIGITAL_CHOICES[0][0])
data_levantamento = models.DateTimeField(u"Data/hora da pesquisa", null=True, blank=True)
pesquisador = models.ForeignKey(Servidor, verbose_name=u"Pesquisador", null=True, blank=True)
obs_pesquisa = models.TextField(u"Observações do pesquisador", blank=True)
ult_alt_endereco = models.DateTimeField(u'Última alteração do endereço', null=True, blank=True, editable=True)
telefones = generic.GenericRelation('contatos.Telefone') telefones = generic.GenericRelation('contatos.Telefone')
foto = models.ImageField( foto = models.ImageField(
_(u"Foto"),
upload_to='imagens/casas', upload_to='imagens/casas',
width_field='foto_largura', width_field='foto_largura',
height_field='foto_altura', height_field='foto_altura',
blank=True blank=True
) )
recorte = ImageRatioField('foto', '400x300', verbose_name="Recorte", ) recorte = ImageRatioField('foto', '400x300', verbose_name=_("Recorte"))
foto_largura = models.SmallIntegerField(editable=False, null=True) foto_largura = models.SmallIntegerField(editable=False, null=True)
foto_altura = models.SmallIntegerField(editable=False, null=True) foto_altura = models.SmallIntegerField(editable=False, null=True)
data_instalacao = models.DateField(u'Data de instalação da Casa Legislativa', null=True, blank=True) data_instalacao = models.DateField(
_(u'Data de instalação da Casa Legislativa'),
null=True,
blank=True
)
class Meta: class Meta:
ordering = ('nome',) ordering = ('nome',)
unique_together = ('municipio', 'tipo') verbose_name = _(u'Órgão')
verbose_name = 'Casa Legislativa' verbose_name_plural = _(u'Órgãos')
verbose_name_plural = 'Casas Legislativas'
def lista_gerentes(self, fmt='html'):
if not self.gerentes_interlegis.exists():
return ""
if fmt == 'html':
return u"<ul><li>"+u"</li><li>".join(
[g.nome_completo for g in self.gerentes_interlegis.all()])+\
u"</li></ul>"
else:
return u", ".join([g.nome_completo for g in
self.gerentes_interlegis.all()])
@property @property
def num_parlamentares(self): def num_parlamentares(self):
@ -156,7 +218,7 @@ class CasaLegislativa(models.Model):
if codigo == '': if codigo == '':
if self.tipo.sigla == 'AL': # Assembléias são tratadas a parte if self.tipo.sigla == 'AL': # Assembléias são tratadas a parte
codigo = 'A' + self.municipio.uf.sigla codigo = 'A' + self.municipio.uf.sigla
if CasaLegislativa.objects.filter(codigo_interlegis=codigo).count() <= 0: if Orgao.objects.filter(codigo_interlegis=codigo).count() <= 0:
# Só grava o código se ele for inédito # Só grava o código se ele for inédito
self.codigo_interlegis = codigo self.codigo_interlegis = codigo
self.save() self.save()
@ -189,7 +251,7 @@ class CasaLegislativa(models.Model):
cityName = cityName.replace(' ', '') cityName = cityName.replace(' ', '')
ultima = len(cityName) ultima = len(cityName)
while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ while Orgao.objects.filter(codigo_interlegis=codigo). \
count() > 0 and ultima > 0: count() > 0 and ultima > 0:
codigo = codigo[:2] + cityName[ultima - 1: ultima] codigo = codigo[:2] + cityName[ultima - 1: ultima]
ultima -= 1 ultima -= 1
@ -198,11 +260,11 @@ class CasaLegislativa(models.Model):
# não gerou um código único, então vamos compor o nome usando as # não gerou um código único, então vamos compor o nome usando as
# três primeiras consoantes. # três primeiras consoantes.
if CasaLegislativa.objects.filter(codigo_interlegis=codigo).count() > 0: if Orgao.objects.filter(codigo_interlegis=codigo).count() > 0:
codigo_cons = cityName.replace('A', '').replace('E', '').\ codigo_cons = cityName.replace('A', '').replace('E', '').\
replace('I', '').replace('O', '').replace('U', '')[:3] replace('I', '').replace('O', '').replace('U', '')[:3]
if len(codigo_cons) == 3 and \ if len(codigo_cons) == 3 and \
CasaLegislativa.objects.filter(codigo_interlegis=codigo).count() > 0: Orgao.objects.filter(codigo_interlegis=codigo).count() > 0:
codigo = codigo_cons codigo = codigo_cons
# Se ainda não gerou um nome único, vamos colocar dígitos no # Se ainda não gerou um nome único, vamos colocar dígitos no
@ -210,7 +272,7 @@ class CasaLegislativa(models.Model):
i = 'A' i = 'A'
while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ while Orgao.objects.filter(codigo_interlegis=codigo). \
count() > 0 and i <= 'Z': count() > 0 and i <= 'Z':
codigo = codigo[:2] + str(i) codigo = codigo[:2] + str(i)
i = chr(ord(i) + 1) i = chr(ord(i) + 1)
@ -221,7 +283,7 @@ class CasaLegislativa(models.Model):
i = 0 i = 0
while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ while Orgao.objects.filter(codigo_interlegis=codigo). \
count() > 0 and i < 100: count() > 0 and i < 100:
codigo = random.choice(cityName) + random.choice(cityName) + \ codigo = random.choice(cityName) + random.choice(cityName) + \
random.choice(cityName) random.choice(cityName)
@ -232,10 +294,8 @@ class CasaLegislativa(models.Model):
i = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' i = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ while Orgao.objects.filter(codigo_interlegis=codigo).count() > 0:
count() > 0: codigo = random.choice(i) + random.choice(i) + random.choice(i)
codigo = random.choice(i) + random.choice(i) + \
random.choice(i)
self.codigo_interlegis = codigo self.codigo_interlegis = codigo
self.save() self.save()
@ -245,11 +305,22 @@ class CasaLegislativa(models.Model):
def __unicode__(self): def __unicode__(self):
return self.nome return self.nome
def clean(self):
if (hasattr(self, 'tipo') and hasattr(self, 'municipio')
and self.tipo.legislativo):
if Orgao.objects.filter(
tipo=self.tipo,
municipio=self.municipio).exclude(pk=self.pk).exists():
raise ValidationError(
_(u"Já existe um(a) %(tipo)s em %(municipio)s"),
code='integrity',
params={'tipo': self.tipo, 'municipio': self.municipio})
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
address_changed = False address_changed = False
if self.pk is not None: if self.pk is not None:
original = CasaLegislativa.objects.get(pk=self.pk) original = Orgao.objects.get(pk=self.pk)
if (self.logradouro != original.logradouro or if (self.logradouro != original.logradouro or
self.bairro != original.bairro or self.bairro != original.bairro or
self.municipio != original.municipio or self.municipio != original.municipio or
@ -261,7 +332,7 @@ class CasaLegislativa(models.Model):
if address_changed: if address_changed:
self.ult_alt_endereco = datetime.now() self.ult_alt_endereco = datetime.now()
return super(CasaLegislativa, self).save(*args, **kwargs) return super(Orgao, self).save(*args, **kwargs)
class Funcionario(models.Model): class Funcionario(models.Model):
@ -271,40 +342,98 @@ class Funcionario(models.Model):
""" """
SETOR_CHOICES = [ SETOR_CHOICES = [
("presidente", "Presidente"), ("presidente", _(u"Presidente")),
("contato_interlegis", "Contato Interlegis"), ("contato_interlegis", _(u"Contato Interlegis")),
("infraestrutura_fisica", "Infraestrutura Física"), ("infraestrutura_fisica", _(u"Infraestrutura Física")),
("estrutura_de_ti", "Estrutura de TI"), ("estrutura_de_ti", _(u"Estrutura de TI")),
("organizacao_do_processo_legislativo", "Organização do Processo Legislativo"), ("organizacao_do_processo_legislativo",
("producao_legislativa", "Produção Legislativa"), _(u"Organização do Processo Legislativo")),
("estrutura_de_comunicacao_social", "Estrutura de Comunicação Social"), ("producao_legislativa", _(u"Produção Legislativa")),
("estrutura_de_recursos_humanos", "Estrutura de Recursos Humanos"), ("estrutura_de_comunicacao_social",
("gestao", "Gestão"), _(u"Estrutura de Comunicação Social")),
("outros", "Outros"), ("estrutura_de_recursos_humanos", _(u"Estrutura de Recursos Humanos")),
("gestao", _(u"Gestão")),
("outros", _(u"Outros")),
] ]
SEXO_CHOICES = [ SEXO_CHOICES = [
("M", "Masculino"), ("M", _(u"Masculino")),
("F", "Feminino") ("F", _(u"Feminino"))
] ]
casa_legislativa = models.ForeignKey(CasaLegislativa) casa_legislativa = models.ForeignKey(
nome = models.CharField('nome completo', max_length=60, blank=False) Orgao,
on_delete=models.CASCADE,
verbose_name=_(u"órgão"),
)
nome = models.CharField(_(u'nome completo'), max_length=60, blank=False)
# nome.alphabetic_filter = True # nome.alphabetic_filter = True
sexo = models.CharField(max_length=1, choices=SEXO_CHOICES, default="M") sexo = models.CharField(
nota = models.CharField(max_length=70, null=True, blank=True) _(u"Sexo"),
email = models.CharField('e-mail', max_length=75, blank=True) max_length=1,
telefones = generic.GenericRelation('contatos.Telefone') choices=SEXO_CHOICES,
endereco = generic.GenericRelation('contatos.Endereco') default="M"
cargo = models.CharField(max_length=100, null=True, blank=True) )
funcao = models.CharField(u'função', max_length=100, null=True, blank=True) data_nascimento = models.DateField(
setor = models.CharField(max_length=100, choices=SETOR_CHOICES, default="outros") _(u"Data de nascimento"),
tempo_de_servico = models.CharField(u'tempo de serviço', max_length=50, null=True, blank=True) blank=True,
ult_alteracao = models.DateTimeField(u'Última alteração', null=True, blank=True, editable=True, auto_now=True) null=True
)
nota = models.CharField(
_(u"Telefones"),
max_length=250,
null=True,
blank=True
)
email = models.CharField(_(u'e-mail'), max_length=250, blank=True)
# endereco = generic.GenericRelation('contatos.Endereco')
endereco = models.CharField(_(u'Endereço'), max_length=100, blank=True)
municipio = models.ForeignKey(
Municipio,
on_delete=models.SET_NULL,
verbose_name=_(u'Municipio'),
null=True,
blank=True,
)
bairro = models.CharField(_(u'Bairro'), max_length=100, blank=True)
cep = models.CharField(_(u'CEP'), max_length=10, blank=True)
redes_sociais = models.TextField(
_(u'Redes sociais'),
help_text=_(u'Colocar um por linha'),
blank=True
)
cargo = models.CharField(_(u"Cargo"), max_length=100, null=True, blank=True)
funcao = models.CharField(
_(u'função'),
max_length=100,
null=True,
blank=True
)
setor = models.CharField(
_(u"Setor"),
max_length=100,
choices=SETOR_CHOICES,
default="outros"
)
tempo_de_servico = models.CharField(
_(u'Tempo de serviço'),
max_length=50,
null=True,
blank=True
)
ult_alteracao = models.DateTimeField(
_(u'Última alteração'),
null=True,
blank=True,
editable=True,
auto_now=True
)
desativado = models.BooleanField(_(u"Desativado"), default=False)
observacoes = models.TextField(_(u"Observações"), blank=True)
class Meta: class Meta:
ordering = ('nome',) ordering = ('nome',)
verbose_name = 'contato da Casa Legislativa' verbose_name = _(u'contato da Casa Legislativa')
verbose_name_plural = 'contatos da Casa Legislativa' verbose_name_plural = _(u'contatos da Casa Legislativa')
def __unicode__(self): def __unicode__(self):
return self.nome return self.nome

406
sigi/apps/casas/reports.py

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.templatetags.static import static
from django.utils.translation import ugettext as _
from geraldo import Report, DetailBand, Label, ObjectValue, ReportGroup, ReportBand, landscape, SubReport, BAND_WIDTH, SystemField from geraldo import Report, DetailBand, Label, ObjectValue, ReportGroup, ReportBand, landscape, SubReport, BAND_WIDTH, SystemField
from geraldo.graphics import Image from geraldo.graphics import Image
from django.templatetags.static import static
from django.utils.translation import ugettext as _
from reportlab.lib.enums import TA_CENTER from reportlab.lib.enums import TA_CENTER
from reportlab.lib.pagesizes import A4 from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm from reportlab.lib.units import cm
@ -51,7 +52,7 @@ class CasasLegislativasLabels(Report):
Usage example:: Usage example::
>>> from geraldo.generators import PDFGenerator >>> from geraldo.generators import PDFGenerator
>>> queryset = CasaLegislativa.objects.filter(municipio__uf__sigla='MG') >>> queryset = Orgao.objects.filter(municipio__uf__sigla='MG')
>>> report = LabelsReport(queryset) >>> report = LabelsReport(queryset)
>>> report.generate_by(PDFGenerator, filename='./inline-detail-report.pdf') >>> report.generate_by(PDFGenerator, filename='./inline-detail-report.pdf')
@ -176,402 +177,3 @@ class CasasLegislativasLabelsSemPresidente(CasasLegislativasLabels):
display_inline=True, display_inline=True,
default_style={'fontName': 'Helvetica', 'fontSize': self.tamanho_fonte}) default_style={'fontName': 'Helvetica', 'fontSize': self.tamanho_fonte})
class CasasLegislativasReport(ReportDefault):
title = _(u'Relatório de Casas Legislativas')
height = 80 * cm
page_size = landscape(A4)
class band_page_header(ReportDefault.band_page_header):
label_top = ReportDefault.band_page_header.label_top
label_left = [0.3, 1, 5.5, 11, 17, 22]
elements = list(ReportDefault.band_page_header.elements)
elements = [
Image(filename=static('img/logo-interlegis.jpg'),
left=23.5 * cm, right=1 * cm, top=0.1 * cm, bottom=1 * cm,
width=4.2 * cm, height=3 * cm,
),
Image(filename=static('img/logo-senado.png'),
left=1 * cm, right=1 * cm, top=0.1 * cm, bottom=1 * cm,
width=3 * cm, height=3 * cm,
),
Label(text=_(u"SENADO FEDERAL"), top=1 * cm, left=0, width=BAND_WIDTH,
style={'fontName': 'Helvetica-Bold', 'fontSize': 14, 'alignment': TA_CENTER}
),
Label(text=_(u"SINTER - Secretaria Especial do Interlegis"), top=1.5 * cm, left=0, width=BAND_WIDTH,
style={'fontName': 'Helvetica-Bold', 'fontSize': 13, 'alignment': TA_CENTER}
),
SystemField(
expression='%(report_title)s', top=2.5 * cm, left=0, width=BAND_WIDTH,
style={'fontName': 'Helvetica-Bold', 'fontSize': 14, 'alignment': TA_CENTER}
),
Label(
text=_(u"UF"),
left=label_left[0] * cm,
top=label_top,
),
Label(
text=_(u"Municipio"),
left=label_left[1] * cm,
top=label_top,
),
Label(
text=_(u"Presidente"),
left=label_left[2] * cm,
top=label_top,
),
Label(
text=_(u"Endereço"),
left=label_left[3] * cm,
top=label_top,
),
Label(
text=_(u"Endereço na Internet"),
left=label_left[4] * cm,
top=label_top,
),
Label(
text=_(u"Email"),
left=label_left[5] * cm,
top=label_top,
),
]
class band_page_footer(ReportDefault.band_page_footer):
pass
class band_detail(ReportDefault.band_detail):
label_left = [0.3, 1, 5.5, 11, 17, 22]
elements = [
ObjectValue(
attribute_name='municipio.uf.sigla',
left=label_left[0] * cm,
width=1 * cm,
),
ObjectValue(
attribute_name='municipio.nome',
left=label_left[1] * cm,
),
ObjectValue(
attribute_name='presidente',
left=label_left[2] * cm,
),
ObjectValue(
attribute_name='logradouro',
left=label_left[3] * cm,
get_value=lambda instance: instance.logradouro + ' - ' + instance.bairro,
),
ObjectValue(
attribute_name='pagina_web',
left=label_left[4] * cm,
),
ObjectValue(
attribute_name='email',
left=label_left[5] * cm,
),
]
groups = [
ReportGroup(attribute_name='municipio.uf',
band_header=ReportBand(
height=0.7 * cm,
elements=[
ObjectValue(attribute_name='municipio.uf')
],
borders={'top': True},
)
)
]
class CasasSemConvenioReport(CasasLegislativasReport):
title = _(u'Relatório de Casas Legislativas sem Convênio')
class InfoCasaLegislativa(ReportDefault):
title = _(u'Casa Legislativa')
class band_summary(ReportBand):
pass
class band_page_footer(ReportBand):
height = 1 * cm
elements = [
SystemField(expression=_(u'%(now:%d/%m/%Y)s às %(now:%H:%M)s'), top=0.3 * cm),
]
class band_detail(ReportDefault.band_detail):
posicao_left = [
0, 1.3, # Tipo
0, 1.8, # Regiao
5.5, 6.8, # U.F.
0, 2.3, # Municipio
0, 2.4, # Endereco
0, 1.6, # Bairro
0, 1.3, # CEP
0, 1.6, # CNPJ
0, 2.3, # Telefone
0, 2.7, # Presidente
]
posicao_top = [
0.5, # Tipo
1.3, # Regiao
1.3, # U.F.
2.1, # Municipio
2.9, # Logradouro
3.7, # Bairro
4.5, # CEP
5.3, # CNPJ
6.1, # Telefone
6.9, # Presidente
]
height = 30 * cm
display_inline = True
default_style = {'fontName': 'Helvetica', 'fontSize': 14}
elements = [
Label(
text=label_text(_(u"Tipo")),
left=posicao_left[0] * cm,
top=posicao_top[0] * cm,
),
ObjectValue(
attribute_name='tipo.nome',
left=posicao_left[1] * cm,
top=posicao_top[0] * cm,
width=6 * cm,
),
Label(
text=label_text(_(u"Região")),
left=posicao_left[2] * cm,
top=posicao_top[1] * cm,
),
ObjectValue(
attribute_name='municipio.uf.regiao',
left=posicao_left[3] * cm,
top=posicao_top[1] * cm,
get_value=lambda instance:
{'SL': _(u'Sul'), 'SD': _(u'Sudeste'), 'CO': _(u'Centro-Oeste'), 'NE': _(u'Nordeste'), 'NO': _(u'Norte'), }
[instance.municipio.uf.regiao]
),
Label(
text=label_text(_(u"UF")),
left=posicao_left[4] * cm,
top=posicao_top[2] * cm,
),
ObjectValue(
attribute_name='municipio.uf',
left=posicao_left[5] * cm,
top=posicao_top[2] * cm,
),
Label(
text=label_text(_(u"Município")),
left=posicao_left[6] * cm,
top=posicao_top[3] * cm,
),
ObjectValue(
attribute_name='municipio.nome',
left=posicao_left[7] * cm,
top=posicao_top[3] * cm,
width=20 * cm,
),
# Linha 3
Label(
text=label_text(_(u"Endereço")),
left=posicao_left[8] * cm,
top=posicao_top[4] * cm,
),
ObjectValue(
attribute_name='logradouro',
left=posicao_left[9] * cm,
top=posicao_top[4] * cm,
width=20 * cm,
),
Label(
text=label_text(_(u"Bairro")),
left=posicao_left[10] * cm,
top=posicao_top[5] * cm,
),
ObjectValue(
attribute_name='bairro',
left=posicao_left[11] * cm,
top=posicao_top[5] * cm,
),
Label(
text=label_text(_(u"CEP")),
left=posicao_left[12] * cm,
top=posicao_top[6] * cm,
),
ObjectValue(
attribute_name='cep',
left=posicao_left[13] * cm,
top=posicao_top[6] * cm,
),
Label(
text=label_text(_(u"CNPJ")),
left=posicao_left[14] * cm,
top=posicao_top[7] * cm,
),
ObjectValue(
attribute_name='cnpj',
left=posicao_left[15] * cm,
top=posicao_top[7] * cm,
),
Label(
text=label_text(_(u"Telefone")),
left=posicao_left[16] * cm,
top=posicao_top[8] * cm,
),
ObjectValue(
attribute_name='telefone',
left=posicao_left[17] * cm,
top=posicao_top[8] * cm,
),
Label(
text=label_text(_(u"Presidente")),
left=posicao_left[18] * cm,
top=posicao_top[9] * cm,
),
ObjectValue(
attribute_name='presidente',
left=posicao_left[19] * cm,
top=posicao_top[9] * cm,
width=20 * cm,
),
]
# Telefones
tel_top = 2 * cm
tel_left = [0, 3, 5]
# Contato
cont_top = 2 * cm
cont_left = [0, 6, 9]
# Convenios
convenio_top = 2 * cm
convenio_left = [0, 1.8, 4.5, 8, 10.5, 13, 15.5, 18]
subreports = [
# Telefones
SubReport(
queryset_string='%(object)s.telefones.all()',
band_header=ReportBand(
default_style={'fontName': 'Helvetica', 'fontSize': 12},
height=2.5 * cm,
elements=[
Label(
text=_(u"Telefone(s)"),
style={'fontSize': 14, 'alignment': TA_CENTER},
width=BAND_WIDTH,
top=1 * cm,
),
Label(text=_(u"Número"), left=tel_left[0] * cm, top=tel_top),
Label(text=_(u"Tipo"), left=tel_left[1] * cm, top=tel_top),
Label(text=_(u"Nota"), left=tel_left[2] * cm, top=tel_top),
],
borders={'bottom': True},
),
band_detail=ReportBand(
default_style={'fontName': 'Helvetica', 'fontSize': 11},
height=0.5 * cm,
elements=[
ObjectValue(attribute_name='__unicode__', left=tel_left[0] * cm),
ObjectValue(attribute_name='tipo', left=tel_left[1] * cm,
get_value=lambda instance:
{'F': _(u'Fixo'), 'M': _(u'Móvel'), 'X': _(u'Fax'), 'I': _(u'Indefinido')}[instance.tipo],
),
ObjectValue(attribute_name='nota', left=tel_left[2] * cm),
],
#borders = {'all':True},
),
),
# Contatos
SubReport(
queryset_string='%(object)s.funcionario_set.all()',
band_header=ReportBand(
default_style={'fontName': 'Helvetica', 'fontSize': 12},
height=2.5 * cm,
elements=[
Label(
text=_(u"Contato(s)"),
style={'fontSize': 14, 'alignment': TA_CENTER},
width=BAND_WIDTH,
top=1 * cm,
),
Label(text=_(u"Nome"), left=cont_left[0] * cm, top=cont_top),
Label(text=_(u"Nota"), left=cont_left[1] * cm, top=cont_top),
Label(text=_(u"E-mail"), left=cont_left[2] * cm, top=cont_top),
],
borders={'bottom': True, 'top': True},
),
band_detail=ReportBand(
default_style={'fontName': 'Helvetica', 'fontSize': 11},
height=0.5 * cm,
elements=[
ObjectValue(attribute_name='nome', left=cont_left[0] * cm),
ObjectValue(attribute_name='nota', left=cont_left[1] * cm),
ObjectValue(attribute_name='email', left=cont_left[2] * cm),
],
#borders = {'all':True},
),
),
# Convenios
SubReport(
queryset_string='%(object)s.convenio_set.all()',
band_header=ReportBand(
default_style={'fontName': 'Helvetica', 'fontSize': 12},
height=2.5 * cm,
elements=[
Label(
text=_(u"Convênio(s)"),
style={'fontSize': 14, 'alignment': TA_CENTER},
width=BAND_WIDTH,
top=1 * cm,
),
Label(text=_(u"Projeto"), left=convenio_left[0] * cm, top=convenio_top),
Label(text=_(u"Nº Convenio"), left=convenio_left[1] * cm, top=convenio_top),
Label(text=_(u"Nº Processo SF"), left=convenio_left[2] * cm, top=convenio_top),
Label(text=_(u"Adesão"), left=convenio_left[3] * cm, top=convenio_top),
Label(text=_(u"Convênio"), left=convenio_left[4] * cm, top=convenio_top),
Label(text=_(u"Equipada"), left=convenio_left[5] * cm, top=convenio_top),
Label(text=_(u"Data D.O."), left=convenio_left[6] * cm, top=convenio_top),
],
borders={'bottom': True}
),
band_detail=ReportBand(
default_style={'fontName': 'Helvetica', 'fontSize': 11},
height=0.5 * cm,
elements=[
ObjectValue(attribute_name='projeto.sigla', left=convenio_left[0] * cm),
ObjectValue(attribute_name='num_convenio', left=convenio_left[1] * cm),
ObjectValue(attribute_name='num_processo_sf', left=convenio_left[2] * cm),
ObjectValue(attribute_name='data_adesao', left=convenio_left[3] * cm,
get_value=lambda instance:
instance.data_adesao.strftime('%d/%m/%Y') if instance.data_adesao is not None else '-'
),
ObjectValue(attribute_name='data_retorno_assinatura', left=convenio_left[4] * cm,
get_value=lambda instance:
instance.data_retorno_assinatura.strftime('%d/%m/%Y') if instance.data_retorno_assinatura is not None else '-'
),
ObjectValue(attribute_name='data_termo_aceite', left=convenio_left[5] * cm,
get_value=lambda instance:
instance.data_termo_aceite.strftime('%d/%m/%Y') if instance.data_termo_aceite is not None else '-'
),
ObjectValue(attribute_name='data_pub_diario', left=convenio_left[6] * cm,
get_value=lambda instance:
instance.data_pub_diario.strftime('%d/%m/%Y') if instance.data_pub_diario is not None else '-'
),
],
#borders = {'all':True},
),
)
]

6
sigi/apps/casas/templates/casas/ocorrencia_inline.html → sigi/apps/casas/templates/admin/casas/convenios_inline.html

@ -65,9 +65,9 @@
{% endif %} {% endif %}
</tr> </tr>
{% endfor %} {% endfor %}
<tr><td colspan="{{ inline_admin_formset.formset.fields|length }}"> <tr><td colspan="100">
<a href="/ocorrencias/ocorrencia/add/?casa_legislativa={{original.pk|safe}}"> <a href="{% url 'admin:convenios_convenio_add' %}?casa_legislativa={{original.pk|safe}}">
<span class="glyphicon glyphicon-plus"></span> Adicionar ocorrência <span class="glyphicon glyphicon-plus"></span>{% blocktrans with inline_admin_formset.opts.verbose_name|capfirst as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}
</a> </a>
</td></tr> </td></tr>
</tbody> </tbody>

164
sigi/apps/casas/templates/admin/casas/ocorrencia_inline.html

@ -0,0 +1,164 @@
{% load i18n admin_static admin_modify bootstrapped_goodies_tags %}
<div class="_inline-group" id="{{ inline_admin_formset.formset.prefix }}-group">
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
{{ inline_admin_formset.formset.management_form }}
<fieldset class="module">
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
{{ inline_admin_formset.formset.non_form_errors }}
<table class="table table-striped table-bordered">
<thead><tr>
{% for field in inline_admin_formset.fields %}
{% if not field.widget.is_hidden %}
<th{% if forloop.first %} colspan="2"{% endif %}{% if field.required %} class="required"{% endif %}>{{ field.label|capfirst }}
{% if field.help_text %}<i class="glyphicon glyphicon-comment help help-tooltip" style="margin-left: 4px;" alt="({{ field.help_text|striptags }})" title="{{ field.help_text|striptags }}"></i>{% endif %}
</th>
{% endif %}
{% endfor %}
{% if inline_admin_formset.formset.can_delete %}<th>{% trans "Delete?" %}</th>{% endif %}
</tr></thead>
<tbody>
{% for inline_admin_form in inline_admin_formset %}
{% if inline_admin_form.form.non_field_errors %}
<tr><td colspan="{{ inline_admin_form|cell_count }}">{{ inline_admin_form.form.non_field_errors }}</td></tr>
{% endif %}
<tr class="form-row {% cycle "row1" "row2" %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last %} empty-form{% endif %}"
id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
<td class="original">
{% if inline_admin_formset.opts.sortable_field_name %}
<span class="btn btn-default btn-xs drag-handler pull-left"><i class="glyphicon glyphicon-move"></i></span>
{% endif %}
{% if inline_admin_form.original or inline_admin_form.show_url %}<p>
{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
{% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
</p>{% endif %}
{% if inline_admin_form.has_auto_field or inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }}
{% spaceless %}
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if field.is_hidden %} {{ field.field }} {% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endspaceless %}
</td>
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
<td{% if field.field.name %} class="field-{{ field.field.name }}"{% endif %}>
{% if field.is_readonly %}
<p>{{ field.contents }}</p>
{% else %}
{% if field.errors %}
<div class="alert alert-danger">{{ field.errors|striptags }}</div>
{% endif %}
{% dab_field_rendering field.field %}
{% endif %}
</td>
{% endfor %}
{% endfor %}
{% endfor %}
{% if inline_admin_formset.formset.can_delete %}
<td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
{% endif %}
</tr>
{% endfor %}
<tr><td colspan="100">
<a href="{% url 'admin:ocorrencias_ocorrencia_add' %}?casa_legislativa={{original.pk|safe}}">
<span class="glyphicon glyphicon-plus"></span>{% blocktrans with inline_admin_formset.opts.verbose_name|capfirst as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}
</a>
</td></tr>
</tbody>
</table>
</fieldset>
</div>
</div>
<script type="text/javascript">
(function($) {
$(document).ready(function($) {
var rows = "#{{ inline_admin_formset.formset.prefix }}-group .tabular.inline-related tbody tr";
var alternatingRows = function(row) {
$(rows).not(".add-row").removeClass("row1 row2")
.filter(":even").addClass("row1").end()
.filter(rows + ":odd").addClass("row2");
}
var reinitDateTimeShortCuts = function() {
// Reinitialize the calendar and clock widgets by force
if (typeof DateTimeShortcuts != "undefined") {
$(".datetimeshortcuts").remove();
DateTimeShortcuts.init();
}
}
var updateSelectFilter = function() {
// If any SelectFilter widgets are a part of the new form,
// instantiate a new SelectFilter instance for it.
if (typeof SelectFilter != "undefined"){
$(".selectfilter").each(function(index, value){
var namearr = value.name.split('-');
SelectFilter.init(value.id, namearr[namearr.length-1], false, "{% static "admin/" %}");
});
$(".selectfilterstacked").each(function(index, value){
var namearr = value.name.split('-');
SelectFilter.init(value.id, namearr[namearr.length-1], true, "{% static "admin/" %}");
});
}
}
var initPrepopulatedFields = function(row) {
row.find('.prepopulated_field').each(function() {
var field = $(this);
var input = field.find('input, select, textarea');
var dependency_list = input.data('dependency_list') || [];
var dependencies = [];
$.each(dependency_list, function(i, field_name) {
dependencies.push('#' + row.find('.field-' + field_name).find('input, select, textarea').attr('id'));
});
if (dependencies.length) {
input.prepopulate(dependencies, input.attr('maxlength'));
}
});
}
$(rows).formset({
prefix: "{{ inline_admin_formset.formset.prefix }}",
addText: "{% blocktrans with verbose_name=inline_admin_formset.opts.verbose_name|title %}Add another {{ verbose_name }}{% endblocktrans %}",
formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}",
deleteCssClass: "inline-deletelink",
deleteText: "{% trans "Remove" %}",
emptyCssClass: "empty-form",
removed: alternatingRows,
added: (function(row) {
initPrepopulatedFields(row);
reinitDateTimeShortCuts();
updateSelectFilter();
alternatingRows(row);
})
});
});
})(django.jQuery);
// listener for jquery 1.7.2
(function($) {
{% if inline_admin_formset.opts.sortable_field_name %}
$('tbody').sortable({
// items: '.dynamic-{{ inline_admin_formset.formset.prefix }}',
handle: '.drag-handler',
items: ".form-row"
});
$("#{{ opts.model_name }}_form").submit(function(e) {
var sortable_field_name = "{{ inline_admin_formset.opts.sortable_field_name }}",
i = 0;
var initial_form_count = $('#id_{{ inline_admin_formset.formset.prefix }}-INITIAL_FORMS').val();
$('#{{ inline_admin_formset.formset.prefix }}-group table > tbody').find(".form-row").each(function(i, e) {
// make sure we don't assign a position unless extra has been moved
if ($(this).find("input[name$='" + sortable_field_name + "']").val() || (i <= initial_form_count - 1 )) {
$(this).find("input[name$='" + sortable_field_name + "']").val(i);
i++;
}
});
});
{% endif %}
})(jQuery);
</script>

6
sigi/apps/casas/templates/casas/carrinho.html

@ -186,6 +186,12 @@
value="Última alteração de endereco" class="action-select" checked="checked" /> value="Última alteração de endereco" class="action-select" checked="checked" />
<label>{% trans 'Data da última alteração de endereço' %}</label> <label>{% trans 'Data da última alteração de endereço' %}</label>
</li> </li>
<li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected"
value="Servicos SEIT" class="action-select" checked="checked" />
<label>{% trans 'Serviços SEIT' %}</label>
</li>
</ul> </ul>
</fieldset> </fieldset>

57
sigi/apps/casas/templates/casas/gerentes_interlegis.html

@ -0,0 +1,57 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
{% load static from staticfiles %}
{% block coltype %}colMS{% endblock %}
{% block content_title %}<h1>{% blocktrans %}Gerentes Interlegis{% endblocktrans %}</h1>{% endblock %}
{% block content %}
<div id="navbar-object-tools" class="nav">
<ul class="nav navbar-nav navbar-left">
<li><a href="?fmt=pdf">
<span class="glyphicon glyphicon-print"></span>
Relatório PDF
</a></li>
<li><a href="?fmt=csv&casas=yes">
<span class="glyphicon glyphicon-list-alt"></span>
CSV com casas
</a></li>
<li><a href="?fmt=csv&casas=no">
<span class="glyphicon glyphicon-list-alt"></span>
CSV sem casas
</a></li>
</ul>
</div>
<div id="content" class="colM">
{% for linha in gerentes %}
<div class="panel panel-primary">
<div class="panel-heading">
<p>{{ linha.gerente.nome_completo }} <span class="badge">{{ linha.gerente.casas_que_gerencia.count }}</span></p>
</div>
<div class="panel-body">
<ul class="nav nav-pills" role="tablist">
{% for uf in linha.ufs %}
<li role="presentation">
<a href="#tab{{ linha.gerente.id }}-{{ uf.0 }}" aria-controls="tab{{ linha.gerente.id }}-{{ uf.0 }}" role="tab" data-toggle="tab">{{ uf.1 }} <span class="badge">{{ uf.2|length }}</span></a>
</li>
{% endfor %}
</ul>
<div class="tab-content">
{% for uf in linha.ufs %}
<div role="tabpanel" class="tab-pane" id="tab{{ linha.gerente.id }}-{{ uf.0 }}">
<ul class="list-group list-inline">
{% for casa in uf.2 %}
<li class="list-group-item list-inline-item">
<a href="{% url 'admin:casas_orgao_change' casa.id %}" target="_blank">{{ casa }}</a></li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}

143
sigi/apps/casas/templates/casas/gerentes_interlegis_pdf.html

@ -0,0 +1,143 @@
{% load static from staticfiles %}
{% load i18n %}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Casa Legislativa</title>
<style type="text/css">
table {
padding: 3px;
line-height: 1em;
-fs-table-paginate: paginate;
}
thead {
display: table-header-group;
}
th {
font-weight: bold;
text-align: left;
}
th, td {
border-bottom: 1px solid #ddd;
vertical-align: top;
}
td.logo {
text-align: center;
}
td.header_text p {
margin: 0px;
font-size: 1.4em;
}
td.header_text {
width: 550px;
}
ul {
list-style-type: none;
padding-left: 15px;
}
li {
padding-left: 5px;
color: #999;
}
li.selected {
list-style-type: disc;
color: #000;
font-weight: bold;
}
p.strong {
margin-left: 25px;
line-height: 1em;
}
h1 {
font-size: 2em;
text-align: center;
}
h2 {
font-size: 1.7em;
}
h3 {
margin-top: 10px;
margin-bottom: 0px;
}
body {
font-family: "Helvetica, Arial, sans-serif";
font-size: 1.3em;
line-height: 1em;
}
div.new_page {
page-break-before: always;
}
div.same_page_ {
-pdf-keep-with-next: true;
}
.text-right {
text-align: right;
}
@page {
margin: 4cm 1cm 1cm 2cm;
font-family: "Helvetica, Arial, sans-serif";
font-size: 2em;
@frame header {
-pdf-frame-content: header;
top: 1cm;
}
@frame footer {
-pdf-frame-content: footer;
bottom: 0cm;
margin-left: 9cm;
margin-right: 9cm;
height: 1cm;
}
}
</style>
</head>
<body>
<div id="header">
<table>
<tr>
<td class="logo"><img src="{% static 'img/logo-senado.jpg' %}"/></td>
<td class="header_text">
<p><strong>{% trans 'SENADO FEDERAL' %}</strong></p>
<p><strong>{% trans 'ILB - Interlegis' %}</strong></p>
<p>{% trans 'Gerentes Interlegis' %}</p>
</td>
<td class="logo"><img src="{% static 'img/logo-interlegis.jpg' %}"/></td>
</tr>
</table>
</div>
<table>
<thead>
<tr>
<th>Gerente Interlegis</th>
<th>UF</th>
<th>Número de casas</th>
</tr>
</thead>
{% for linha in gerentes %}
{% for uf in linha.ufs %}
<tr>
{% if forloop.first %}
<td>{{ linha.gerente.nome_completo }}</td>
{% else %}
<td>&nbsp;</td>
{% endif %}
<td>{{ uf.1 }}</td>
<td class="text-right">{{ uf.2.count }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="2"><strong>Total de casas atendidas por {{ linha.gerente.nome_completo }}</strong></td>
<td class="text-right"><strong>{{ linha.gerente.casas_que_gerencia.count }}</strong></td>
</tr>
{% endfor %}
</table>
<div id="footer">
{%block page_foot%}
{% trans 'Página' %} <pdf:pagenumber>
{%endblock%}
</div>
</body>
</html>

81
sigi/apps/casas/templates/casas/importar.html

@ -0,0 +1,81 @@
{% extends "admin/base_site.html" %}
{% load i18n bootstrap3 %}
{% block content_title %}
<h1 class="pull-left">{% trans 'Importar dados para atualização de órgãos' %}</h1>
{% endblock %}
{% block content %}
{% if error %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endif %}
<div id="content-main">
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
{% bootstrap_form form %}
</div>
<input type="submit" value="Importar" class="btn btn-primary"/>
</form>
<div id="data-hints">
<h3>Padrões do arquivo:</h3>
<ul class="list-group">
<li class="list-group-item">O arquivo deve ter o formato de texto, no padrão CSV</li>
<li class="list-group-item">Deve-se usar pt-br.UTF-8 como codificação do arquivo</li>
<li class="list-group-item">A primeira linha do arquivo teve conter o cabeçalho das colunas, conforme explicado a seguir</li>
<li class="list-group-item">Cada linha subsequente deve referir-se a um e somente um órgão</li>
<li class="list-group-item">Campos deixados em branco serão ignorados</li>
</ul>
<hr/>
<h3>Colunas do arquivo:</h3>
<ul class="list-group">
<li class="list-group-item">O arquivo deve possuir no mínimo as colunas marcadas como obrigatórias.
A primeira linha deve conter os cabeçalhos, que devem ser grafados
EXATAMENTE como descrito na tabela abaixo (minúsculas, sem acentos, sem espaços).</li>
<li class="list-group-item">É desejável que as colunas estejam na mesma ordem definida aqui.</li>
<li class="list-group-item">Colunas adicionais podem estar presentes, e serão ignoradas</li>
</ul>
<table class="table table-striped table-condensed">
<thead class="thead-light">
<tr>
<th>Obrigatório</th>
<th>Título do campo</th>
<th>Conteúdo esperado</th>
</tr>
</thead>
<tbody>
<tr><th>*</th><th>tipo</th><td>Deve conter CM para Câmara Municipal ou AL para Assembleia Legislativa</td></tr>
<tr><th>*</th><th>municipio</th><td>O nome do município. Não use abreviações!!!</td></tr>
<tr><th>*</th><th>uf</th><td>A sigla da Unidade da Federação (Estado) em letras maiúsculas (ex: MG, SP, PA)</td></tr>
<tr><th></th><th>orgao_endereco</th><td>O novo endereço do órgão.</td></tr>
<tr><th></th><th>orgao_bairro</th><td>O novo bairro do órgão</td></tr>
<tr><th></th><th>orgao_cep</th><td>O novo CEP do órgão</td></tr>
<tr><th></th><th>orgao_email</th><td>O novo e-mail institucional do órgão</td></tr>
<tr><th></th><th>orgao_portal</th><td>O novo endereço do portal institucional do órgão</td></tr>
<tr><th></th><th>orgao_telefones</th><td>Os telefones do órgão. Pode conter quantos telefones forem necessários, separando-os por ';'. Use a formatação padrão de telefones, mas não use ';' entre os dígitos de um telefone, senão o sistema interpretará como dois telefones diferentes. </td></tr>
<tr><th></th><th>presidente_nome</th><td>O nome completo do presidente</td></tr>
<tr><th></th><th>presidente_data_nascimento</th><td>A data de nascimento do presidente no formato DD/MM/AAAA</td></tr>
<tr><th></th><th>presidente_telefones</th><td>Os telefones ou whatsapp do presidente. Pode conter quantos telefones forem necessários, separando-os por ';'. Use a formatação padrão de telefones, mas não use ';' entre os dígitos de um telefone, senão o sistema interpretará como dois telefones diferentes.</td></tr>
<tr><th></th><th>presidente_emails</th><td>Os e-mails do presidente. Pode conter quantos e-mails forem necessários. Utilize ';' para separar um e-mail do outro</td></tr>
<tr><th></th><th>presidente_endereco</th><td>O novo endereço do presidente</td></tr>
<tr><th></th><th>presidente_municipio</th><td>O nome do município onde mora o presidente</td></tr>
<tr><th></th><th>presidente_bairro</th><td>O nome do bairro onde mora o presidente</td></tr>
<tr><th></th><th>presidente_cep</th><td>O novo CEP do presidente</td></tr>
<tr><th></th><th>presidente_redes_sociais</th><td>As redes sociais do presidente. Pode conter quantas redes sociais forem necessárias. Utilize espaço para separar uma rede da outra.</td></tr>
<tr><th></th><th>contato_nome</th><td>O nome completo do contato</td></tr>
<tr><th></th><th>contato_data_nascimento</th><td>A data de nascimento do contato no formato DD/MM/AAAA</td></tr>
<tr><th></th><th>contato_telefones</th><td>Os telefones ou whatsapp do contato. Pode conter quantos telefones forem necessários, separando-os por ';'. Use a formatação padrão de telefones, mas não use ';' entre os dígitos de um telefone, senão o sistema interpretará como dois telefones diferentes.</td></tr>
<tr><th></th><th>contato_emails</th><td>Os e-mails do contato. Pode conter quantos e-mails forem necessários. Utilize ';' para separar um e-mail do outro</td></tr>
<tr><th></th><th>contato_endereco</th><td>O novo endereço do contato</td></tr>
<tr><th></th><th>contato_municipio</th><td>O nome do município onde mora o contato</td></tr>
<tr><th></th><th>contato_bairro</th><td>O nome do bairro onde mora o contato</td></tr>
<tr><th></th><th>contato_cep</th><td>O novo CEP do contato</td></tr>
<tr><th></th><th>contato_redes_sociais</th><td>As redes sociais do contato. Pode conter quantas redes sociais forem necessárias. Utilize espaço para separar uma rede da outra.</td></tr>
<tbody>
</table>
</div>
</div>
{% endblock %}

18
sigi/apps/casas/templates/casas/importar_result.html

@ -0,0 +1,18 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block content_title %}
<h1 class="pull-left">Importação de órgãos concluída com {% if com_erros %}erros{% else %}sucesso!{% endif %}</h1>
{% endblock %}
{% block content %}
<div id="content-main">
<p>{{ total }} registros importados do arquivo {{ file_name }}</p>
{% if com_erros %}
<p>{{ com_erros }} registros apresentaram erros</p>
<p><a href="{{ MEDIA_URL }}temp/{{ result_file }}">Download do arquivo de erros</a></p>
{% endif %}
<p><a href="{% url 'importar-casas' %}">Importar outro arquivo</a></p>
</div>
{% endblock %}

10
sigi/apps/casas/templates/casas/lista_casas_carteira_snippet.html

@ -31,26 +31,26 @@
<li role="presentation" {% if regiao == k %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&r={{ k }}">{{ l }}</a></li> <li role="presentation" {% if regiao == k %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&r={{ k }}">{{ l }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<ul class="nav nav-pills"> <ul class="nav nav-pills">
{% for u in ufs %} {% for u in ufs %}
<li role="presentation" {% if u.pk == uf.pk %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&uf={{ u.sigla }}" autocomplete="off">{{ u.nome }}</a></li> <li role="presentation" {% if u.pk == uf.pk %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&uf={{ u.sigla }}" autocomplete="off">{{ u.nome }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<ul class="nav nav-pills"> <ul class="nav nav-pills">
{% for m in uf.mesorregiao_set.all %} {% for m in uf.mesorregiao_set.all %}
<li role="presentation" {% if m.pk == meso.pk %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&meso={{ m.pk|safe }}" autocomplete="off">{{ m.nome }}</a></li> <li role="presentation" {% if m.pk == meso.pk %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&meso={{ m.pk|safe }}" autocomplete="off">{{ m.nome }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<ul class="nav nav-pills"> <ul class="nav nav-pills">
{% for m in meso.microrregiao_set.all %} {% for m in meso.microrregiao_set.all %}
<li role="presentation" {% if m.pk == micro.pk %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&micro={{ m.pk|safe }}" autocomplete="off">{{ m.nome }}</a></li> <li role="presentation" {% if m.pk == micro.pk %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&micro={{ m.pk|safe }}" autocomplete="off">{{ m.nome }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
{% if page_obj %} {% if page_obj %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-striped"> <table class="table table-striped">
@ -64,7 +64,7 @@
</tr> </tr>
{% for casa in page_obj.object_list %} {% for casa in page_obj.object_list %}
<tr> <tr>
<td><a href="{% url 'admin:casas_casalegislativa_change' casa.pk %}">{{ casa.nome }}</a></td> <td><a href="{% url 'admin:casas_orgao_change' casa.pk %}">{{ casa.nome }}</a></td>
<td>{{ casa.municipio.uf.get_regiao_display }}</td> <td>{{ casa.municipio.uf.get_regiao_display }}</td>
<td>{{ casa.municipio.uf }}</td> <td>{{ casa.municipio.uf }}</td>
<td>{{ casa.municipio.microrregiao.mesorregiao }}</td> <td>{{ casa.municipio.microrregiao.mesorregiao }}</td>

46
sigi/apps/casas/templates/casas/portfolio.html

@ -5,6 +5,32 @@
{% block extrastyle %} {% block extrastyle %}
<style type="text/css"> <style type="text/css">
/* Tooltip container */
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
}
/* Tooltip text */
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
padding: 5px 0;
border-radius: 6px;
/* Position the tooltip text - see examples below! */
position: absolute;
z-index: 1;
}
/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
visibility: visible;
}
</style> </style>
{{ block.super }} {{ block.super }}
{% endblock %} {% endblock %}
@ -22,10 +48,18 @@
<div class="alert alert-danger">{{ e }}</div> <div class="alert alert-danger">{{ e }}</div>
{% endfor %} {% endfor %}
<div class="nav">
<ul class="object-tools pull-left nav nav-pills">
{% for t in tipos_casas %}
<li{% if tipo == t.sigla %} class="active"{% endif %}><a href="?tipo={{ t.sigla }}" data-toggle="tooltip" title="{{ t.nome }}">{{ t.sigla }}</a></li>
{% endfor %}
</ul>
</div>
<div class="nav"> <div class="nav">
<ul class="object-tools pull-left nav nav-pills"> <ul class="object-tools pull-left nav nav-pills">
{% for key, value in regioes %} {% for key, value in regioes %}
<li{% if regiao == key %} class="active"{% endif %}><a href="?regiao={{ key }}">{{ value }}</a></li> <li{% if regiao == key %} class="active"{% endif %}><a href="?regiao={{ key }}{% if tipo %}&tipo={{ tipo|safe }}{% endif %}">{{ value }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
@ -34,7 +68,7 @@
<div class="nav"> <div class="nav">
<ul class="object-tools pull-left nav nav-tabs"> <ul class="object-tools pull-left nav nav-tabs">
{% for uf in ufs %} {% for uf in ufs %}
<li{% if uf_id == uf.pk %} class="active"{% endif %}><a href="?uf={{ uf.pk|safe }}">{{ uf.nome }}</a></li> <li{% if uf_id == uf.pk %} class="active"{% endif %}><a href="?uf={{ uf.pk|safe }}{% if tipo %}&tipo={{ tipo|safe }}{% endif %}">{{ uf.nome }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
@ -44,7 +78,7 @@
<div class="nav"> <div class="nav">
<ul class="object-tools pull-left nav nav-pills"> <ul class="object-tools pull-left nav nav-pills">
{% for meso in mesorregioes %} {% for meso in mesorregioes %}
<li{% if meso_id == meso.pk %} class="active"{% endif %}><a href="?meso={{ meso.pk|safe }}">{{ meso.nome }}</a></li> <li{% if meso_id == meso.pk %} class="active"{% endif %}><a href="?meso={{ meso.pk|safe }}{% if tipo %}&tipo={{ tipo|safe }}{% endif %}">{{ meso.nome }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
@ -54,7 +88,7 @@
<div class="nav"> <div class="nav">
<ul class="object-tools pull-left nav nav-pills"> <ul class="object-tools pull-left nav nav-pills">
{% for micro in microrregioes %} {% for micro in microrregioes %}
<li{% if micro_id == micro.pk %} class="active"{% endif %}><a href="?micro={{ micro.pk|safe }}">{{ micro.nome }}</a></li> <li{% if micro_id == micro.pk %} class="active"{% endif %}><a href="?micro={{ micro.pk|safe }}{% if tipo %}&tipo={{ tipo|safe }}{% endif %}">{{ micro.nome }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
@ -64,7 +98,7 @@
<form action="" method="post" id="atribui_gerente_form"> <form action="" method="post" id="atribui_gerente_form">
{% csrf_token %} {% csrf_token %}
{{ form }} {{ form }}
<input type="submit" name="_save" value="Atribuir" class="btn btn-default" /> <input type="submit" name="_save" class="btn btn-default"/>
</form> </form>
{% endif %} {% endif %}
@ -85,7 +119,7 @@
<td>{{ casa.municipio.uf }}</td> <td>{{ casa.municipio.uf }}</td>
<td>{{ casa.municipio.microrregiao.mesorregiao }}</td> <td>{{ casa.municipio.microrregiao.mesorregiao }}</td>
<td>{{ casa.municipio.microrregiao.nome }}</td> <td>{{ casa.municipio.microrregiao.nome }}</td>
<td>{{ casa.gerente_contas }}</td> <td>{{ casa.lista_gerentes|safe }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

237
sigi/apps/casas/templates/casas/report_complete_pdf.html

@ -0,0 +1,237 @@
{% load smart_if %}
{% load static from staticfiles %}
{% load i18n %}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Casa Legislativa</title>
<style type="text/css">
table {
padding: 3px;
line-height: 1em;
-fs-table-paginate: paginate;
}
thead {
display: table-header-group;
}
th {
font-weight: bold;
text-align: left;
}
th, td {
border-bottom: 1px solid #ddd;
}
.identificacao th {
width: 20%;
}
div#capa h3 {
text-align: center;
margin-top: 5px;
margin-bottom: 0px;
}
div#capa p {
text-align: center;
}
td.logo {
text-align: center;
}
td.header_text p {
margin: 0px;
font-size: 1.4em;
}
td.header_text {
width: 550px;
}
ul {
list-style-type: none;
padding-left: 15px;
}
li {
padding-left: 5px;
color: #999;
}
li.selected {
list-style-type: disc;
color: #000;
font-weight: bold;
}
p.strong {
margin-left: 25px;
line-height: 1em;
}
h1 {
font-size: 2em;
text-align: center;
}
h2 {
font-size: 1.7em;
}
h3 {
margin-top: 10px;
margin-bottom: 0px;
}
body {
font-family: "Helvetica, Arial, sans-serif";
font-size: 1.3em;
line-height: 1em;
}
div.new_page {
page-break-before: always;
}
div.same_page_ {
-pdf-keep-with-next: true;
}
@page {
size: {{ pagesize }};
margin: 4cm 1cm 1cm 2cm;
font-family: "Helvetica, Arial, sans-serif";
font-size: 2em;
@frame header {
-pdf-frame-content: header;
top: 1cm;
}
@frame footer {
-pdf-frame-content: footer;
bottom: 0cm;
margin-left: 9cm;
margin-right: 9cm;
height: 1cm;
}
}
</style>
</head>
<body>
<div id="header">
<table>
<tr>
<td class="logo"><img src="{% static 'img/logo-senado.jpg' %}"/></td>
<td class="header_text">
<p><strong>{% trans 'SENADO FEDERAL' %}</strong></p>
<p><strong>{% trans 'ILB - Interlegis' %}</strong></p>
<p>{% trans 'Relatório completo' %}</p>
</td>
<td class="logo"><img src="{% static 'img/logo-interlegis.jpg' %}"/></td>
</tr>
</table>
</div>
{% for casa in casas %}
<div class="{% if forloop.first %}{% else %}new_page{% endif %}">
<h2>{{ casa.nome }}</h2>
<table class="identificacao">
<tr><th>{% trans 'Presidente:' %}</th><td>{{ casa.presidente }}</td></tr>
<tr><th>{% trans 'Tipo:' %}</th><td>{{ casa.tipo.nome }}</td></tr>
<tr><th>{% trans 'Estado / região:' %}</th><td>{{ casa.municipio.uf.nome }} / {{ casa.municipio.uf.get_regiao_display }}</td></tr>
<tr><th>{% trans 'Município:' %}</th><td>{{ casa.municipio.nome }}</td></tr>
<tr><th>{% trans 'Endereço:' %}</th><td>{{ casa.logradouro }}</td></tr>
<tr><th>{% trans 'Bairro:' %}</th><td>{{ casa.bairro }}</td></tr>
<tr><th>{% trans 'CEP:' %}</th><td>{{ casa.cep }}</td></tr>
<tr><th>{% trans 'CNPJ:' %}</th><td>{{ casa.cnpj }}</td></tr>
<tr><th>{% trans 'Telefone:' %}</th><td>{{ casa.telefone }}</td></tr>
<tr><th>{% trans 'E-mail:' %}</th><td>{{ casa.email }}</td></tr>
</table>
<h3>Telefones</h3>
<table repeat="1">
<thead>
<tr>
<th>Número</th>
<th>Tipo</th>
<th>Nota</th>
</tr>
<thead>
{% for tel in casa.telefones.all %}
<tr>
<td>{{ tel.numero }}</td>
<td>{{ tel.get_tipo_display }}</td>
<td>{{ tel.nota }}</td>
</tr>
{% endfor %}
</table>
<h3>Pessoas de contato</h3>
<table repeat="1">
<thead>
<tr>
<th>Nome</th>
<th>E-mail</th>
<th>Setor</th>
<th>Notas</th>
</tr>
</thead>
{% for func in casa.funcionario_set.all %}
<tr>
<td>{{ func.nome }}</td>
<td>{{ func.email }}</td>
<td>{{ func.get_setor_display }}</td>
<td>{{ func.nota }}</td>
</tr>
{% endfor %}
</table>
<h3>Convênios</h3>
<table repeat="1">
<thead>
<tr>
<th>Projeto</th>
<th>Nº convênio</th>
<th>Nº processo SF</th>
<th>Adesão</th>
<th>Convênio</th>
<th>Equipada</th>
<th>Publicada</th>
</tr>
</thead>
{% for conv in casa.convenio_set.all %}
<tr>
<td>{{ conv.projeto.nome }}</td>
<td>{{ conv.num_convenio|default_if_none:"-" }}</td>
<td>{{ conv.num_processo_sf|default_if_none:"-" }}</td>
<td>{{ conv.data_adesao|date:"SHORT_DATE_FORMAT" }}</td>
<td>{{ conv.data_retorno_assinatura|date:"SHORT_DATE_FORMAT" }}</td>
<td>{{ conv.equipada|yesno }}</td>
<td>{{ conv.data_pub_diario|date:"SHORT_DATE_FORMAT" }}</td>
</tr>
{% endfor %}
</table>
<h3>Serviços Interlegis</h3>
<table repeat="1">
<thead>
<tr>
<th>Serviço</th>
<th>Endereço</th>
<th>Ativado em</th>
<th>Desativado em</th>
</tr>
</thead>
{% for srv in casa.servico_set.all %}
<tr>
<td>{{ srv.tipo_servico.nome }}</td>
<td>{{ srv.url|default_if_none:"-" }}</td>
<td>{{ srv.data_ativacao|date:"SHORT_DATE_FORMAT" }}</td>
<td>{{ srv.data_desativacao|date:"SHORT_DATE_FORMAT" }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endfor %}
<div id="footer">
{%block page_foot%}
{% trans 'Página' %} <pdf:pagenumber>
{%endblock%}
</div>
</body>
</html>

132
sigi/apps/casas/templates/casas/report_pdf.html

@ -0,0 +1,132 @@
{% load smart_if %}
{% load static from staticfiles %}
{% load i18n %}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Casa Legislativa</title>
<style type="text/css">
table {
padding: 3px;
line-height: 1em;
-fs-table-paginate: paginate;
}
thead {
display: table-header-group;
}
th {
font-weight: bold;
text-align: left;
}
th, td {
border-bottom: 1px solid #ddd;
}
td.logo {
text-align: center;
}
td.header_text p {
margin: 0px;
font-size: 1.4em;
}
td.header_text {
width: 550px;
}
h1 {
font-size: 2em;
text-align: center;
}
h2 {
font-size: 1.7em;
}
h3 {
margin-top: 10px;
margin-bottom: 0px;
}
body {
font-family: "Helvetica, Arial, sans-serif";
font-size: 1.3em;
line-height: 1em;
}
#footer {
text-align: center;
}
@page {
size: a4 landscape;
margin: 3.5cm 2cm 2cm 2cm;
font-family: "Helvetica, Arial, sans-serif";
font-size: 2em;
@frame header {
-pdf-frame-content: header;
top: 1cm;
}
@frame footer {
-pdf-frame-content: footer;
bottom: 0cm;
margin-left: 2cm;
margin-right: 2cm;
height: 1cm;
}
}
</style>
</head>
<body>
<div id="header">
<table>
<tr>
<td class="logo"><img src="{% static 'img/logo-senado.jpg' %}"/></td>
<td class="header_text">
<p><strong>{% trans 'SENADO FEDERAL' %}</strong></p>
<p><strong>{% trans 'ILB - Interlegis' %}</strong></p>
<p>{{ title }}</p>
</td>
<td class="logo"><img src="{% static 'img/logo-interlegis.jpg' %}"/></td>
</tr>
</table>
</div>
<table repeat="1">
<thead>
<tr>
<th style="width: 22.5%;">{% trans 'Casa' %}</th>
<th style="width: 12.5%;">{% trans 'Presidente' %}</th>
<th style="width: 5%;">{% trans 'Tipo' %}</th>
<th style="width: 18%;">{% trans 'Endereço' %}</th>
<th style="width: 10%;">{% trans 'Bairro' %}</th>
<th style="width: 7%;">{% trans 'CEP' %}</th>
<th style="width: 12.5%;">{% trans 'Telefone' %}</th>
<th style="width: 12.5%;">{% trans 'E-mail' %}</th>
</tr>
</thead>
{% for casa in casas %}
{% ifchanged casa.municipio.uf %}
<tr><td colspan="8"><h3>{{ casa.municipio.uf.nome }}</h3></td></tr>
{% endifchanged %}
<tr>
<td>{{ casa.nome }}</td>
<td>{{ casa.presidente }}</td>
<td>{{ casa.tipo.sigla }}</td>
<td>{{ casa.logradouro }}</td>
<td>{{ casa.bairro }}</td>
<td>{{ casa.cep }}</td>
<td>{{ casa.telefone }}</td>
<td>{{ casa.email }}</td>
</tr>
{% endfor %}
</table>
<div id="footer">
{%block page_foot%}
{% trans 'Página' %} <pdf:pagenumber>
{%endblock%}
</div>
</body>
</html>

4
sigi/apps/casas/test_casas.py

@ -1,7 +1,7 @@
import pytest import pytest
from django_dynamic_fixture import G from django_dynamic_fixture import G
from sigi.apps.casas.models import CasaLegislativa from sigi.apps.casas.models import Orgao
@pytest.fixture @pytest.fixture
@ -14,4 +14,4 @@ def some_parliaments():
def parliaments_from_names(names): def parliaments_from_names(names):
return [G(CasaLegislativa, nome=name, foto=None, gerente_contas=None,) for name in names] return [G(Orgao, nome=name, foto=None,) for name in names]

47
sigi/apps/casas/urls.py

@ -1,38 +1,57 @@
# coding: utf-8 # coding: utf-8
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from django.contrib.auth.decorators import login_required
from sigi.apps.casas.views import importa_casas
urlpatterns = patterns( urlpatterns = patterns(
'sigi.apps.casas.views', 'sigi.apps.casas.views',
# Informacoes de uma casa legislativa # Informacoes de uma casa legislativa
url(r'^casalegislativa/report_complete/$', 'report_complete', name='report-complete-all'), url(r'^orgao/report_complete/$', 'report_complete',
url(r'^casalegislativa/(?P<id>\w+)/report_complete/$', 'report_complete', name='report-complete-id'), name='report-complete-all'),
url(r'^orgao/(?P<id>\w+)/report_complete/$', 'report_complete',
name='report-complete-id'),
# Reports Labels # Reports Labels
url(r'^casalegislativa/labels/$', 'labels_report', name='labels-report-all'), url(r'^orgao/labels/$', 'labels_report', name='labels-report-all'),
url(r'^casalegislativa/(?P<id>\w+)/labels/$', 'labels_report', name='labels-report-id'), url(r'^orgao/(?P<id>\w+)/labels/$', 'labels_report',
name='labels-report-id'),
# Reports Labels Parlamentar # Reports Labels Parlamentar
url(r'^casalegislativa/labels_parlamentar/$', 'labels_report_parlamentar', name='lebels-report-parlamentar-all'), url(r'^orgao/labels_parlamentar/$', 'labels_report_parlamentar',
url(r'^casalegislativa/(?P<id>\w+)/labels_parlamentar/$', 'labels_report_parlamentar', name='labels-report-parlamentar-id'), name='lebels-report-parlamentar-all'),
url(r'^orgao/(?P<id>\w+)/labels_parlamentar/$', 'labels_report_parlamentar',
name='labels-report-parlamentar-id'),
# Reports labels sem presidente # Reports labels sem presidente
url(r'^casalegislativa/labels_sem_presidente/$', 'labels_report_sem_presidente', name='labels-report-sem-presidente-all'), url(r'^orgao/labels_sem_presidente/$', 'labels_report_sem_presidente',
url(r'^casalegislativa/(?P<id>\w+)/labels_sem_presidente/$', 'labels_report_sem_presidente', name='labels-report-sem-presidente-id'), name='labels-report-sem-presidente-all'),
url(r'^orgao/(?P<id>\w+)/labels_sem_presidente/$',
'labels_report_sem_presidente', name='labels-report-sem-presidente-id'),
# Reports casas sem convenio # Reports casas sem convenio
url(r'^casalegislativa/reports/$', 'report', name='casa-report'), url(r'^orgao/reports/$', 'report', name='casa-report'),
url(r'^casalegislativa/casas_sem_convenio_report/$', 'casas_sem_convenio_report', name='casas-sem-convenio-report'), url(r'^orgao/casas_sem_convenio_report/$', 'casas_sem_convenio_report',
name='casas-sem-convenio-report'),
# CSV # CSV
url(r'^casalegislativa/csv/$', 'export_csv', name='casa-export-csv'), # Error url(r'^orgao/csv/$', 'export_csv', name='casa-export-csv'), # Error
# Carrinho # Carrinho
url(r'^casalegislativa/carrinho/$', 'visualizar_carrinho', name='visualizar-carrinho'), url(r'^orgao/carrinho/$', 'visualizar_carrinho',
url(r'^casalegislativa/carrinho/excluir_carrinho/$', 'excluir_carrinho', name='excluir-carrinho'), # Error name='visualizar-carrinho'),
url(r'^casalegislativa/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho', name='deleta-itens-carrinho'), # Error url(r'^orgao/carrinho/excluir_carrinho/$', 'excluir_carrinho',
name='excluir-carrinho'), # Error
url(r'^orgao/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho',
name='deleta-itens-carrinho'), # Error
url(r'^portfolio/$', 'portfolio', name='casas-portfolio'), url(r'^portfolio/$', 'portfolio', name='casas-portfolio'),
url(r'^carteira/$', 'painel_relacionamento', name='casas-carteira'), url(r'^carteira/$', 'painel_relacionamento', name='casas-carteira'),
# Atualização por CSV
url(r'^orgao/importa/$', login_required(importa_casas.as_view()),
name='importar-casas'),
url(r'^gerentes/$', 'gerentes_interlegis',
name='gerentes_interlegis'),
) )

694
sigi/apps/casas/views.py

File diff suppressed because it is too large

39
sigi/apps/contatos/migrations/0003_auto_20210416_0841.py

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('contatos', '0002_auto_20151104_0810'),
]
operations = [
migrations.AlterField(
model_name='contato',
name='municipio',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='munic\xedpio', blank=True, to='contatos.Municipio', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='endereco',
name='municipio',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='munic\xedpio', blank=True, to='contatos.Municipio', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='municipio',
name='microrregiao',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Microrregi\xe3o', blank=True, to='contatos.Microrregiao', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='municipio',
name='uf',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='UF', to='contatos.UnidadeFederativa'),
preserve_default=True,
),
]

24
sigi/apps/contatos/migrations/0004_auto_20210611_0946.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('contatos', '0003_auto_20210416_0841'),
]
operations = [
migrations.AlterModelOptions(
name='microrregiao',
options={'ordering': ('nome',), 'verbose_name': 'Microrregi\xe3o', 'verbose_name_plural': 'Microrregi\xf5es'},
),
migrations.AlterField(
model_name='unidadefederativa',
name='regiao',
field=models.CharField(max_length=2, verbose_name='regi\xe3o', choices=[(b'CO', 'Centro-Oeste'), (b'NE', 'Nordeste'), (b'NO', 'Norte'), (b'SD', 'Sudeste'), (b'SL', 'Sul')]),
preserve_default=True,
),
]

58
sigi/apps/contatos/models.py

@ -13,11 +13,11 @@ class UnidadeFederativa(models.Model):
""" Modelo que representa um estado brasileiro """ Modelo que representa um estado brasileiro
""" """
REGIAO_CHOICES = ( REGIAO_CHOICES = (
('SL', _(u'Sul')),
('SD', _(u'Sudeste')),
('CO', _(u'Centro-Oeste')), ('CO', _(u'Centro-Oeste')),
('NE', _(u'Nordeste')), ('NE', _(u'Nordeste')),
('NO', _(u'Norte')), ('NO', _(u'Norte')),
('SD', _(u'Sudeste')),
('SL', _(u'Sul')),
) )
codigo_ibge = models.PositiveIntegerField( codigo_ibge = models.PositiveIntegerField(
u'código IBGE', u'código IBGE',
@ -51,7 +51,11 @@ class Mesorregiao(models.Model):
unique=True, unique=True,
help_text=_(u'Código da mesorregião segundo o IBGE') help_text=_(u'Código da mesorregião segundo o IBGE')
) )
uf = models.ForeignKey(UnidadeFederativa, verbose_name=_(u'UF')) uf = models.ForeignKey(
UnidadeFederativa,
on_delete=models.CASCADE,
verbose_name=_(u'UF')
)
nome = models.CharField(_(u"Nome mesorregião"), max_length=100) nome = models.CharField(_(u"Nome mesorregião"), max_length=100)
# Campo de busca em caixa baixa sem acento # Campo de busca em caixa baixa sem acento
search_text = SearchField(field_names=['nome']) search_text = SearchField(field_names=['nome'])
@ -62,7 +66,7 @@ class Mesorregiao(models.Model):
def __unicode__(self): def __unicode__(self):
return self.nome return self.nome
class Microrregiao(models.Model): class Microrregiao(models.Model):
codigo_ibge = models.PositiveIntegerField( codigo_ibge = models.PositiveIntegerField(
_(u'Código IBGE'), _(u'Código IBGE'),
@ -70,13 +74,16 @@ class Microrregiao(models.Model):
unique=True, unique=True,
help_text=_(u'Código da microrregião segundo o IBGE') help_text=_(u'Código da microrregião segundo o IBGE')
) )
mesorregiao = models.ForeignKey(Mesorregiao) mesorregiao = models.ForeignKey(
Mesorregiao,
on_delete=models.CASCADE
)
nome = models.CharField(_(u"Nome microrregião"), max_length=100) nome = models.CharField(_(u"Nome microrregião"), max_length=100)
# Campo de busca em caixa baixa sem acento # Campo de busca em caixa baixa sem acento
search_text = SearchField(field_names=['nome']) search_text = SearchField(field_names=['nome'])
class Meta: class Meta:
ordering = ('mesorregiao', 'nome') ordering = ('nome',)
verbose_name, verbose_name_plural = _(u'Microrregião'), _(u'Microrregiões') verbose_name, verbose_name_plural = _(u'Microrregião'), _(u'Microrregiões')
def __unicode__(self): def __unicode__(self):
@ -92,8 +99,14 @@ class Municipio(models.Model):
unique=True, unique=True,
help_text=_(u'Código do município segundo IBGE.') help_text=_(u'Código do município segundo IBGE.')
) )
microrregiao = models.ForeignKey(Microrregiao, verbose_name=_(u'Microrregião'), blank=True, null=True) microrregiao = models.ForeignKey(
Microrregiao,
on_delete=models.PROTECT,
verbose_name=_(u'Microrregião'),
blank=True,
null=True
)
# codio designado pelo Tribunal Superior Eleitoral # codio designado pelo Tribunal Superior Eleitoral
codigo_tse = models.PositiveIntegerField( codigo_tse = models.PositiveIntegerField(
@ -104,7 +117,11 @@ class Municipio(models.Model):
) )
nome = models.CharField(max_length=50) nome = models.CharField(max_length=50)
search_text = SearchField(field_names=[_(u'nome'), _(u'uf')]) search_text = SearchField(field_names=[_(u'nome'), _(u'uf')])
uf = models.ForeignKey(UnidadeFederativa, verbose_name=_(u'UF')) uf = models.ForeignKey(
UnidadeFederativa,
on_delete=models.PROTECT,
verbose_name=_(u'UF')
)
# verdadeiro se o município é capital do estado # verdadeiro se o município é capital do estado
is_capital = models.BooleanField(_(u'capital'), default=False) is_capital = models.BooleanField(_(u'capital'), default=False)
populacao = models.PositiveIntegerField(_(u'população')) populacao = models.PositiveIntegerField(_(u'população'))
@ -173,10 +190,13 @@ class Telefone(models.Model):
ult_alteracao = models.DateTimeField(_(u'Última alteração'), null=True, blank=True, editable=False, auto_now=True) ult_alteracao = models.DateTimeField(_(u'Última alteração'), null=True, blank=True, editable=False, auto_now=True)
# guarda o tipo do objeto (classe) vinculado a esse registro # guarda o tipo do objeto (classe) vinculado a esse registro
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
# identificador do registro na classe vinculado a esse registro # identificador do registro na classe vinculado a esse registro
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id') content_object = generic.GenericForeignKey(
'content_type',
'object_id',
)
class Meta: class Meta:
ordering = ('numero',) ordering = ('numero',)
@ -200,16 +220,20 @@ class Contato(models.Model):
municipio = models.ForeignKey( municipio = models.ForeignKey(
Municipio, Municipio,
on_delete=models.SET_NULL,
verbose_name=_(u'município'), verbose_name=_(u'município'),
blank=True, blank=True,
null=True, null=True,
) )
# guarda o tipo do objeto (classe) vinculado a esse registro # guarda o tipo do objeto (classe) vinculado a esse registro
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
# identificador do registro na classe vinculado a esse registro # identificador do registro na classe vinculado a esse registro
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id') content_object = generic.GenericForeignKey(
'content_type',
'object_id',
)
class Meta: class Meta:
ordering = ('nome',) ordering = ('nome',)
@ -291,6 +315,7 @@ class Endereco(models.Model):
municipio = models.ForeignKey( municipio = models.ForeignKey(
Municipio, Municipio,
on_delete=models.SET_NULL,
verbose_name=_(u'município'), verbose_name=_(u'município'),
blank=True, blank=True,
null=True, null=True,
@ -298,10 +323,13 @@ class Endereco(models.Model):
municipio.uf_filter = True municipio.uf_filter = True
# guarda o tipo do objeto (classe) vinculado a esse registro # guarda o tipo do objeto (classe) vinculado a esse registro
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
# identificador do registro na classe vinculado a esse registro # identificador do registro na classe vinculado a esse registro
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id') content_object = generic.GenericForeignKey(
'content_type',
'object_id',
)
class Meta: class Meta:
ordering = ('logradouro', 'numero') ordering = ('logradouro', 'numero')

116
sigi/apps/convenios/admin.py

@ -4,29 +4,29 @@ from django.http import HttpResponse, HttpResponseRedirect
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from geraldo.generators import PDFGenerator from geraldo.generators import PDFGenerator
from sigi.apps.convenios.models import Projeto, Convenio, EquipamentoPrevisto, Anexo, Tramitacao from sigi.apps.convenios.models import (Projeto, StatusConvenio,
TipoSolicitacao, Convenio,
EquipamentoPrevisto, Anexo, Tramitacao)
from sigi.apps.convenios.reports import ConvenioReport from sigi.apps.convenios.reports import ConvenioReport
from sigi.apps.convenios.views import adicionar_convenios_carrinho from sigi.apps.convenios.views import adicionar_convenios_carrinho
from sigi.apps.utils import queryset_ascii from sigi.apps.utils import queryset_ascii
from sigi.apps.utils.base_admin import BaseModelAdmin from sigi.apps.utils.base_admin import BaseModelAdmin
from sigi.apps.servidores.models import Servidor
from sigi.apps.casas.admin import GerentesInterlegisFilter
# class TramitacaoInline(admin.TabularInline):
class TramitacaoInline(admin.TabularInline): # model = Tramitacao
model = Tramitacao # extra = 1
extra = 1
class AnexosInline(admin.TabularInline): class AnexosInline(admin.TabularInline):
model = Anexo model = Anexo
extra = 2 extra = 2
exclude = ['data_pub', ] exclude = ['data_pub', ]
# class EquipamentoPrevistoInline(admin.TabularInline):
class EquipamentoPrevistoInline(admin.TabularInline): # model = EquipamentoPrevisto
model = EquipamentoPrevisto # extra = 2
extra = 2 # raw_id_fields = ('equipamento',)
raw_id_fields = ('equipamento',)
class AnexoAdmin(BaseModelAdmin): class AnexoAdmin(BaseModelAdmin):
date_hierarchy = 'data_pub' date_hierarchy = 'data_pub'
@ -36,30 +36,44 @@ class AnexoAdmin(BaseModelAdmin):
search_fields = ('descricao', 'convenio__id', 'arquivo', search_fields = ('descricao', 'convenio__id', 'arquivo',
'convenio__casa_legislativa__nome') 'convenio__casa_legislativa__nome')
class AcompanhaFilter(admin.filters.RelatedFieldListFilter):
def __init__(self, *args, **kwargs):
super(AcompanhaFilter, self).__init__(*args, **kwargs)
servidores = Servidor.objects.filter(
convenio__isnull=False).order_by('nome_completo').distinct()
self.lookup_choices = [(x.id, x) for x in servidores]
class ConvenioAdmin(BaseModelAdmin): class ConvenioAdmin(BaseModelAdmin):
change_list_template = 'convenios/change_list.html' change_list_template = 'convenios/change_list.html'
fieldsets = ( fieldsets = (
(None, (None,
{'fields': ('casa_legislativa', 'num_processo_sf', 'num_convenio', 'projeto', 'observacao')} {'fields': ('casa_legislativa', 'num_processo_sf', 'num_convenio',
'projeto', 'data_sigi',)}
), ),
(_(u"Acompanhamento no gabinete"),
{'fields': ('data_solicitacao', 'data_sigad', 'tipo_solicitacao',
'status', 'acompanha', 'observacao',)}
),
(_(u"Gestão do convênio"),
{'fields': ('servico_gestao', 'servidor_gestao',)}
),
(_(u'Datas'), (_(u'Datas'),
{'fields': ('data_adesao', 'data_retorno_assinatura', {'fields': ('data_retorno_assinatura', 'duracao',
'data_termo_aceite', 'data_pub_diario', 'data_pub_diario',)}
'data_devolucao_via', 'data_postagem_correio')}
),
(_(u'Datas - Convenio sem assinatura'),
{'fields': ('data_devolucao_sem_assinatura', 'data_retorno_sem_assinatura',)}
), ),
) )
readonly_fields = ('data_sigi',)
actions = ['adicionar_convenios'] actions = ['adicionar_convenios']
inlines = (TramitacaoInline, AnexosInline, EquipamentoPrevistoInline) inlines = (AnexosInline,)
list_display = ('num_convenio', 'casa_legislativa', 'get_uf', list_display = ('num_convenio', 'casa_legislativa', 'get_uf',
'data_adesao', 'data_retorno_assinatura', 'data_pub_diario', 'data_termo_aceite', 'status_convenio', 'link_sigad', 'data_retorno_assinatura',
'projeto', 'duracao', 'projeto', 'status', 'acompanha',)
)
list_display_links = ('num_convenio', 'casa_legislativa',) list_display_links = ('num_convenio', 'casa_legislativa',)
list_filter = ('projeto', 'casa_legislativa__municipio__uf', 'casa_legislativa', 'conveniada', 'equipada') list_filter = ('status', ('acompanha', AcompanhaFilter),
('casa_legislativa__gerentes_interlegis',
GerentesInterlegisFilter), 'projeto',
'casa_legislativa__tipo', 'conveniada','equipada',
'casa_legislativa__municipio__uf',)
#date_hierarchy = 'data_adesao' #date_hierarchy = 'data_adesao'
ordering = ('casa_legislativa__tipo__sigla', 'casa_legislativa__municipio__uf', 'casa_legislativa') ordering = ('casa_legislativa__tipo__sigla', 'casa_legislativa__municipio__uf', 'casa_legislativa')
raw_id_fields = ('casa_legislativa',) raw_id_fields = ('casa_legislativa',)
@ -72,25 +86,43 @@ class ConvenioAdmin(BaseModelAdmin):
get_uf.short_description = _(u'UF') get_uf.short_description = _(u'UF')
get_uf.admin_order_field = 'casa_legislativa__municipio__uf__sigla' get_uf.admin_order_field = 'casa_legislativa__municipio__uf__sigla'
def status_convenio(self, obj):
if obj.pk is None:
return ""
status = obj.get_status()
if status in [u"Vencido", u"Desistência", u"Cancelado"]:
label = r"danger"
elif status == u"Vigente":
label = r"success"
elif status == u"Pendente":
label = r"warning"
else:
label = r"info"
return u'<p class="label label-{label}">{status}</p>'.format(label=label, status=status)
status_convenio.short_description = _(u"Status do convênio")
status_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
def changelist_view(self, request, extra_context=None): def changelist_view(self, request, extra_context=None):
import re from sigi.apps.convenios.views import normaliza_data
request.GET._mutable = True request.GET._mutable = True
if 'data_retorno_assinatura__gte' in request.GET: normaliza_data(request.GET, 'data_retorno_assinatura__gte')
value = request.GET.get('data_retorno_assinatura__gte', '') normaliza_data(request.GET, 'data_retorno_assinatura__lte')
if value == '': normaliza_data(request.GET, 'data_sigad__gte')
del request.GET['data_retorno_assinatura__gte'] normaliza_data(request.GET, 'data_sigad__lte')
elif re.match('^\d*$', value): # Year only normaliza_data(request.GET, 'data_sigi__gte')
request.GET['data_retorno_assinatura__gte'] = "%s-01-01" % value # Complete with january 1st normaliza_data(request.GET, 'data_sigi__lte')
elif re.match('^\d*\D\d*$', value): # Year and month normaliza_data(request.GET, 'data_solicitacao__gte')
request.GET['data_retorno_assinatura__gte'] = '%s-01' % value # Complete with 1st day of month normaliza_data(request.GET, 'data_solicitacao__lte')
if 'data_retorno_assinatura__lte' in request.GET:
value = request.GET.get('data_retorno_assinatura__lte', '')
if value == '':
del request.GET['data_retorno_assinatura__lte']
elif re.match('^\d*$', value): # Year only
request.GET['data_retorno_assinatura__lte'] = "%s-01-01" % value # Complete with january 1st
elif re.match('^\d*\D\d*$', value): # Year and month
request.GET['data_retorno_assinatura__lte'] = '%s-01' % value # Complete with 1st day of month
request.GET._mutable = False request.GET._mutable = False
return super(ConvenioAdmin, self).changelist_view( return super(ConvenioAdmin, self).changelist_view(
@ -141,5 +173,7 @@ class EquipamentoPrevistoAdmin(BaseModelAdmin):
'equipamento__modelo__modelo', 'equipamento__modelo__tipo__tipo') 'equipamento__modelo__modelo', 'equipamento__modelo__tipo__tipo')
admin.site.register(Projeto) admin.site.register(Projeto)
admin.site.register(StatusConvenio)
admin.site.register(TipoSolicitacao)
admin.site.register(Convenio, ConvenioAdmin) admin.site.register(Convenio, ConvenioAdmin)
admin.site.register(EquipamentoPrevisto, EquipamentoPrevistoAdmin) admin.site.register(EquipamentoPrevisto, EquipamentoPrevistoAdmin)

0
sigi/apps/mdl/__init__.py → sigi/apps/convenios/management/__init__.py

0
sigi/apps/mdl/migrations/__init__.py → sigi/apps/convenios/management/commands/__init__.py

26
sigi/apps/metas/management/commands/gera_map_data.py → sigi/apps/convenios/management/commands/duracao_act.py

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# sigi.apps.servicos.management.commands.atualiza_uso_servico # sigi.apps.casas.management.commands.importa_gerentes
# #
# Copyright (c) 2012 by Interlegis # Copyright (c) 2015 by Interlegis
# #
# GNU General Public License (GPL) # GNU General Public License (GPL)
# #
@ -21,15 +21,23 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. # 02110-1301, USA.
# #
from django.core.management.base import BaseCommand
from django.utils.translation import ugettext as _
from sigi.apps.metas.views import gera_map_data_file
from django.core.management.base import BaseCommand, CommandError
from sigi.apps.convenios.models import Projeto, Convenio
class Command(BaseCommand): class Command(BaseCommand):
help = _(u'Gera arquivo de dados de plotagem do mapa de atuação do Interlegis.') help = u"""Define a duração de todos os ACT para 60 meses.
* A sigla do Projeto precisa ser ACT;
* O campo duracao precisa estar em branco.
"""
def handle(self, *args, **options): def handle(self, *args, **options):
result = gera_map_data_file(cronjob=True) self.stdout.write(u"Atualizando ACTs... ")
self.stdout.write(result + "\n") act = Projeto.objects.get(sigla='ACT')
for conv in Convenio.objects.filter(projeto=act, duracao=None):
conv.duracao = 60
conv.save()
self.stdout.write(u"\tACT {sigad} da Casa {casa} atualizado".format(
sigad=conv.num_processo_sf, casa=conv.casa_legislativa.nome
))
self.stdout.write(u"Pronto!")

20
sigi/apps/convenios/migrations/0002_convenio_duracao.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('convenios', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='convenio',
name='duracao',
field=models.PositiveIntegerField(help_text='Deixar em branco caso a dura\xe7\xe3o seja indefinida', null=True, verbose_name='Dura\xe7\xe3o (meses)', blank=True),
preserve_default=True,
),
]

21
sigi/apps/convenios/migrations/0003_auto_20210406_1945.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('convenios', '0002_convenio_duracao'),
('casas', '0014_auto_20210406_1945'),
]
operations = [
migrations.AlterField(
model_name='convenio',
name='casa_legislativa',
field=models.ForeignKey(verbose_name='Casa Legislativa', to='casas.Orgao'),
preserve_default=True,
),
]

78
sigi/apps/convenios/migrations/0004_auto_20210407_1928.py

@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('servidores', '0001_initial'),
('convenios', '0003_auto_20210406_1945'),
]
operations = [
migrations.CreateModel(
name='StatusConvenio',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('nome', models.CharField(max_length=100)),
('cancela', models.BooleanField(default=False, verbose_name='Cancela o conv\xeanio')),
],
options={
'ordering': ('nome',),
'verbose_name': 'Estado de convenios',
'verbose_name_plural': 'Estados de convenios',
},
bases=(models.Model,),
),
migrations.AddField(
model_name='convenio',
name='acompanha',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='acompanhado por', blank=True, to='servidores.Servidor', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='convenio',
name='status',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='estado atual', blank=True, to='convenios.StatusConvenio', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='convenio',
name='casa_legislativa',
field=models.ForeignKey(verbose_name='\xf3rg\xe3o conveniado', to='casas.Orgao'),
preserve_default=True,
),
migrations.AlterField(
model_name='convenio',
name='data_adesao',
field=models.DateField(null=True, verbose_name='aderidas', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='convenio',
name='data_retorno_assinatura',
field=models.DateField(help_text='Conv\xeanio firmado.', null=True, verbose_name='conveniadas', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='convenio',
name='data_termo_aceite',
field=models.DateField(help_text='Equipamentos recebidos.', null=True, verbose_name='equipadas', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='convenio',
name='duracao',
field=models.PositiveIntegerField(help_text='Deixar em branco caso a dura\xe7\xe3o seja indefinida', null=True, verbose_name='dura\xe7\xe3o (meses)', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='convenio',
name='observacao',
field=models.TextField(null=True, verbose_name='observa\xe7\xf5es', blank=True),
preserve_default=True,
),
]

26
sigi/apps/convenios/migrations/0005_auto_20210409_0842.py

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('convenios', '0004_auto_20210407_1928'),
]
operations = [
migrations.AddField(
model_name='convenio',
name='data_sigad',
field=models.DateField(null=True, verbose_name='data de cadastro no SIGAD', blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='convenio',
name='data_sigi',
field=models.DateField(auto_now_add=True, verbose_name='data de cadastro no SIGI', null=True),
preserve_default=True,
),
]

33
sigi/apps/convenios/migrations/0006_auto_20210416_0841.py

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('convenios', '0005_auto_20210409_0842'),
]
operations = [
migrations.AlterField(
model_name='convenio',
name='casa_legislativa',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='\xf3rg\xe3o conveniado', to='casas.Orgao'),
preserve_default=True,
),
migrations.AlterField(
model_name='convenio',
name='projeto',
field=models.ForeignKey(to='convenios.Projeto', on_delete=django.db.models.deletion.PROTECT),
preserve_default=True,
),
migrations.AlterField(
model_name='tramitacao',
name='unid_admin',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Unidade Administrativa', to='convenios.UnidadeAdministrativa'),
preserve_default=True,
),
]

40
sigi/apps/convenios/migrations/0007_auto_20210416_0918.py

@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('convenios', '0006_auto_20210416_0841'),
]
operations = [
migrations.CreateModel(
name='TipoSolicitacao',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('nome', models.CharField(max_length=100)),
],
options={
'ordering': ('nome',),
'verbose_name': 'tipo de solicita\xe7\xe3o',
'verbose_name_plural': 'Tipos de solicita\xe7\xe3o',
},
bases=(models.Model,),
),
migrations.AddField(
model_name='convenio',
name='data_solicitacao',
field=models.DateField(null=True, verbose_name='data do e-mail de solicita\xe7\xe3o', blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='convenio',
name='tipo_solicitacao',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='tipo de solicita\xe7\xe3o', blank=True, to='convenios.TipoSolicitacao', null=True),
preserve_default=True,
),
]

34
sigi/apps/convenios/migrations/0008_auto_20210422_1907.py

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('servidores', '0004_auto_20210422_1907'),
('convenios', '0007_auto_20210416_0918'),
]
operations = [
migrations.AddField(
model_name='convenio',
name='servico_gestao',
field=models.ForeignKey(related_name='convenios_geridos', on_delete=django.db.models.deletion.SET_NULL, verbose_name='servi\xe7o de gest\xe3o', blank=True, to='servidores.Servico', null=True),
preserve_default=True,
),
migrations.AddField(
model_name='convenio',
name='servidor_gestao',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, verbose_name='servidor de gest\xe3o', blank=True, to='servidores.Servidor', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='convenio',
name='acompanha',
field=models.ForeignKey(related_name='convenios_acompanhados', on_delete=django.db.models.deletion.SET_NULL, verbose_name='acompanhado por', blank=True, to='servidores.Servidor', null=True),
preserve_default=True,
),
]

18
sigi/apps/convenios/migrations/0009_auto_20210611_0946.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('convenios', '0008_auto_20210422_1907'),
]
operations = [
migrations.AlterModelOptions(
name='projeto',
options={'ordering': ('nome',)},
),
]

259
sigi/apps/convenios/models.py

@ -1,13 +1,12 @@
# style="list-style-type: noneo -*- coding: utf-8 -*- #-*- coding: utf-8 -*-
from datetime import datetime import re
from datetime import datetime, date
from django.db import models from django.db import models
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from sigi.apps.utils import SearchField from sigi.apps.utils import SearchField
from sigi.apps.servidores.models import Servidor, Servico
class Projeto(models.Model): class Projeto(models.Model):
""" Modelo para representar os projetos do programa """ Modelo para representar os projetos do programa
Interlegis Interlegis
""" """
@ -16,25 +15,45 @@ class Projeto(models.Model):
def __unicode__(self): def __unicode__(self):
return self.sigla return self.sigla
class Meta:
ordering = ('nome',)
class StatusConvenio(models.Model):
nome = models.CharField(max_length=100)
cancela = models.BooleanField(_(u"Cancela o convênio"), default=False)
class Meta:
ordering = ('nome',)
verbose_name = _(u"Estado de convenios")
verbose_name_plural = _(u"Estados de convenios")
class Convenio(models.Model): def __unicode__(self):
return self.nome
""" Modelo que representa um convênio do Interlegis class TipoSolicitacao(models.Model):
com uma Casa Legislativa. nome = models.CharField(max_length=100)
Uma Casa Legislativa pode não ter um convênio e sim class Meta:
apenas uma adesão com o Interlegis, isto é, ordering = ('nome',)
não tem compromissos direto com o Interlegis apenas verbose_name = _(u"tipo de solicitação")
um pacto de colaboração entre as partes verbose_name_plural = _(u"Tipos de solicitação")
"""
def __unicode__(self):
return self.nome
class Convenio(models.Model):
casa_legislativa = models.ForeignKey( casa_legislativa = models.ForeignKey(
'casas.CasaLegislativa', 'casas.Orgao',
verbose_name=_(u'Casa Legislativa') on_delete=models.PROTECT,
verbose_name=_(u'órgão conveniado')
) )
# campo de busca em caixa baixa e sem acentos # campo de busca em caixa baixa e sem acentos
search_text = SearchField(field_names=['casa_legislativa']) search_text = SearchField(field_names=['casa_legislativa'])
projeto = models.ForeignKey(_(u'Projeto')) projeto = models.ForeignKey(
Projeto,
on_delete=models.PROTECT,
)
# numero designado pelo Senado Federal para o convênio # numero designado pelo Senado Federal para o convênio
num_processo_sf = models.CharField( num_processo_sf = models.CharField(
_(u'número do processo SF (Senado Federal)'), _(u'número do processo SF (Senado Federal)'),
@ -47,24 +66,88 @@ class Convenio(models.Model):
max_length=10, max_length=10,
blank=True blank=True
) )
data_sigi = models.DateField(
_(u"data de cadastro no SIGI"),
blank=True,
null=True,
auto_now_add=True
)
data_sigad = models.DateField(
_(u"data de cadastro no SIGAD"),
null=True,
blank=True
)
data_solicitacao = models.DateField(
_(u"data do e-mail de solicitação"),
null=True,
blank=True
)
tipo_solicitacao = models.ForeignKey(
TipoSolicitacao,
on_delete=models.PROTECT,
null=True,
blank=True,
verbose_name=_(u"tipo de solicitação")
)
status = models.ForeignKey(
StatusConvenio,
on_delete=models.SET_NULL,
verbose_name=_(u"estado atual"),
null=True,
blank=True
)
acompanha = models.ForeignKey(
Servidor,
on_delete=models.SET_NULL,
related_name='convenios_acompanhados',
verbose_name=_(u"acompanhado por"),
null=True,
blank=True
)
observacao = models.TextField(
_(u"observações"),
null=True,
blank=True,
)
servico_gestao = models.ForeignKey(
Servico,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='convenios_geridos',
verbose_name=_(u"serviço de gestão")
)
servidor_gestao = models.ForeignKey(
Servidor,
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name=_(u"servidor de gestão")
)
data_adesao = models.DateField( data_adesao = models.DateField(
_(u'Aderidas'), _(u'aderidas'),
null=True, null=True,
blank=True, blank=True,
) )
data_retorno_assinatura = models.DateField( data_retorno_assinatura = models.DateField(
_(u'Conveniadas'), _(u'conveniadas'),
null=True, null=True,
blank=True, blank=True,
help_text=_(u'Convênio firmado.') help_text=_(u'Convênio firmado.')
) )
duracao = models.PositiveIntegerField(
_(u"duração (meses)"),
null=True,
blank=True,
help_text=_(u"Deixar em branco caso a duração seja indefinida")
)
data_pub_diario = models.DateField( data_pub_diario = models.DateField(
_(u'data da publicação no Diário Oficial'), _(u'data da publicação no Diário Oficial'),
null=True, null=True,
blank=True blank=True
) )
data_termo_aceite = models.DateField( data_termo_aceite = models.DateField(
_(u'Equipadas'), _(u'equipadas'),
null=True, null=True,
blank=True, blank=True,
help_text=_(u'Equipamentos recebidos.') help_text=_(u'Equipamentos recebidos.')
@ -92,14 +175,64 @@ class Convenio(models.Model):
blank=True, blank=True,
help_text=_(u'Data do retorno do convênio sem assinatura'), help_text=_(u'Data do retorno do convênio sem assinatura'),
) )
observacao = models.CharField(
null=True,
blank=True,
max_length=100,
)
conveniada = models.BooleanField(default=False) conveniada = models.BooleanField(default=False)
equipada = models.BooleanField(default=False) equipada = models.BooleanField(default=False)
def get_termino_convenio(self):
if (self.data_retorno_assinatura is None or
self.duracao is None):
return None
ano = self.data_retorno_assinatura.year + int(self.duracao / 12)
mes = int(self.data_retorno_assinatura.month + int(self.duracao % 12))
if mes > 12:
ano = ano + 1
mes = mes - 12
dia = self.data_retorno_assinatura.day
while True:
try:
data_fim = date(year=ano, month=mes,day=dia)
break
except:
dia = dia - 1
return data_fim
def get_status(self):
if self.status and self.status.cancela:
return _(u"Cancelado")
if self.data_retorno_assinatura is not None:
if self.duracao is not None:
if date.today() >= self.get_termino_convenio():
return _(u"Vencido")
return _(u"Vigente")
if (self.data_retorno_assinatura is None and
self.data_devolucao_sem_assinatura is None and
self.data_retorno_sem_assinatura is None):
return _(u"Pendente")
if (self.data_devolucao_sem_assinatura is not None or
self.data_retorno_sem_assinatura is not None):
return _(u"Desistência")
return _(u"Indefinido")
def get_sigad_url(self):
m = re.match(
r'(?P<orgao>00100|00200)\.(?P<sequencial>\d{6})/(?P<ano>\d{4})-\d{2}',
self.num_processo_sf
)
if m:
return (r'<a href="https://intra.senado.leg.br/'
r'sigad/novo/protocolo/impressao.asp?area=processo'
r'&txt_numero_orgao={orgao}'
r'&txt_numero_sequencial={sequencial}'
r'&txt_numero_ano={ano}"'
r' target="_blank">{processo}</a>').format(processo=self.num_processo_sf,**m.groupdict())
return self.num_processo_sf
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.conveniada = self.data_retorno_assinatura is not None self.conveniada = self.data_retorno_assinatura is not None
self.equipada = self.data_termo_aceite is not None self.equipada = self.data_termo_aceite is not None
@ -111,16 +244,47 @@ class Convenio(models.Model):
verbose_name = _(u'convênio') verbose_name = _(u'convênio')
def __unicode__(self): def __unicode__(self):
if self.data_retorno_assinatura is not None: # if self.data_retorno_assinatura is not None:
return _(u"Convênio nº %(number)s - projeto %(project)s, em %(date)s") % dict( # return _(u"Convênio {project} nº {number} assinado em {date}. Status: {status}".format(
number=self.num_convenio, # number=self.num_convenio,
project=self.projeto.sigla, # project=self.projeto.sigla,
date=self.data_retorno_assinatura) # date=self.data_retorno_assinatura,
else: # status=self.get_status()))
return _(u"Adesão ao projeto %(project)s, em %(date)s") % dict( # else:
project=self.projeto.sigla, # return _(u"Adesão ao projeto %(project)s, em %(date)s") % dict(
date=self.data_adesao) # project=self.projeto.sigla,
# date=self.data_adesao)
if ((self.data_retorno_assinatura is None) and
(self.equipada and self.data_termo_aceite is not None)):
return _(u"Convênio nº {number} - equipada em {date} pelo {project}"
).format(number=self.num_convenio,
date=self.data_termo_aceite.strftime('%d/%m/%Y'),
project=self.projeto.sigla)
elif self.data_retorno_assinatura is None:
return _(u"Convênio nº {number} - adesão ao projeto {project}, "
u"em {date}").format(number=self.num_convenio,
project=self.projeto.sigla,
date=self.data_adesao)
if ((self.data_retorno_assinatura is not None) and not
(self.equipada and self.data_termo_aceite is not None)):
return _(u"Convênio nº {number} - conveniada ao {project} em "
u"{date}. Status: {status}").format(
number=self.num_convenio,
project=self.projeto.sigla,
date=self.data_retorno_assinatura.strftime('%d/%m/%Y'),
status=self.get_status())
if ((self.data_retorno_assinatura is not None) and
(self.equipada and self.data_termo_aceite is not None)):
return _(u"Convẽnio nº {number} - conveniada ao {project} em {date}"
u" e equipada em {equipped_date}. Status: {status}"
).format(number=self.num_convenio,
project=self.projeto.sigla,
date=self.data_retorno_assinatura.strftime(
'%d/%m/%Y'),
equipped_date=self.data_termo_aceite.strftime(
'%d/%m/%Y'),
status=self.get_status())
class EquipamentoPrevisto(models.Model): class EquipamentoPrevisto(models.Model):
@ -128,8 +292,15 @@ class EquipamentoPrevisto(models.Model):
disponibilizados para as Casas Legislativas disponibilizados para as Casas Legislativas
(foi usado na prmeira etapa do programa) (foi usado na prmeira etapa do programa)
""" """
convenio = models.ForeignKey(Convenio, verbose_name=_(u'convênio')) convenio = models.ForeignKey(
equipamento = models.ForeignKey('inventario.Equipamento') Convenio,
on_delete=models.CASCADE,
verbose_name=_(u'convênio')
)
equipamento = models.ForeignKey(
'inventario.Equipamento',
on_delete=models.CASCADE
)
quantidade = models.PositiveSmallIntegerField(default=1) quantidade = models.PositiveSmallIntegerField(default=1)
class Meta: class Meta:
@ -145,7 +316,11 @@ class Anexo(models.Model):
""" Modelo para giardar os documentos gerados """ Modelo para giardar os documentos gerados
no processo de convênio no processo de convênio
""" """
convenio = models.ForeignKey(Convenio, verbose_name=_(u'convênio')) convenio = models.ForeignKey(
Convenio,
on_delete=models.CASCADE,
verbose_name=_(u'convênio')
)
# caminho no sistema para o documento anexo # caminho no sistema para o documento anexo
arquivo = models.FileField(upload_to='apps/convenios/anexo/arquivo', max_length=500) arquivo = models.FileField(upload_to='apps/convenios/anexo/arquivo', max_length=500)
descricao = models.CharField(_(u'descrição'), max_length='70') descricao = models.CharField(_(u'descrição'), max_length='70')
@ -179,8 +354,16 @@ class Tramitacao(models.Model):
""" Modelo para registrar as vias do processo de convênio e a Unidade """ Modelo para registrar as vias do processo de convênio e a Unidade
responsável pelo tramite (ex. colher assinaturas do secretário do senado) responsável pelo tramite (ex. colher assinaturas do secretário do senado)
""" """
convenio = models.ForeignKey(Convenio, verbose_name=_(u'convênio')) convenio = models.ForeignKey(
unid_admin = models.ForeignKey(UnidadeAdministrativa, verbose_name=_(u'Unidade Administrativa')) Convenio,
on_delete=models.CASCADE,
verbose_name=_(u'convênio')
)
unid_admin = models.ForeignKey(
UnidadeAdministrativa,
on_delete=models.PROTECT,
verbose_name=_(u'Unidade Administrativa')
)
data = models.DateField() data = models.DateField()
observacao = models.CharField( observacao = models.CharField(
_(u'observação'), _(u'observação'),

166
sigi/apps/convenios/templates/convenios/carrinho.html

@ -21,8 +21,8 @@
{% block action %}deleta_itens_carrinho{% endblock %} {% block action %}deleta_itens_carrinho{% endblock %}
{% block tabela %} {% block tabela %}
<table> <table class="table table-striped">
<thead> <thead class="thead-dark">
<tr> <tr>
{%if not carIsEmpty%} {%if not carIsEmpty%}
<th class="sorted ascending"><!-- <input type="checkbox" id="action-toggle" style="display: inline;">--> <th class="sorted ascending"><!-- <input type="checkbox" id="action-toggle" style="display: inline;">-->
@ -38,7 +38,7 @@
</thead> </thead>
<tbody> <tbody>
{% for convenio in paginas.object_list %} {% for convenio in paginas.object_list %}
<tr class="{% cycle 'row1' 'row2' %}"> <tr>
{%if not carIsEmpty%} {%if not carIsEmpty%}
<th><input type="checkbox" name="_selected_action" <th><input type="checkbox" name="_selected_action"
value="{{convenio.id|safe}}" class="action-select" /></th> value="{{convenio.id|safe}}" class="action-select" /></th>
@ -56,103 +56,103 @@
{% endblock %} {% endblock %}
{% block botoes %} {% block botoes %}
<div id="tabs"> <ul class="nav nav-tabs" role="tablist">
<li class="active" role="presentation"><a href="#tabs-1" aria-controls="tabs-1" role="tab" data-toggle="tab">{% trans 'Relatório' %}</a></li>
<ul> <li role="presentation"><a href="#tabs-2" aria-controls="tabs-2" role="tab" data-toggle="tab">{% trans 'Arquivo CSV (Excel, Calc)' %}</a></li>
<li><a href="#tabs-1">{% trans 'Relatório' %}</a></li> </ul>
<li><a href="#tabs-2">{% trans 'Arquivo CSV (Excel, Calc)' %}</a></li> <div class="tab-content">
</ul> <div role="tabpanel" class="tab-pane active" id="tabs-1">
<div id="tabs-1"> <form action="../reports/{{ query_str }}" method="post">{% csrf_token %}
<form action="../reports/{{ query_str }}" method="post">{% csrf_token %} <fieldset>
<fieldset> <legend>{% trans 'Relatório por' %}</legend>
<legend>{% trans 'Relatório por' %}</legend> <ul class="tabs-conteudo">
<ul class="tabs-conteudo"> <li>
<li> <input type="radio" name="filtro_casa" value="tudo" checked="checked"/>
<input type="radio" name="filtro_casa" value="cm" checked="checked"/> <label>{% trans 'Todos' %}</label>
<label>{% trans 'Câmara Municipal' %}</label> </li>
</li> <li>
<li> <input type="radio" name="filtro_casa" value="cm"/>
<input type="radio" name="filtro_casa" value="al" /> <label>{% trans 'Câmara Municipal' %}</label>
<label>{% trans 'Assembléia Legislativa' %}</label> </li>
</li> <li>
</ul> <input type="radio" name="filtro_casa" value="al" />
<label>{% trans 'Assembléia Legislativa' %}</label>
</li>
</ul>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>{% trans 'Com data de aceite? (Equipada)' %}</legend> <legend>{% trans 'Com data de aceite? (Equipada)' %}</legend>
<ul class="tabs-conteudo"> <ul class="tabs-conteudo">
<li> <li>
<input type="radio" name="data_aceite" value="sim" checked="checked" /> <input type="radio" name="data_aceite" value="sim" checked="checked" />
<label>{% trans 'Sim' %}</label> <label>{% trans 'Sim' %}</label>
</li> </li>
<li> <li>
<input type="radio" name="data_aceite" value="nao" /> <input type="radio" name="data_aceite" value="nao" />
<label>{% trans 'Não' %}</label> <label>{% trans 'Não' %}</label>
</li> </li>
</ul> </ul>
</fieldset> </fieldset>
<ul class="botoes"> <input type="submit" value="Gerar Relatório" type="button" class="btn btn-primary">
<li><input type="submit" value="Gerar Relatório"></li> </form>
</ul>
</form>
</div> </div>
<div id="tabs-2"> <div role="tabpanel" class="tab-pane" id="tabs-2">
<form action="../csv/{{query_str}}" method="post">{% csrf_token %} <form action="../csv/{{query_str}}" method="post">{% csrf_token %}
<fieldset><legend>{% trans 'Escolha os atributos para exportar' %}</legend> <fieldset>
<ul id="sortable" class="tabs-conteudo"> <legend>{% trans 'Escolha os atributos para exportar' %}</legend>
<li> <ul id="sortable" class="tabs-conteudo">
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> <li>
<input type="checkbox" name="itens_csv_selected" value="No. Processo" <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="No. Processo"
class="action-select" checked="checked" /> class="action-select" checked="checked" />
<label>{% trans 'Nº Processo' %}</label> <label>{% trans 'Nº Processo' %}</label>
</li> </li>
<li> <li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="No. Convênio" <input type="checkbox" name="itens_csv_selected" value="No. Convênio"
class="action-select" checked="checked" /> class="action-select" checked="checked" />
<label>{% trans 'Nº Convênio' %}</label> <label>{% trans 'Nº Convênio' %}</label>
</li> </li>
<li> <li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Projeto" <input type="checkbox" name="itens_csv_selected" value="Projeto"
class="action-select" checked="checked" /> class="action-select" checked="checked" />
<label>{% trans 'Projeto' %}</label> <label>{% trans 'Projeto' %}</label>
</li> </li>
<li> <li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Casa Legislativa" <input type="checkbox" name="itens_csv_selected" value="Casa Legislativa"
class="action-select" checked="checked" /> class="action-select" checked="checked" />
<label>{% trans 'Casa Legislativa' %}</label> <label>{% trans 'Casa Legislativa' %}</label>
</li> </li>
<li> <li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Data de Adesão" <input type="checkbox" name="itens_csv_selected" value="Data de Adesão"
class="action-select" checked="checked" /> class="action-select" checked="checked" />
<label>{% trans 'Data de Adesão' %}</label> <label>{% trans 'Data de Adesão' %}</label>
</li> </li>
<li> <li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Data de Convênio" <input type="checkbox" name="itens_csv_selected" value="Data de Convênio"
class="action-select" checked="checked" /> class="action-select" checked="checked" />
<label>{% trans 'Data de Convênio' %}</label> <label>{% trans 'Data de Convênio' %}</label>
</li> </li>
<li> <li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Data da Publicacao no D.O." <input type="checkbox" name="itens_csv_selected" value="Data da Publicacao no D.O."
class="action-select" checked="checked" /> class="action-select" checked="checked" />
<label>{% trans 'Data da Publicação no Diário Oficial' %}</label> <label>{% trans 'Data da Publicação no Diário Oficial' %}</label>
</li> </li>
<li> <li>
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>
<input type="checkbox" name="itens_csv_selected" value="Data Equipada" <input type="checkbox" name="itens_csv_selected" value="Data Equipada"
class="action-select" checked="checked" /> class="action-select" checked="checked" />
<label>{% trans 'Data Equipada' %}</label> <label>{% trans 'Data Equipada' %}</label>
</li> </li>
</ul> </ul>
</fieldset> </fieldset>
<ul class="botoes"> <input type="submit" value="Exportar CSV" type="button" class="btn btn-primary"/>
<li><input type="submit" value="Exportar CSV" /></li> </form>
</ul> </div>
</form>
</div>
</div> </div>
{% endblock %} {% endblock %}

76
sigi/apps/convenios/templates/convenios/change_list.html

@ -1,19 +1,67 @@
{% extends "change_list_with_cart.html" %} {% extends "change_list_with_cart.html" %}
{% load i18n %} {% load i18n %}
{% block search %} {% block extra_search %}
<div id="toolbar"> <nav class="navbar navbar-default">
<form id="changelist-search" action="" method="get"> <div class="container-fluid">
<div><!-- DIV needed for valid HTML --> <div class="navbar-header">
<label for="searchbar"><img src="/static/admin/img/icon_searchbox.png" alt="Search" /></label> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<input type="text" size="40" name="q" value="" id="searchbar" /> <span class="sr-only">Toggle navigation</span>
<label for="data_retorno_assinatura__gte">{% trans 'Conveniadas a partir de' %}:</label> <span class="icon-bar"></span>
<input type="text" size="10" name="data_retorno_assinatura__gte" value="" id="data_retorno_assinatura__gte" class="vDateField"/> <span class="icon-bar"></span>
<label for="data_retorno_assinatura__lte">{% trans 'até' %}:</label> <span class="icon-bar"></span>
<input type="text" size="10" name="data_retorno_assinatura__lte" value="" id="data_retorno_assinatura__lte" /> </button>
<input type="submit" value="Pesquisar" /> <a class="navbar-brand" href="#">Filtro de datas</a>
{% trans 'Datas podem ser: Um ano (aaaa), um mês (aaaa-mm) ou um dia (aaaa-mm-dd)' %} <p class="navbar-text">Use AAAA, AAAA-MM ou AAAA-MM-DD</p>
</div> </div>
</form> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<form class="navbar-form navbar-left" role="extra-search" id="changelist-extrasearch" action="" method="get">
<div class="form-group">
<label for="data_retorno_assinatura__gte">{% trans 'Conveniadas a partir de' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_retorno_assinatura__gte" value="" id="data_retorno_assinatura__gte">
<label for="data_retorno_assinatura__lte">{% trans 'até' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_retorno_assinatura__lte" value="" id="data_retorno_assinatura__lte">
</div>
<div class="form-group">
<label for="data_sigad__gte">{% trans 'SIGAD a partir de' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_sigad__gte" value="" id="data_sigad__gte">
<label for="data_sigad__lte">{% trans 'até' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_sigad__lte" value="" id="data_sigad__lte">
</div>
<div class="form-group">
<label for="data_sigi__gte">{% trans 'SIGI a partir de' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_sigi__gte" value="" id="data_sigi__gte">
<label for="data_sigi__lte">{% trans 'até' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_sigi__lte" value="" id="data_sigi__lte">
</div>
<div class="form-group">
<label for="data_solicitacao__gte">{% trans 'E-mail a partir de' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_solicitacao__gte" value="" id="data_solicitacao__gte">
<label for="data_solicitacao__lte">{% trans 'até' %}:</label>
<input type="text" class="form-control search-query" size="10" name="data_solicitacao__lte" value="" id="data_solicitacao__lte">
</div>
<button type="submit" class="btn btn-default navbar-btn ">
<span class="glyphicon glyphicon-search"></span>
</button>
</form>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{% comment %}
<form class="navbar-form navbar-right" role="extra-search" id="changelist-extrasearch" action="" method="get">
<div class="form-group"><!-- DIV needed for valid HTML -->
<div class="input-group">
<label for="data_retorno_assinatura__gte">{% trans 'Conveniadas a partir de' %}:</label>
<input type="text" class="form-control search-query" placeholder="YYYY ou YYYY-MM ou YYYY-MM-DD" size="10" name="data_retorno_assinatura__gte" value="" id="data_retorno_assinatura__gte">
<label for="data_retorno_assinatura__lte">{% trans 'até' %}:</label>
<input type="text" class="form-control search-query" placeholder="YYYY ou YYYY-MM ou YYYY-MM-DD" size="10" name="data_retorno_assinatura__lte" value="" id="data_retorno_assinatura__lte">
<span class="input-group-btn">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</div> </div>
{% endblock %} </form>
{% endcomment %}
{% endblock %}

45
sigi/apps/convenios/views.py

@ -11,10 +11,15 @@ from django.template import Context, loader
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from geraldo.generators import PDFGenerator from geraldo.generators import PDFGenerator
from sigi.apps.casas.models import CasaLegislativa from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import UnidadeFederativa from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Convenio, Projeto from sigi.apps.convenios.models import Convenio, Projeto
from sigi.apps.convenios.reports import ConvenioPorCMReport, ConvenioPorALReport, ConvenioReportSemAceiteAL, ConvenioReportSemAceiteCM from sigi.apps.convenios.reports import (ConvenioReport,
ConvenioReportSemAceite,
ConvenioPorCMReport,
ConvenioPorALReport,
ConvenioReportSemAceiteAL,
ConvenioReportSemAceiteCM)
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
@ -31,10 +36,32 @@ def query_ordena(qs, o, ot):
qs = qs.order_by("-" + aux) qs = qs.order_by("-" + aux)
return qs return qs
def normaliza_data(get, nome_param):
import re
if nome_param in get:
value = get.get(nome_param, '')
if value == '':
del get[nome_param]
elif re.match('^\d*$', value): # Year only
# Complete with january 1st
get[nome_param] = "%s-01-01" % value
elif re.match('^\d*\D\d*$', value): # Year and month
# Complete with 1st day of month
get[nome_param] = '%s-01' % value
def get_for_qs(get, qs): def get_for_qs(get, qs):
kwargs = {} kwargs = {}
ids = 0 ids = 0
get._mutable = True
normaliza_data(get, 'data_retorno_assinatura__gte')
normaliza_data(get, 'data_retorno_assinatura__lte')
normaliza_data(get, 'data_sigad__gte')
normaliza_data(get, 'data_sigad__lte')
normaliza_data(get, 'data_sigi__gte')
normaliza_data(get, 'data_sigi__lte')
normaliza_data(get, 'data_solicitacao__gte')
normaliza_data(get, 'data_solicitacao__lte')
get._mutable = False
for k, v in get.iteritems(): for k, v in get.iteritems():
if k not in ['page', 'pop', 'q', '_popup']: if k not in ['page', 'pop', 'q', '_popup']:
if not k == 'o': if not k == 'o':
@ -45,8 +72,7 @@ def get_for_qs(get, qs):
if(str(k) == 'ids'): if(str(k) == 'ids'):
ids = 1 ids = 1
break break
qs = qs.filter(**kwargs) qs = qs.filter(**kwargs)
if ids: if ids:
query = 'id IN (' + kwargs['ids'].__str__() + ')' query = 'id IN (' + kwargs['ids'].__str__() + ')'
qs = Convenio.objects.extra(where=[query]) qs = Convenio.objects.extra(where=[query])
@ -154,7 +180,7 @@ def report(request, id=None):
tipo = request.POST['filtro_casa'] tipo = request.POST['filtro_casa']
if 'data_aceite' in request.POST: if 'data_aceite' in request.POST:
data_aceite_has = request.POST['data_aceite'] data_aceite_has = request.POST['data_aceite']
# Verifica filtro se é por Assembleia # filtro adicional pela seleção do usuário
if tipo == 'al': if tipo == 'al':
qs = qs.filter(casa_legislativa__tipo__sigla='AL') qs = qs.filter(casa_legislativa__tipo__sigla='AL')
# Verifica se é com data de aceite # Verifica se é com data de aceite
@ -162,12 +188,17 @@ def report(request, id=None):
report = ConvenioReportSemAceiteAL(queryset=qs) report = ConvenioReportSemAceiteAL(queryset=qs)
else: else:
report = ConvenioPorALReport(queryset=qs) report = ConvenioPorALReport(queryset=qs)
else: elif tipo == 'cm':
qs = qs.filter(casa_legislativa__tipo__sigla='CM') qs = qs.filter(casa_legislativa__tipo__sigla='CM')
if data_aceite_has == 'nao': if data_aceite_has == 'nao':
report = ConvenioReportSemAceiteCM(queryset=qs) report = ConvenioReportSemAceiteCM(queryset=qs)
else: else:
report = ConvenioPorCMReport(queryset=qs) report = ConvenioPorCMReport(queryset=qs)
else:
if data_aceite_has == 'nao':
report = ConvenioReportSemAceite(queryset=qs)
else:
report = ConvenioReport(queryset=qs)
response = HttpResponse(content_type='application/pdf') response = HttpResponse(content_type='application/pdf')
if report: if report:
@ -249,7 +280,7 @@ def report_regiao(request, regiao='NE'):
projetos = Projeto.objects.all() projetos = Projeto.objects.all()
camaras = CasaLegislativa.objects.filter(tipo__sigla='CM') camaras = Orgao.objects.filter(tipo__sigla='CM')
tabelas = list() tabelas = list()
# Geral # Geral

10
sigi/apps/diagnosticos/forms.py

@ -11,7 +11,7 @@ from django.utils.translation import ugettext as _
from eav.fields import RangeField from eav.fields import RangeField
from eav.forms import BaseDynamicEntityForm from eav.forms import BaseDynamicEntityForm
from sigi.apps.casas.models import CasaLegislativa, Funcionario from sigi.apps.casas.models import Orgao, Funcionario
from sigi.apps.contatos.models import Telefone from sigi.apps.contatos.models import Telefone
from sigi.apps.diagnosticos.models import Diagnostico from sigi.apps.diagnosticos.models import Diagnostico
from sigi.apps.diagnosticos.widgets import EavCheckboxSelectMultiple, EavRadioSelect from sigi.apps.diagnosticos.widgets import EavCheckboxSelectMultiple, EavRadioSelect
@ -132,23 +132,23 @@ class DiagnosticoMobileForm(BaseDynamicEntityForm):
self.initial[schema.name] = value self.initial[schema.name] = value
class CasaLegislativaMobileForm(forms.ModelForm): class OrgaoMobileForm(forms.ModelForm):
data_instalacao = forms.DateField(label=_(u'Data de instalação da Casa Legislativa'), required=False) data_instalacao = forms.DateField(label=_(u'Data de instalação da Casa Legislativa'), required=False)
data_criacao = forms.DateField() data_criacao = forms.DateField()
class Meta: class Meta:
model = CasaLegislativa model = Orgao
fields = ('cnpj', 'data_criacao', 'data_instalacao', 'logradouro', 'bairro', 'cep', 'email', 'pagina_web') fields = ('cnpj', 'data_criacao', 'data_instalacao', 'logradouro', 'bairro', 'cep', 'email', 'pagina_web')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(CasaLegislativaMobileForm, self).__init__(*args, **kwargs) super(OrgaoMobileForm, self).__init__(*args, **kwargs)
self.fields['data_criacao'] = forms.DateField( self.fields['data_criacao'] = forms.DateField(
label=_(u'Data de criação do Município'), label=_(u'Data de criação do Município'),
initial=self.instance.municipio.data_criacao, initial=self.instance.municipio.data_criacao,
required=False) required=False)
def save(self, commit=True): def save(self, commit=True):
super(CasaLegislativaMobileForm, self).save(commit=True) super(OrgaoMobileForm, self).save(commit=True)
self.instance.municipio.data_criacao = self.cleaned_data['data_criacao'] self.instance.municipio.data_criacao = self.cleaned_data['data_criacao']
if commit: if commit:
self.instance.municipio.save() self.instance.municipio.save()

0
sigi/apps/saberes/__init__.py → sigi/apps/diagnosticos/management/__init__.py

0
sigi/apps/saberes/management/__init__.py → sigi/apps/diagnosticos/management/commands/__init__.py

275
sigi/apps/diagnosticos/management/commands/ls_export.py

@ -0,0 +1,275 @@
# -*- coding: utf-8 -*-
import csv
from collections import OrderedDict
from django.core.management.base import BaseCommand, CommandError
from sigi.apps.casas.models import Funcionario
from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.diagnosticos.models import Categoria, Diagnostico, Resposta
DATATYPES = {
'text': 'T',
'float': 'N',
'date': 'D',
'one': 'L',
'many': 'M'
}
class Command(BaseCommand):
help = u"""Exporta dados do diagnóstico para o formato Tab-Separated-Values
do LimeSurvey, conforme documentado em
https://manual.limesurvey.org/Tab_Separated_Value_survey_structure"""
def handle(self, *args, **options):
def normalize(l):
return [s.encode('utf-8') for s in l]
nonum = lambda s: s[s.index(' ')+1:]
avalue = lambda e: ('Y' if e.title == u'Sim' else 'N'
if e.title == u'Não' else e.id)
setores = [(i+1, s[0], s[1]) for i, s in enumerate(
Funcionario.SETOR_CHOICES)]
if len(args) < 2:
raise CommandError(u"Use: ls_export survey_id struct.txt data.csv")
survey_id = args[0]
lsf = csv.writer(open(args[1], 'wb+'), delimiter="\t",
quoting=csv.QUOTE_MINIMAL)
struct = ['id', 'token', 'submitdate', 'lastpage', 'startlanguage',
'seed']
self.stdout.write("Exporting survey structure: ")
# Structure headers #
self.stdout.write("\tStructure headers...", ending=" ")
lsf.writerow(['id', 'related_id', 'class', 'type/scale', 'name',
'relevance', 'text', 'help', 'language', 'validation',
'mandatory', 'other', 'default', 'same_default'])
lsf.writerows([
['', '', 'S', '', 'sid', '', survey_id],
['', '', 'S', '', 'format', '', 'G'],
['', '', 'S', '', 'language', '', 'pt-BR'],
['', '', 'SL', '', 'surveyls_survey_id', '', survey_id, '',
'pt-BR'],
['', '', 'SL', '', 'surveyls_language', '', 'pt-BR', '', 'pt-BR'],
['', '', 'SL', '', 'surveyls_title', '',
u'Diagnóstico PML'.encode('utf-8'), '', 'pt-BR']])
self.stdout.write("Done!")
# Identificação da Casa Legislativa e sua equipe #
self.stdout.write("\tIdentificação da Casa...", ending=" ")
lsf.writerow(normalize(['1000', '', 'G', '', u'Identificação da Casa',
'', '', '', 'pt-BR']))
lsf.writerow(normalize(['1001', '', 'Q', 'L', 'c001q001', '1',
u'Região', '', 'pt-BR', '', 'Y', 'N', '', '0']))
struct.append('c001q001')
lsf.writerows([normalize(['1001', '', 'A', '0', sigla, '', nome, '',
'pt-BR']) for sigla, nome in UnidadeFederativa.REGIAO_CHOICES])
lsf.writerow(normalize(['1002', '', 'Q', '!', 'c001q002', '1',
u'Estado (UF)', '', 'pt-BR', '', 'Y', 'N', '', '0']))
struct.append('c001q002')
lsf.writerows([normalize(['1002', '', 'A', '0', u.sigla, '', u.nome, '',
'pt-BR']) for u in UnidadeFederativa.objects.all()])
lsf.writerow(normalize(['1003', '', 'Q', 'S', 'c001q003', '1',
u'Município', '', 'pt-BR', '', 'Y', 'N', '', '0']))
struct.append('c001q003')
lsf.writerow(normalize(['1004', '', 'Q', 'D', 'c001q004', '1',
u'Data de criação do município', '', 'pt-BR', '', 'Y', 'N', '',
'0']))
struct.append('c001q004')
lsf.writerow(normalize(['1005', '', 'Q', 'S', 'c001q005', '1',
u'Nome da Casa', '', 'pt-BR', '', 'Y', 'N', '', '0']))
struct.append('c001q005')
lsf.writerow(normalize(['1006', '', 'Q', 'D', 'c001q006', '1',
u'Data de instalação do legislativo', '', 'pt-BR', '', 'Y', 'N', '',
'0']))
struct.append('c001q006')
lsf.writerow(normalize(['1007', '', 'Q', 'T', 'c001q007', '1',
u'Endereço', '', 'pt-BR', '', 'N', 'N', '', '0']))
struct.append('c001q007')
lsf.writerow(normalize(['1008', '', 'Q', 'S', 'c001q008', '1',
u'CNPJ', '', 'pt-BR', '', 'N', 'N', '', '0']))
struct.append('c001q008')
lsf.writerow(normalize(['1009', '', 'Q', 'S', 'c001q009', '1',
u'E-mail principal', '', 'pt-BR', '', 'N', 'N', '', '0']))
struct.append('c001q009')
lsf.writerow(normalize(['1010', '', 'Q', 'S', 'c001q010', '1',
u'Endereço Web', '', 'pt-BR', '', 'N', 'N', '', '0']))
struct.append('c001q010')
lsf.writerow(normalize(['1011', '', 'Q', ';', 'c001q011', '1',
u'Pessoas de contato', '', 'pt-BR', '', 'N', 'N', '', '0']))
lsf.writerow(normalize(['101198', '', 'SQ', '1', 'SQ00101', '', u'Nome',
'', 'pt-BR', '', '', 'N', '', '0']))
lsf.writerow(normalize(['101199', '', 'SQ', '1', 'SQ00102', '',
u'E-mail', '', 'pt-BR', '', '', 'N', '', '0']))
for i, k, v in setores:
lsf.writerow(normalize(['10110{0}'.format(i), '', 'SQ', '',
'SQ1010{0}'.format(i), '1', v, '', 'pt-BR', '', '', 'N',
'', '0']))
struct.extend([
'c001q011_SQ1010{0}_SQ00101'.format(i),
'c001q011_SQ1010{0}_SQ00102'.format(i),
])
self.stdout.write("Done!")
# Equipe de diagnóstico #
self.stdout.write("\tEquipe de diagnóstico...", ending=" ")
lsf.writerow(normalize(['2000', '', 'G', '', u'Equipe de diagnóstico',
'', '', '', 'pt-BR']))
lsf.writerow(normalize(['2001', '', 'Q', 'D', 'c002q001', '1',
u'Data de início da visita', '', 'pt-BR', '', 'Y', 'N', '', '0']))
struct.append('c002q001')
lsf.writerow(normalize(['2002', '', 'Q', 'D', 'c002q002', '1',
u'Data de término da visita', '', 'pt-BR', '', 'Y', 'N', '', '0']))
struct.append('c002q002')
lsf.writerow(normalize(['2003', '', 'Q', 'S', 'c002q003', '1',
u'Líder da equipe', '', 'pt-BR', '', 'Y', 'N', '', '0']))
struct.append('c002q003')
lsf.writerow(normalize(['2004', '', 'Q', 'T', 'c002q004', '1',
u'Membros da equipe', '', 'pt-BR', '', 'Y', 'N', '', '0']))
struct.append('c002q004')
self.stdout.write("Done!")
for c in Categoria.objects.all():
self.stdout.write("\t{0}...".format(nonum(c.nome).encode('utf-8')), ending=" ")
lsf.writerow(normalize([str(c.id), '', 'G', '',
nonum(c.nome), '', nonum(c.nome), '',
'pt-BR']))
perguntas = sorted([(p.title, p) for p in c.perguntas.all()])
for t, p in perguntas:
lstype = DATATYPES[p.datatype]
# Hack para perguntas SIM/NÃO que foram cadastradas como Choice
if lstype == 'L':
if ("".join([e.title for e in p.choices.all()]) in
[u"SimNão", u"NãoSim"]):
lstype = 'Y'
########
relevance = "1"
if p.abre_por.exists():
relevance = "(" + " or ".join(
[u'({sid}X{gid}X{qid}.NAOK == "{value}")'.format(
sid=survey_id, gid=e.schema.categoria.id,
qid=e.schema.id, value=avalue(e)) for e in
p.abre_por.all()]) + ")"
lsf.writerow(normalize([str(p.id), '', 'Q', lstype,
'c{0:03}q{1:03}'.format(c.id, p.id), relevance,
nonum(p.title), p.help_text, 'pt-BR', '', 'NY'[p.required],
'N', '', '0']))
if lstype == 'L':
lsf.writerows([normalize([str(p.id), u'', u'A', u'0',
str(e.id), u'', e.title, u'', u'pt-BR'])
for e in p.choices.all()])
if lstype == 'M':
lsf.writerows([normalize([str(p.id*1000+e.id), u'', u'SQ',
u'', str(e.id), u'1', e.title, u'', u'pt-BR'])
for e in p.choices.all()])
struct.extend(['c{0:03}q{1:03}_{2}'.format(c.id, p.id,
e.id) for e in p.choices.all()])
else:
struct.extend(['c{0:03}q{1:03}'.format(c.id, p.id)])
self.stdout.write("Done!")
if len(args) < 3: # No data export
return
self.stdout.write("Exporting survey data: ")
dtf = csv.writer(open(args[2], 'wb+'), delimiter='\t',
quoting=csv.QUOTE_MINIMAL)
dtf.writerow(struct)
for d in Diagnostico.objects.all():
self.stdout.write(u"\t{0}".format(d.casa_legislativa.nome))
form = OrderedDict.fromkeys(struct, '{question_not_shown}')
form['id'] = str(d.id)
if d.data_publicacao:
form['submitdate'] = d.data_publicacao.isoformat()
# form['lastpage'] = '8'
form['startlanguage'] = 'pt-BR'
# form['seed'] = '123456'
# Identificação da Casa Legislativa e sua equipe #
form['c001q001'] = d.casa_legislativa.municipio.uf.regiao
form['c001q002'] = d.casa_legislativa.municipio.uf.sigla
form['c001q003'] = d.casa_legislativa.municipio.nome
if d.casa_legislativa.municipio.data_criacao:
form['c001q004'] = \
d.casa_legislativa.municipio.data_criacao.isoformat()
form['c001q005'] = d.casa_legislativa.nome
if d.casa_legislativa.data_instalacao:
form['c001q006'] = \
d.casa_legislativa.data_instalacao.isoformat()
form['c001q007'] = (
u"{logradouro}{{cr}}{{newline}}"
u"{bairro}{{cr}}{{newline}}"
u"{cep} - {municipio} - {uf}".format(
logradouro=d.casa_legislativa.logradouro,
bairro=d.casa_legislativa.bairro,
cep=d.casa_legislativa.cep,
municipio=d.casa_legislativa.municipio.nome,
uf=d.casa_legislativa.municipio.uf.sigla
))
form['c001q008'] = d.casa_legislativa.cnpj
form['c001q009'] = d.casa_legislativa.email
form['c001q010'] = d.casa_legislativa.pagina_web
for i, k, v in setores:
q = d.casa_legislativa.funcionario_set.filter(setor=k)
if q.exists():
f = q.first()
knome = 'c001q011_SQ1010{0}_SQ00101'.format(i)
kmail = 'c001q011_SQ1010{0}_SQ00102'.format(i)
form[knome] = f.nome
form[kmail] = f.email
if d.data_visita_inicio:
form['c002q001'] = d.data_visita_inicio.isoformat()
if d.data_visita_fim:
form['c002q002'] = d.data_visita_fim.isoformat()
form['c002q003'] = d.responsavel.nome_completo
form['c002q004'] = "{cr}{newline}".join(
[e.membro.nome_completo for e in d.equipe_set.all()])
for r in Resposta.objects.filter(entity_id=d.id):
if r.schema.datatype == 'many':
key = "c{cid:03}q{qid:03}_{sqid}".format(
cid=r.schema.categoria.id,
qid=r.schema.id,
sqid=r.value.id
)
value = 'Y'
else:
key = "c{cid:03}q{qid:03}".format(cid=r.schema.categoria.id,
qid=r.schema.id)
value = r.value
if r.schema.datatype == 'one':
if value is None:
value = '{question_not_shown}'
elif value.title == u'Sim':
value = 'Y'
elif value.title == u'Não':
value = 'N'
else:
value = r.value.id
elif r.schema.datatype == 'text':
value = value.\
replace('\r\n', '{cr}{newline}').\
replace('\r', '{cr}{newline}').\
replace('\n', '{cr}{newline}').\
replace('\t', ' ')
if value is None:
value = '{question_not_shown}'
form[key] = u'{0}'.format(value)
dtf.writerow(normalize(form.values()))
self.stdout.write('Done!')

22
sigi/apps/diagnosticos/migrations/0002_auto_20170407_1024.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import autoslug.fields
import eav.models
class Migration(migrations.Migration):
dependencies = [
('diagnosticos', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='pergunta',
name='name',
field=autoslug.fields.AutoSlugField(populate_from=b'title', editable=True, max_length=250, blank=True, verbose_name='name', slugify=eav.models.slugify_attr_name),
preserve_default=True,
),
]

20
sigi/apps/diagnosticos/migrations/0003_auto_20201101_2240.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('diagnosticos', '0002_auto_20170407_1024'),
]
operations = [
migrations.AlterField(
model_name='escolha',
name='schema_to_open',
field=models.ForeignKey(related_name='abre_por', verbose_name='pergunta para abrir', blank=True, to='diagnosticos.Pergunta', null=True),
preserve_default=True,
),
]

21
sigi/apps/diagnosticos/migrations/0004_auto_20210406_1945.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('diagnosticos', '0003_auto_20201101_2240'),
('casas', '0014_auto_20210406_1945'),
]
operations = [
migrations.AlterField(
model_name='diagnostico',
name='casa_legislativa',
field=models.ForeignKey(verbose_name='Casa Legislativa', to='casas.Orgao'),
preserve_default=True,
),
]

51
sigi/apps/diagnosticos/migrations/0005_auto_20210416_0841.py

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('diagnosticos', '0004_auto_20210406_1945'),
]
operations = [
migrations.AlterField(
model_name='diagnostico',
name='casa_legislativa',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Casa Legislativa', to='casas.Orgao'),
preserve_default=True,
),
migrations.AlterField(
model_name='diagnostico',
name='responsavel',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='respons\xe1vel', to='servidores.Servidor'),
preserve_default=True,
),
migrations.AlterField(
model_name='equipe',
name='membro',
field=models.ForeignKey(to='servidores.Servidor', on_delete=django.db.models.deletion.PROTECT),
preserve_default=True,
),
migrations.AlterField(
model_name='escolha',
name='schema_to_open',
field=models.ForeignKey(related_name='abre_por', on_delete=django.db.models.deletion.SET_NULL, verbose_name='pergunta para abrir', blank=True, to='diagnosticos.Pergunta', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='resposta',
name='choice',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='escolha', blank=True, to='diagnosticos.Escolha', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='resposta',
name='schema',
field=models.ForeignKey(related_name='attrs', on_delete=django.db.models.deletion.PROTECT, verbose_name='pergunta', to='diagnosticos.Pergunta'),
preserve_default=True,
),
]

67
sigi/apps/diagnosticos/models.py

@ -14,8 +14,10 @@ class Diagnostico(BaseEntity):
em uma Casa Legislativa em uma Casa Legislativa
""" """
casa_legislativa = models.ForeignKey( casa_legislativa = models.ForeignKey(
'casas.CasaLegislativa', 'casas.Orgao',
verbose_name=_(u'Casa Legislativa')) on_delete=models.PROTECT,
verbose_name=_(u'Casa Legislativa')
)
# campo de busca em caixa baixa e sem acento # campo de busca em caixa baixa e sem acento
search_text = SearchField(field_names=['casa_legislativa']) search_text = SearchField(field_names=['casa_legislativa'])
@ -38,8 +40,11 @@ class Diagnostico(BaseEntity):
blank=True, blank=True,
) )
responsavel = models.ForeignKey('servidores.Servidor', responsavel = models.ForeignKey(
verbose_name=_(u'responsável')) 'servidores.Servidor',
on_delete=models.PROTECT,
verbose_name=_(u'responsável')
)
class Meta: class Meta:
verbose_name, verbose_name_plural = _(u'diagnóstico'), _(u'diagnósticos') verbose_name, verbose_name_plural = _(u'diagnóstico'), _(u'diagnósticos')
@ -156,7 +161,11 @@ class Pergunta(BaseSchema):
Uma pergunta tem o nome e o tipo da resposta Uma pergunta tem o nome e o tipo da resposta
""" """
categoria = models.ForeignKey(Categoria, related_name='perguntas') categoria = models.ForeignKey(
Categoria,
on_delete=models.CASCADE,
related_name='perguntas'
)
def group_choices(self): def group_choices(self):
from django.db import connection, transaction from django.db import connection, transaction
@ -196,10 +205,20 @@ class Escolha(BaseChoice):
""" Perguntas de multiplas escolhas tem as opções """ Perguntas de multiplas escolhas tem as opções
cadastradas neste modelo cadastradas neste modelo
""" """
schema = models.ForeignKey(Pergunta, schema = models.ForeignKey(
related_name='choices', verbose_name=_(u'pergunta')) Pergunta,
schema_to_open = models.ForeignKey(Pergunta, related_name='', on_delete=models.CASCADE,
verbose_name=_(u'pergunta para abrir'), blank=True, null=True) related_name='choices',
verbose_name=_(u'pergunta')
)
schema_to_open = models.ForeignKey(
Pergunta,
on_delete=models.SET_NULL,
related_name='abre_por',
verbose_name=_(u'pergunta para abrir'),
blank=True,
null=True
)
ordem = models.PositiveIntegerField(blank=True, null=True) ordem = models.PositiveIntegerField(blank=True, null=True)
class Meta: class Meta:
@ -212,10 +231,19 @@ class Resposta(BaseAttribute):
""" Modelo para guardar as respostas das perguntas """ Modelo para guardar as respostas das perguntas
de um diagnosico de um diagnosico
""" """
schema = models.ForeignKey(Pergunta, related_name='attrs', schema = models.ForeignKey(
verbose_name=_(u'pergunta')) Pergunta,
choice = models.ForeignKey(Escolha, verbose_name=_(u'escolha'), on_delete=models.PROTECT,
blank=True, null=True) related_name='attrs',
verbose_name=_(u'pergunta')
)
choice = models.ForeignKey(
Escolha,
on_delete=models.PROTECT,
verbose_name=_(u'escolha'),
blank=True,
null=True
)
class Meta: class Meta:
verbose_name, verbose_name_plural = _(u'resposta'), _(u'respostas') verbose_name, verbose_name_plural = _(u'resposta'), _(u'respostas')
@ -225,8 +253,11 @@ class Equipe(models.Model):
""" Modelo que representa a equipe de um diagnóstico """ Modelo que representa a equipe de um diagnóstico
""" """
diagnostico = models.ForeignKey(Diagnostico) diagnostico = models.ForeignKey(Diagnostico, on_delete=models.CASCADE)
membro = models.ForeignKey('servidores.Servidor') membro = models.ForeignKey(
'servidores.Servidor',
on_delete=models.PROTECT
)
class Meta: class Meta:
verbose_name, verbose_name_plural = _(u'equipe'), _(u'equipe') verbose_name, verbose_name_plural = _(u'equipe'), _(u'equipe')
@ -240,7 +271,11 @@ class Anexo(models.Model):
""" Modelo para representar os documentos levantados """ Modelo para representar os documentos levantados
no processo de diagnóstico. Podem ser fotos, contratos, etc. no processo de diagnóstico. Podem ser fotos, contratos, etc.
""" """
diagnostico = models.ForeignKey(Diagnostico, verbose_name=u'diagnóstico') diagnostico = models.ForeignKey(
Diagnostico,
on_delete=models.CASCADE,
verbose_name=u'diagnóstico'
)
arquivo = models.FileField(upload_to='apps/diagnostico/anexo/arquivo', max_length=500) arquivo = models.FileField(upload_to='apps/diagnostico/anexo/arquivo', max_length=500)
descricao = models.CharField(_(u'descrição'), max_length='70') descricao = models.CharField(_(u'descrição'), max_length='70')
data_pub = models.DateTimeField(_(u'data da publicação do anexo'), data_pub = models.DateTimeField(_(u'data da publicação do anexo'),

6
sigi/apps/diagnosticos/views.py

@ -12,7 +12,7 @@ from sigi.apps.casas.models import Funcionario
from sigi.apps.contatos.models import Telefone from sigi.apps.contatos.models import Telefone
from sigi.apps.diagnosticos.decorators import validate_diagnostico from sigi.apps.diagnosticos.decorators import validate_diagnostico
from sigi.apps.diagnosticos.forms import (DiagnosticoMobileForm, from sigi.apps.diagnosticos.forms import (DiagnosticoMobileForm,
CasaLegislativaMobileForm, FuncionariosMobileForm) OrgaoMobileForm, FuncionariosMobileForm)
from sigi.apps.diagnosticos.models import Diagnostico, Categoria, Pergunta from sigi.apps.diagnosticos.models import Diagnostico, Categoria, Pergunta
from sigi.apps.diagnosticos.urls import LOGIN_REDIRECT_URL from sigi.apps.diagnosticos.urls import LOGIN_REDIRECT_URL
from sigi.apps.utils.decorators import login_required from sigi.apps.utils.decorators import login_required
@ -117,7 +117,7 @@ def categoria_casa_legislativa(request, id_diagnostico):
casa_legislativa = diagnostico.casa_legislativa casa_legislativa = diagnostico.casa_legislativa
if request.method == "POST": if request.method == "POST":
form = CasaLegislativaMobileForm(request.POST, form = OrgaoMobileForm(request.POST,
instance=casa_legislativa) instance=casa_legislativa)
if form.is_valid(): if form.is_valid():
form.save() form.save()
@ -133,7 +133,7 @@ def categoria_casa_legislativa(request, id_diagnostico):
json = simplejson.dumps(resposta) json = simplejson.dumps(resposta)
return HttpResponse(json, content_type='application/json') return HttpResponse(json, content_type='application/json')
else: else:
form = CasaLegislativaMobileForm(instance=casa_legislativa) form = OrgaoMobileForm(instance=casa_legislativa)
context = RequestContext(request, {'form': form, context = RequestContext(request, {'form': form,
'diagnostico': diagnostico, 'casa_legislativa': casa_legislativa}) 'diagnostico': diagnostico, 'casa_legislativa': casa_legislativa})

64
sigi/apps/eventos/admin.py

@ -3,43 +3,47 @@
# sigi.apps.eventos.admin # sigi.apps.eventos.admin
# #
# Copyright (C) 2015 Interlegis # Copyright (C) 2015 Interlegis
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from django.contrib import admin
from django import forms from django import forms
from django.contrib import admin
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from sigi.apps.eventos.models import TipoEvento, Funcao, Evento, Equipe, Convite from sigi.apps.eventos.models import TipoEvento, Funcao, Evento, Equipe, Convite
from sigi.apps.eventos.views import adicionar_eventos_carrinho
class EventoAdminForm(forms.ModelForm): class EventoAdminForm(forms.ModelForm):
class Meta: class Meta:
model = Evento model = Evento
fields = ('tipo_evento', 'nome', 'descricao', 'solicitante', 'data_inicio', 'data_termino', fields = ('tipo_evento', 'nome', 'descricao', 'virtual', 'solicitante',
'casa_anfitria', 'municipio', 'local', 'publico_alvo', 'status', 'data_inicio', 'data_termino', 'carga_horaria',
'data_cancelamento', 'motivo_cancelamento', 'curso_moodle_id', 'casa_anfitria', 'municipio', 'local', 'publico_alvo',
) 'status', 'data_cancelamento', 'motivo_cancelamento', )
def clean(self): def clean(self):
cleaned_data = super(EventoAdminForm, self).clean() cleaned_data = super(EventoAdminForm, self).clean()
data_inicio = cleaned_data.get("data_inicio") data_inicio = cleaned_data.get("data_inicio")
data_termino = cleaned_data.get("data_termino") data_termino = cleaned_data.get("data_termino")
if data_inicio > data_termino: if data_inicio > data_termino:
raise forms.ValidationError(_(u"Data término deve ser posterior à data inicio"), raise forms.ValidationError(
code="invalid_period" ) _(u"Data término deve ser posterior à data inicio"),
code="invalid_period"
)
@admin.register(TipoEvento) @admin.register(TipoEvento)
class TipoEventAdmin(admin.ModelAdmin): class TipoEventAdmin(admin.ModelAdmin):
search_fields = ('nome',) search_fields = ('nome',)
@ -48,24 +52,42 @@ class TipoEventAdmin(admin.ModelAdmin):
class FuncaoAdmin(admin.ModelAdmin): class FuncaoAdmin(admin.ModelAdmin):
list_display = ('nome', 'descricao',) list_display = ('nome', 'descricao',)
search_fields = ('nome', 'descricao',) search_fields = ('nome', 'descricao',)
class EquipeInline(admin.TabularInline): class EquipeInline(admin.TabularInline):
model = Equipe model = Equipe
class ConviteInline(admin.TabularInline): class ConviteInline(admin.TabularInline):
model = Convite model = Convite
raw_id_fields = ('casa',) raw_id_fields = ('casa',)
@admin.register(Evento) @admin.register(Evento)
class EventoAdmin(admin.ModelAdmin): class EventoAdmin(admin.ModelAdmin):
form = EventoAdminForm form = EventoAdminForm
date_hierarchy = 'data_inicio' date_hierarchy = 'data_inicio'
list_display = ('nome', 'tipo_evento', 'status', 'data_inicio', 'data_termino', 'municipio', list_display = ('nome', 'tipo_evento', 'status', 'data_inicio',
'solicitante') 'data_termino', 'municipio', 'solicitante')
list_filter = ('status', 'tipo_evento', 'municipio__uf', 'solicitante') list_filter = ('status', 'tipo_evento', 'virtual', 'municipio__uf',
'solicitante')
raw_id_fields = ('casa_anfitria', 'municipio',) raw_id_fields = ('casa_anfitria', 'municipio',)
search_fields = ('nome', 'tipo_evento__nome', 'casa_anfitria__search_text', search_fields = ('nome', 'tipo_evento__nome', 'casa_anfitria__search_text',
'municipio__search_text', 'solicitante') 'municipio__search_text', 'solicitante')
inlines = (EquipeInline, ConviteInline) inlines = (EquipeInline, ConviteInline)
actions = ['adicionar_eventos', ]
def adicionar_eventos(self, request, queryset):
if 'carrinho_eventos' in request.session:
q1 = len(request.session['carrinho_eventos'])
else:
q1 = 0
response = adicionar_eventos_carrinho(request, queryset=queryset)
q2 = len(request.session['carrinho_eventos'])
quant = q2 - q1
if quant:
self.message_user(request, str(q2 - q1) + " " +
_(u"Eventos adicionados no carrinho"))
else:
self.message_user(request, _(u"Os Eventos selecionados "
u"já foram adicionados anteriormente"))
return HttpResponseRedirect('.')
adicionar_eventos.short_description = _(u"Armazenar eventos no carrinho "
u"para exportar")

18
sigi/apps/eventos/migrations/0004_remove_evento_curso_moodle_id.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('eventos', '0003_auto_20151104_0810'),
]
operations = [
migrations.RemoveField(
model_name='evento',
name='curso_moodle_id',
),
]

27
sigi/apps/eventos/migrations/0005_auto_20210406_1945.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('eventos', '0004_remove_evento_curso_moodle_id'),
('casas', '0014_auto_20210406_1945'),
]
operations = [
migrations.AlterField(
model_name='convite',
name='casa',
field=models.ForeignKey(verbose_name='Casa convidada', to='casas.Orgao'),
preserve_default=True,
),
migrations.AlterField(
model_name='evento',
name='casa_anfitria',
field=models.ForeignKey(verbose_name='Casa anfitri\xe3', blank=True, to='casas.Orgao', null=True),
preserve_default=True,
),
]

57
sigi/apps/eventos/migrations/0006_auto_20210416_0841.py

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('eventos', '0005_auto_20210406_1945'),
]
operations = [
migrations.AlterField(
model_name='convite',
name='casa',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Casa convidada', to='casas.Orgao'),
preserve_default=True,
),
migrations.AlterField(
model_name='convite',
name='servidor',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Servidor que convidou', to='servidores.Servidor'),
preserve_default=True,
),
migrations.AlterField(
model_name='equipe',
name='funcao',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Fun\xe7\xe3o na equipe', to='eventos.Funcao'),
preserve_default=True,
),
migrations.AlterField(
model_name='equipe',
name='membro',
field=models.ForeignKey(related_name='equipe_evento', on_delete=django.db.models.deletion.PROTECT, to='servidores.Servidor'),
preserve_default=True,
),
migrations.AlterField(
model_name='evento',
name='casa_anfitria',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='Casa anfitri\xe3', blank=True, to='casas.Orgao', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='evento',
name='municipio',
field=models.ForeignKey(to='contatos.Municipio', on_delete=django.db.models.deletion.PROTECT),
preserve_default=True,
),
migrations.AlterField(
model_name='evento',
name='tipo_evento',
field=models.ForeignKey(to='eventos.TipoEvento', on_delete=django.db.models.deletion.PROTECT),
preserve_default=True,
),
]

38
sigi/apps/eventos/migrations/0007_auto_20210417_0744.py

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('eventos', '0006_auto_20210416_0841'),
]
operations = [
migrations.AddField(
model_name='convite',
name='nomes_participantes',
field=models.TextField(help_text='Favor colocar um participante por linha', verbose_name='nome dos participantes', blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='convite',
name='qtde_participantes',
field=models.PositiveIntegerField(default=0, verbose_name='n\xfamero de participantes'),
preserve_default=True,
),
migrations.AddField(
model_name='evento',
name='carga_horaria',
field=models.PositiveIntegerField(default=0, verbose_name='carga hor\xe1ria'),
preserve_default=True,
),
migrations.AddField(
model_name='evento',
name='virtual',
field=models.BooleanField(default=False, verbose_name='Virtual'),
preserve_default=True,
),
]

141
sigi/apps/eventos/models.py

@ -1,40 +1,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# sigi.apps.eventos.models
#
# Copyright (C) 2015 Interlegis
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from django.db import models from django.db import models
from django.utils.functional import lazy from django.utils.functional import lazy
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from sigi.apps.casas.models import CasaLegislativa from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import Municipio from sigi.apps.contatos.models import Municipio
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from sigi.apps.utils.moodle_ws_api import get_courses
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from sigi.apps.mdl.models import Course
class TipoEvento(models.Model): class TipoEvento(models.Model):
nome = models.CharField(_(u"Nome"), max_length=100) nome = models.CharField(_(u"Nome"), max_length=100)
class Meta: class Meta:
ordering = ("nome",) ordering = ("nome",)
verbose_name, verbose_name_plural = _(u"Tipo de evento"), _(u"Tipos de evento") verbose_name, verbose_name_plural = _(u"Tipo de evento"), _(u"Tipos de evento")
def __unicode__(self): def __unicode__(self):
return self.nome return self.nome
@ -46,95 +26,120 @@ class Evento(models.Model):
('R', _(u"Realizado")), ('R', _(u"Realizado")),
('C', _(u"Cancelado")) ('C', _(u"Cancelado"))
) )
# def get_course_choices(): tipo_evento = models.ForeignKey(
# result = [(None, u'---------')] TipoEvento,
# on_delete=models.PROTECT,
# try: )
# courses = get_courses(sort_order='categorysortorder', idnumber__startswith='evento')
# result = result + [(c['id'], c['fullname']) for c in courses]
# except Exception as e:
# result.append((None, _(u"Erro ao acessar o saberes: '%s'" % (e.message,))))
#
# return result
def get_course_choices():
from django.apps import apps
if apps.models_ready:
courses = Course.objects.filter(idnumber__startswith='evento')
else:
courses = []
result = [(None, u'---------')] + [(c.id, c.fullname) for c in courses]
return result
tipo_evento = models.ForeignKey(TipoEvento)
nome = models.CharField(_(u"Nome do evento"), max_length=100) nome = models.CharField(_(u"Nome do evento"), max_length=100)
descricao = models.TextField(_(u"Descrição do evento")) descricao = models.TextField(_(u"Descrição do evento"))
virtual = models.BooleanField(_("Virtual"), default=False)
solicitante = models.CharField(_(u"Solicitante"), max_length=100) solicitante = models.CharField(_(u"Solicitante"), max_length=100)
data_inicio = models.DateField(_(u"Data de início")) data_inicio = models.DateField(_(u"Data de início"))
data_termino = models.DateField(_(u"Data de término")) data_termino = models.DateField(_(u"Data de término"))
casa_anfitria = models.ForeignKey(CasaLegislativa, verbose_name=_(u"Casa anfitriã"), blank=True, carga_horaria = models.PositiveIntegerField(
null=True) _(u"carga horária"),
municipio = models.ForeignKey(Municipio) default=0
)
casa_anfitria = models.ForeignKey(
Orgao,
on_delete=models.PROTECT,
verbose_name=_(u"Casa anfitriã"),
blank=True,
null=True
)
municipio = models.ForeignKey(
Municipio,
on_delete=models.PROTECT
)
local = models.TextField(_(u"Local do evento"), blank=True) local = models.TextField(_(u"Local do evento"), blank=True)
publico_alvo = models.TextField(_(u"Público alvo"), blank=True) publico_alvo = models.TextField(_(u"Público alvo"), blank=True)
status = models.CharField(_(u"Status"), max_length=1, choices=STATUS_CHOICES) status = models.CharField(_(u"Status"), max_length=1, choices=STATUS_CHOICES)
data_cancelamento = models.DateField(_(u"Data de cancelamento"), blank=True, null=True) data_cancelamento = models.DateField(_(u"Data de cancelamento"), blank=True, null=True)
motivo_cancelamento = models.TextField(_(u"Motivo do cancelamento"), blank=True) motivo_cancelamento = models.TextField(_(u"Motivo do cancelamento"), blank=True)
curso_moodle_id = models.IntegerField(_(u"Curso saberes"), blank=True, null=True,
choices=lazy(get_course_choices, list)())
class Meta: class Meta:
ordering = ("-data_inicio",) ordering = ("-data_inicio",)
verbose_name, verbose_name_plural = _(u"Evento"), _(u"Eventos") verbose_name, verbose_name_plural = _(u"Evento"), _(u"Eventos")
def __unicode__(self): def __unicode__(self):
return _("%(nome)s (%(tipo_evento)s): de %(data_inicio)s a %(data_termino)s") % dict( return _("%(nome)s (%(tipo_evento)s): de %(data_inicio)s a %(data_termino)s") % dict(
nome=self.nome, nome=self.nome,
tipo_evento=unicode(self.tipo_evento), tipo_evento=unicode(self.tipo_evento),
data_inicio=self.data_inicio, data_inicio=self.data_inicio,
data_termino=self.data_termino) data_termino=self.data_termino)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if self.status != 'C': if self.status != 'C':
self.data_cancelamento = None self.data_cancelamento = None
self.motivo_cancelamento = "" self.motivo_cancelamento = ""
if self.data_inicio > self.data_termino: if self.data_inicio > self.data_termino:
raise ValidationError(_(u"Data de término deve ser posterior à data de início")) raise ValidationError(_(u"Data de término deve ser posterior à data de início"))
return super(Evento, self).save(*args, **kwargs) return super(Evento, self).save(*args, **kwargs)
class Funcao(models.Model): class Funcao(models.Model):
nome = models.CharField(_(u"Função na equipe de evento"), max_length=100) nome = models.CharField(_(u"Função na equipe de evento"), max_length=100)
descricao = models.TextField(_(u"Descrição da função")) descricao = models.TextField(_(u"Descrição da função"))
class Meta: class Meta:
ordering = ("nome",) ordering = ("nome",)
verbose_name, verbose_name_plural = _(u"Função"), _(u"Funções") verbose_name, verbose_name_plural = _(u"Função"), _(u"Funções")
def __unicode__(self): def __unicode__(self):
return self.nome return self.nome
class Equipe(models.Model): class Equipe(models.Model):
evento = models.ForeignKey(Evento) evento = models.ForeignKey(
membro = models.ForeignKey(Servidor, related_name="equipe_evento") Evento,
funcao = models.ForeignKey(Funcao, verbose_name=_(u"Função na equipe")) on_delete=models.CASCADE
)
membro = models.ForeignKey(
Servidor,
on_delete=models.PROTECT,
related_name="equipe_evento"
)
funcao = models.ForeignKey(
Funcao,
on_delete=models.PROTECT,
verbose_name=_(u"Função na equipe")
)
observacoes = models.TextField(_(u"Observações"), blank=True) observacoes = models.TextField(_(u"Observações"), blank=True)
class Meta: class Meta:
ordering = ('evento', 'funcao', 'membro',) ordering = ('evento', 'funcao', 'membro',)
verbose_name, verbose_name_plural = _(u"Membro da equipe"), _(u"Membros da equipe") verbose_name, verbose_name_plural = _(u"Membro da equipe"), _(u"Membros da equipe")
def __unicode__(self): def __unicode__(self):
return u"%s (%s)" % (unicode(self.membro), unicode(self.funcao),) return u"%s (%s)" % (unicode(self.membro), unicode(self.funcao),)
class Convite(models.Model): class Convite(models.Model):
evento = models.ForeignKey(Evento) evento = models.ForeignKey(
casa = models.ForeignKey(CasaLegislativa, verbose_name=_(u"Casa convidada")) Evento,
servidor = models.ForeignKey(Servidor, verbose_name=_(u"Servidor que convidou")) on_delete=models.CASCADE
)
casa = models.ForeignKey(
Orgao,
on_delete=models.PROTECT,
verbose_name=_(u"Casa convidada")
)
servidor = models.ForeignKey(
Servidor,
on_delete=models.PROTECT,
verbose_name=_(u"Servidor que convidou")
)
data_convite = models.DateField(_(u"Data do convite")) data_convite = models.DateField(_(u"Data do convite"))
aceite = models.BooleanField(_("Aceitou o convite"), default=False) aceite = models.BooleanField(_("Aceitou o convite"), default=False)
participou = models.BooleanField(_(u"Participou do evento"), default=False) participou = models.BooleanField(_(u"Participou do evento"), default=False)
qtde_participantes = models.PositiveIntegerField(
_(u"número de participantes"),
default=0
)
nomes_participantes = models.TextField(
_(u"nome dos participantes"),
blank=True,
help_text=_(u"Favor colocar um participante por linha")
)
class Meta: class Meta:
ordering = ('evento', 'casa', '-data_convite') ordering = ('evento', 'casa', '-data_convite')
unique_together = ('evento', 'casa') unique_together = ('evento', 'casa')

1
sigi/apps/eventos/templates/admin/eventos/change_list.html

@ -0,0 +1 @@
{% extends "change_list_with_cart.html" %}

63
sigi/apps/eventos/templates/eventos/carrinho.html

@ -0,0 +1,63 @@
{% extends "admin/carrinho.html" %}
{% load admin_list i18n %}
{% block extrastyle %}
{{ block.super }}
{#% include "admin/tabs_style.html" %#}
{% endblock %}
{% block title %}{% trans 'Eventos no Carrinho | SIGI' %}{% endblock %}
{% block content_title %}<h1>{% trans 'Eventos no Carrinho' %}</h1>{% endblock %}
{% block mensagem%}
<ul class="messagelist">
{%if carIsEmpty%}
<li class="warning">{% trans 'O carrinho está vazio, sendo assim todos os eventos entram na lista para exportação de acordo com os filtros aplicados.' %}</li>
{%else%}
<li>{{paginas.paginator.count}} {% trans 'Eventos no carrinho' %}.</li>
{%endif%}
</ul>
{% endblock %}
{% block action %}deleta_itens_carrinho{% endblock %}
{% block tabela %}
<table class="table table-striped">
<thead class="thead-dark">
<tr>
{%if not carIsEmpty%}
<th><!-- <input type="checkbox" id="action-toggle" style="display: inline;">-->
</th>
{% endif %}
<th>{% trans 'Nome do evento' %}</th>
<th>{% trans 'Tipo evento' %}</th>
<th>{% trans 'Status' %}</th>
<th>{% trans 'Data de início' %}</th>
<th>{% trans 'Data de término' %}</th>
<th>{% trans 'município' %}</th>
<th>{% trans 'Solicitante' %}</th>
</tr>
</thead>
<tbody>
{% for evento in paginas.object_list %}
<tr>
{%if not carIsEmpty%}
<th><input type="checkbox" name="_selected_action"
value="{{evento.id|safe}}" class="action-select" />
</th>
{% endif %}
<td style="text-align: left;">{{evento.nome}}</td>
<td>{{evento.tipo_evento}}</td>
<td>{{evento.get_status_display}}</td>
<td>{{evento.data_inicio}}</td>
<td>{{evento.data_termino}}</td>
<td>{{evento.municipio}}</td>
<td>{{evento.solicitante}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
{% block botoes %}
<a class="btn btn-primary" href="../csv/{{query_str}}">{% trans "Exportar CVS" %}</a>
{% endblock %}

9
sigi/apps/eventos/urls.py

@ -7,4 +7,13 @@ urlpatterns = patterns(
# Painel de ocorrencias # Painel de ocorrencias
url(r'^calendario/$', 'calendario', name='eventos-calendario'), url(r'^calendario/$', 'calendario', name='eventos-calendario'),
url(r'^alocacaoequipe/$', 'alocacao_equipe', name='eventos-alocacaoequipe'), url(r'^alocacaoequipe/$', 'alocacao_equipe', name='eventos-alocacaoequipe'),
# Carrinho
url(r'^evento/carrinho/$', 'visualizar_carrinho',
name='visualizar-carrinho-evento'),
url(r'^evento/carrinho/excluir_carrinho/$', 'excluir_carrinho',
name='excluir-carrinho-evento'), # Error
url(r'^evento/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho',
name='deleta-itens-carrinho-evento'), # Error
url(r'^evento/csv/$', 'export_csv', name='evento-export-csv'), # Error
) )

234
sigi/apps/eventos/views.py

@ -3,17 +3,17 @@
# sigi.apps.eventos.views # sigi.apps.eventos.views
# #
# Copyright (C) 2015 Interlegis # Copyright (C) 2015 Interlegis
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@ -21,11 +21,14 @@
import calendar import calendar
import datetime import datetime
import locale import locale
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.shortcuts import render from django.shortcuts import render
from django.utils import translation from django.utils import translation
from django.utils.translation import ungettext, ugettext as _ from django.utils.translation import ungettext, ugettext as _
from sigi.apps.eventos.models import Evento from sigi.apps.eventos.models import Evento, Equipe, Convite
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from sigi.shortcuts import render_to_pdf from sigi.shortcuts import render_to_pdf
import csv import csv
@ -36,28 +39,28 @@ def calendario(request):
mes_pesquisa = int(request.GET.get('mes', datetime.date.today().month)) mes_pesquisa = int(request.GET.get('mes', datetime.date.today().month))
ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year)) ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year))
formato = request.GET.get('fmt', 'html') formato = request.GET.get('fmt', 'html')
dia1 = datetime.date(ano_pesquisa, mes_pesquisa, 1) dia1 = datetime.date(ano_pesquisa, mes_pesquisa, 1)
mes_anterior = dia1 - datetime.timedelta(days=1) mes_anterior = dia1 - datetime.timedelta(days=1)
mes_seguinte = dia1.replace(day=28) + datetime.timedelta(days=4) # Ugly hack mes_seguinte = dia1.replace(day=28) + datetime.timedelta(days=4) # Ugly hack
mes_seguinte = mes_seguinte.replace(day=1) mes_seguinte = mes_seguinte.replace(day=1)
data = {'mes_pesquisa': mes_pesquisa, 'ano_pesquisa': ano_pesquisa} data = {'mes_pesquisa': mes_pesquisa, 'ano_pesquisa': ano_pesquisa}
if Evento.objects.filter(data_inicio__year=mes_anterior.year, if Evento.objects.filter(data_inicio__year=mes_anterior.year,
data_inicio__month=mes_anterior.month).exists(): data_inicio__month=mes_anterior.month).exists():
data['prev_button'] = {'mes': mes_anterior.month, 'ano': mes_anterior.year } data['prev_button'] = {'mes': mes_anterior.month, 'ano': mes_anterior.year }
if Evento.objects.filter(data_inicio__year=mes_seguinte.year, if Evento.objects.filter(data_inicio__year=mes_seguinte.year,
data_inicio__month=mes_seguinte.month).exists(): data_inicio__month=mes_seguinte.month).exists():
data['next_button'] = {'mes': mes_seguinte.month, 'ano': mes_seguinte.year } data['next_button'] = {'mes': mes_seguinte.month, 'ano': mes_seguinte.year }
c = calendar.Calendar(6) c = calendar.Calendar(6)
dates = reduce(lambda x,y: x+y, c.monthdatescalendar(ano_pesquisa, mes_pesquisa)) dates = reduce(lambda x,y: x+y, c.monthdatescalendar(ano_pesquisa, mes_pesquisa))
eventos = [] eventos = []
for evento in Evento.objects.filter(data_inicio__year=ano_pesquisa, for evento in Evento.objects.filter(data_inicio__year=ano_pesquisa,
data_inicio__month=mes_pesquisa).order_by('data_inicio'): data_inicio__month=mes_pesquisa).order_by('data_inicio'):
start = dates.index(evento.data_inicio) start = dates.index(evento.data_inicio)
if not evento.data_termino in dates: if not evento.data_termino in dates:
@ -75,13 +78,13 @@ def calendario(request):
# Agrupa os eventos em linhas para melhorar a visualização # Agrupa os eventos em linhas para melhorar a visualização
linhas = [] linhas = []
for evento in eventos: for evento in eventos:
encaixado = False encaixado = False
for linha in linhas: for linha in linhas:
sobrepoe = False sobrepoe = False
for e in linha: for e in linha:
if (((evento['evento'].data_inicio >= e['evento'].data_inicio) and if (((evento['evento'].data_inicio >= e['evento'].data_inicio) and
(evento['evento'].data_inicio <= e['evento'].data_termino)) or (evento['evento'].data_inicio <= e['evento'].data_termino)) or
((evento['evento'].data_termino >= e['evento'].data_inicio) and ((evento['evento'].data_termino >= e['evento'].data_inicio) and
(evento['evento'].data_termino <= e['evento'].data_termino))): (evento['evento'].data_termino <= e['evento'].data_termino))):
@ -96,7 +99,7 @@ def calendario(request):
# Adiciona uma nova linha porque este evento não se encaixa em nenhuma existente # Adiciona uma nova linha porque este evento não se encaixa em nenhuma existente
linhas.append([evento]) linhas.append([evento])
# Recalcula as distâncias dos eventos por linha para encaixar no calendário # Recalcula as distâncias dos eventos por linha para encaixar no calendário
for linha in linhas: for linha in linhas:
anterior = None anterior = None
for evento in linha: for evento in linha:
@ -110,27 +113,27 @@ def calendario(request):
data['dates'] = dates data['dates'] = dates
data['eventos'] = eventos data['eventos'] = eventos
data['linhas'] = linhas data['linhas'] = linhas
if formato == 'pdf': if formato == 'pdf':
return render_to_pdf('eventos/calendario_pdf.html', data ) return render_to_pdf('eventos/calendario_pdf.html', data )
return render(request, 'eventos/calendario.html', data) return render(request, 'eventos/calendario.html', data)
@login_required @login_required
def alocacao_equipe(request): def alocacao_equipe(request):
ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year)) ano_pesquisa = int(request.GET.get('ano', datetime.date.today().year))
formato = request.GET.get('fmt', 'html') formato = request.GET.get('fmt', 'html')
data = {'ano_pesquisa': ano_pesquisa} data = {'ano_pesquisa': ano_pesquisa}
if Evento.objects.filter(data_inicio__year=ano_pesquisa-1).exists(): if Evento.objects.filter(data_inicio__year=ano_pesquisa-1).exists():
data['prev_button'] = {'ano': ano_pesquisa - 1 } data['prev_button'] = {'ano': ano_pesquisa - 1 }
if Evento.objects.filter(data_inicio__year=ano_pesquisa+1).exists(): if Evento.objects.filter(data_inicio__year=ano_pesquisa+1).exists():
data['next_button'] = {'ano': ano_pesquisa + 1 } data['next_button'] = {'ano': ano_pesquisa + 1 }
dados = [] dados = []
for evento in Evento.objects.filter(data_inicio__year=ano_pesquisa).exclude(status='C').prefetch_related('equipe_set'): for evento in Evento.objects.filter(data_inicio__year=ano_pesquisa).exclude(status='C').prefetch_related('equipe_set'):
for p in evento.equipe_set.all(): for p in evento.equipe_set.all():
registro = None registro = None
@ -141,36 +144,36 @@ def alocacao_equipe(request):
if not registro: if not registro:
registro = [p.membro.pk, p.membro.nome_completo, [{'dias': 0, 'eventos': 0} for x in range(1,13)]] registro = [p.membro.pk, p.membro.nome_completo, [{'dias': 0, 'eventos': 0} for x in range(1,13)]]
dados.append(registro) dados.append(registro)
registro[2][evento.data_inicio.month-1]['dias'] += (evento.data_termino - evento.data_inicio).days + 1 registro[2][evento.data_inicio.month-1]['dias'] += (evento.data_termino - evento.data_inicio).days + 1
registro[2][evento.data_inicio.month-1]['eventos'] += 1 registro[2][evento.data_inicio.month-1]['eventos'] += 1
dados.sort(lambda x, y: cmp(x[1], y[1])) dados.sort(lambda x, y: cmp(x[1], y[1]))
lang = (translation.to_locale(translation.get_language())+'.utf8').encode() lang = (translation.to_locale(translation.get_language())+'.utf8').encode()
locale.setlocale(locale.LC_ALL, lang) locale.setlocale(locale.LC_ALL, lang)
meses = [calendar.month_name[m] for m in range(1,13)] meses = [calendar.month_name[m] for m in range(1,13)]
linhas = [[_(u"Servidor")] + meses + ['total']] linhas = [[_(u"Servidor")] + meses + ['total']]
for r in dados: for r in dados:
r[2].append(reduce(lambda x,y:{'dias': x['dias'] + y['dias'], r[2].append(reduce(lambda x,y:{'dias': x['dias'] + y['dias'],
'eventos': x['eventos'] + y['eventos']}, r[2])) 'eventos': x['eventos'] + y['eventos']}, r[2]))
linhas.append([r[1]] + linhas.append([r[1]] +
[_(ungettext(u"%(dias)s dia", u"%(dias)s dias", d['dias']) + " em " + [_(ungettext(u"%(dias)s dia", u"%(dias)s dias", d['dias']) + " em " +
ungettext(u"%(eventos)s evento", u"%(eventos)s eventos", d['eventos']) ungettext(u"%(eventos)s evento", u"%(eventos)s eventos", d['eventos'])
) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in r[2]]) ) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in r[2]])
# for registro in Servidor.objects.filter(equipe_evento__evento__data_inicio__year=ano_pesquisa).exclude(equipe_evento__evento__status='C').distinct(): # for registro in Servidor.objects.filter(equipe_evento__evento__data_inicio__year=ano_pesquisa).exclude(equipe_evento__evento__status='C').distinct():
# dados = [{'dias': 0, 'eventos': 0} for x in range(1,13)] # dados = [{'dias': 0, 'eventos': 0} for x in range(1,13)]
# for part in registro.equipe_evento.filter(evento__data_inicio__year=ano_pesquisa).exclude(evento__status='C'): # for part in registro.equipe_evento.filter(evento__data_inicio__year=ano_pesquisa).exclude(evento__status='C'):
# dados[part.evento.data_inicio.month-1]['dias'] += (part.evento.data_termino - # dados[part.evento.data_inicio.month-1]['dias'] += (part.evento.data_termino -
# part.evento.data_inicio).days + 1 # part.evento.data_inicio).days + 1
# dados[part.evento.data_inicio.month-1]['eventos'] += 1 # dados[part.evento.data_inicio.month-1]['eventos'] += 1
# dados.append([registro.nome_completo] + [_(ungettext(u"%(dias)s dia", u"%(dias)s dias", d['dias']) + " em " + ungettext(u"%(eventos)s evento", u"%(eventos)s eventos", d['eventos'])) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in dados]) # dados.append([registro.nome_completo] + [_(ungettext(u"%(dias)s dia", u"%(dias)s dias", d['dias']) + " em " + ungettext(u"%(eventos)s evento", u"%(eventos)s eventos", d['eventos'])) % d if d['dias'] > 0 or d['eventos'] > 0 else '' for d in dados])
data['linhas'] = linhas data['linhas'] = linhas
if formato == 'pdf': if formato == 'pdf':
return render_to_pdf('eventos/alocacao_equipe_pdf.html', data) return render_to_pdf('eventos/alocacao_equipe_pdf.html', data)
elif formato == 'csv': elif formato == 'csv':
@ -187,5 +190,166 @@ def alocacao_equipe(request):
'meses': {m[0]: m[1] for m in zip(meses+['total'], d[2])} 'meses': {m[0]: m[1] for m in zip(meses+['total'], d[2])}
} for d in dados]} } for d in dados]}
return JsonResponse(result) return JsonResponse(result)
return render(request, 'eventos/alocacao_equipe.html', data) return render(request, 'eventos/alocacao_equipe.html', data)
# Views e functions para carrinho de exportação
def query_ordena(qs, o):
from sigi.apps.eventos.admin import EventoAdmin
list_display = EventoAdmin.list_display
order_fields = []
for order_number in o.split('.'):
order_number = int(order_number)
order = ''
if order_number != abs(order_number):
order_number = abs(order_number)
order = '-'
order_fields.append(order + list_display[order_number - 1])
qs = qs.order_by(*order_fields)
return qs
def get_for_qs(get, qs):
kwargs = {}
for k, v in get.iteritems():
if str(k) not in ('page', 'pop', 'q', '_popup', 'o', 'ot'):
kwargs[str(k)] = v
qs = qs.filter(**kwargs)
if 'o' in get:
qs = query_ordena(qs, get['o'])
return qs
def carrinhoOrGet_for_qs(request):
if 'carrinho_eventos' in request.session:
ids = request.session['carrinho_eventos']
qs = Evento.objects.filter(pk__in=ids)
else:
qs = Evento.objects.all()
if request.GET:
qs = get_for_qs(request.GET, qs)
return qs
def adicionar_eventos_carrinho(request, queryset=None, id=None):
if request.method == 'POST':
ids_selecionados = request.POST.getlist('_selected_action')
if 'carrinho_eventos' not in request.session:
request.session['carrinho_eventos'] = ids_selecionados
else:
lista = request.session['carrinho_eventos']
# Verifica se id já não está adicionado
for id in ids_selecionados:
if id not in lista:
lista.append(id)
request.session['carrinho_eventos'] = lista
@login_required
def visualizar_carrinho(request):
qs = carrinhoOrGet_for_qs(request)
paginator = Paginator(qs, 100)
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
try:
paginas = paginator.page(page)
except (EmptyPage, InvalidPage):
paginas = paginator.page(paginator.num_pages)
carrinhoIsEmpty = not('carrinho_eventos' in request.session)
return render(
request,
'eventos/carrinho.html',
{
'carIsEmpty': carrinhoIsEmpty,
'paginas': paginas,
'query_str': '?' + request.META['QUERY_STRING']
}
)
@login_required
def excluir_carrinho(request):
if 'carrinho_eventos' in request.session:
del request.session['carrinho_eventos']
messages.info(request, u'O carrinho foi esvaziado')
return HttpResponseRedirect('../../')
@login_required
def deleta_itens_carrinho(request):
if request.method == 'POST':
ids_selecionados = request.POST.getlist('_selected_action')
removed = 0
if 'carrinho_eventos' in request.session:
lista = request.session['carrinho_eventos']
for item in ids_selecionados:
lista.remove(item)
removed += 1
if lista:
request.session['carrinho_eventos'] = lista
else:
del lista
del request.session['carrinho_eventos']
messages.info(request, u"{0} itens removidos do carrinho".format(removed))
return HttpResponseRedirect('.')
@login_required
def export_csv(request):
def serialize(r, field):
value = (getattr(r, 'get_{0}_display'.format(field.name), None) or
getattr(r, field.name, ""))
if callable(value):
value = value()
if value is None:
value = ""
return unicode(value).encode('utf8')
eventos = carrinhoOrGet_for_qs(request)
eventos.select_related('equipe', 'convite')
if not eventos:
messages.info(request, _(u"Nenhum evento a exportar"))
return HttpResponseRedirect('../')
max_equipe = max([e.equipe_set.count() for e in eventos])
head = [f.verbose_name.encode('utf8') for f in Evento._meta.fields]
head.extend([f.verbose_name.encode('utf8')+"_{0}".format(i+1)
for i in range(max_equipe) for f in Equipe._meta.fields
if f.name not in ('id', 'evento')])
head.extend([f.verbose_name.encode('utf8') for f in Convite._meta.fields
if f.name not in ('id', 'evento')])
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=eventos.csv'
writer = csv.DictWriter(response, fieldnames=head)
writer.writeheader()
for evento in eventos:
reg = {f.verbose_name.encode('utf8'): serialize(evento, f)
for f in Evento._meta.fields}
idx = 1
for membro in evento.equipe_set.all():
reg.update(
{
"{0}_{1}".format(f.verbose_name.encode('utf8'), idx):
serialize(membro, f) for f in Equipe._meta.fields
if f.name not in ('id', 'evento')
}
)
idx += 1
for convite in evento.convite_set.all():
reg.update(
{f.verbose_name.encode('utf8'): serialize(convite, f)
for f in Convite._meta.fields
if f.name not in ('id', 'evento')}
)
writer.writerow(reg)
if evento.convite_set.count() == 0:
writer.writerow(reg)
return response

6
sigi/apps/financeiro/models.py

@ -6,7 +6,11 @@ from sigi.apps.convenios.models import Projeto
class Desembolso(models.Model): class Desembolso(models.Model):
projeto = models.ForeignKey(Projeto, verbose_name=_(u'Projeto')) projeto = models.ForeignKey(
Projeto,
on_delete=models.CASCADE,
verbose_name=_(u'Projeto')
)
descricao = models.CharField(_(u'Descrição da despesa'), max_length=100) descricao = models.CharField(_(u'Descrição da despesa'), max_length=100)
data = models.DateField(_(u'Data do desembolso')) data = models.DateField(_(u'Data do desembolso'))
valor_reais = models.DecimalField(_(u'Valor em R$'), max_digits=18, decimal_places=2) valor_reais = models.DecimalField(_(u'Valor em R$'), max_digits=18, decimal_places=2)

2
sigi/apps/home/templates/home/sem_convenio.html

@ -77,7 +77,7 @@
<tr> <tr>
<td>{{ casa.nome }}</td> <td>{{ casa.nome }}</td>
<td>{{ casa.municipio.uf.sigla }}</td> <td>{{ casa.municipio.uf.sigla }}</td>
<td>{{ casa.gerente_contas.nome_completo }}</td> <td>{{ casa.lista_gerentes }}</td>
<td> <td>
{% for s in casa.servico_set.all %} {% for s in casa.servico_set.all %}
{% if s.data_desativacao == None %} {% if s.data_desativacao == None %}

170
sigi/apps/home/templatetags/menu_conf.yaml

@ -1,6 +1,5 @@
main_menu: main_menu:
- title: Municípios - title: Municípios
url: contatos/municipio/
children: children:
- title: Municípios - title: Municípios
url: contatos/municipio/ url: contatos/municipio/
@ -8,96 +7,43 @@ main_menu:
url: contatos/unidadefederativa/ url: contatos/unidadefederativa/
- title: Mesorregiões - title: Mesorregiões
url: contatos/mesorregiao/ url: contatos/mesorregiao/
- title: Casas Legislativas - title: Casas e órgãos
url: casas/casalegislativa/
children: children:
- title: Todas - title: Todo legislativo
url: casas/casalegislativa/ url: casas/orgao/?tipo__legislativo__exact=1
- title: Câmaras Municipais - title: Câmaras Municipais
url: casas/casalegislativa/?tipo__id__exact=1 url: casas/orgao/?tipo__sigla__exact=CM
- title: Assembléias Legislativas - title: Assembléias Legislativas
url: casas/casalegislativa/?tipo__id__exact=2 url: casas/orgao/?tipo__sigla__exact=AL
- title: Portfólio de relacionamento - title: Demais órgãos
url: casas/portfolio/ url: casas/orgao/?tipo__legislativo__exact=0
- title: Gerência Interlegis
children:
- title: Carteira de relacionamentos - title: Carteira de relacionamentos
url: casas/carteira url: casas/carteira
- title: Tipos de Casas - title: Organizar relacionamentos
url: casas/tipocasalegislativa/ url: casas/portfolio/
- title: Legislaturas - title: Lista de gerentes
url: parlamentares/legislatura/ url: casas/gerentes/
children:
- title: Todas
url: parlamentares/legislatura/
- title: Parlamentares
url: parlamentares/parlamentar/
- title: Tabela de cargos
url: parlamentares/cargo/
- title: Tabela de partidos
url: parlamentares/partido/
- title: Diagnósticos
url: diagnosticos/diagnostico/
children:
- title: Administração
url: diagnosticos/diagnostico/
- title: Coleta de dados
url: diagnosticos/mobile/
- title: Gráficos e estatísticas
url: diagnosticos/graficos
- title: Convênios - title: Convênios
url: convenios/convenio/
children: children:
- title: Convênios - title: Convênios
url: convenios/convenio/ url: convenios/convenio/
- title: Planos diretores - title: Planos diretores
url: metas/planodiretor/ url: metas/planodiretor/
- title: Inventário
url: inventario/bem/
children:
- title: Bens
url: inventario/bem/
- title: Fornecedores
url: inventario/fornecedor/
- title: Equipamentos
url: inventario/equipamento/
- title: Fabricantes
url: inventario/fabricante/
- title: Tipos de equipamentos
url: inventario/tipoequipamento/
- title: Modelos de equipamentos
url: inventario/modeloequipamento/
- title: Servidores
url: servidores/servidor/?user__is_active__exact=1
children:
- title: Pessoal
url: servidores/servidor/?user__is_active__exact=1
- title: Funções
url: servidores/funcao
- title: Férias
url: servidores/ferias/
- title: Licenças
url: servidores/licenca/
- title: Serviços SEIT - title: Serviços SEIT
url: servicos/casaatendida/
children: children:
- title: Tipos de serviço
url: servicos/tiposervico/
- title: Casas atendidas - title: Casas atendidas
url: servicos/casaatendida/ url: servicos/casaatendida/
- title: Lista de serviços - title: Lista de serviços
url: servicos/servico/ url: servicos/servico/
- title: Ocorrências - title: Ocorrências
url: ocorrencias/ocorrencia/?minhas=S&status__in=1,2
children: children:
- title: Painel de ocorrências - title: Painel de ocorrências
url: ocorrencias/painel/ url: ocorrencias/painel/
- title: Registro de ocorrências - title: Registro de ocorrências
url: ocorrencias/ocorrencia/?minhas=S&status__in=1,2 url: ocorrencias/ocorrencia/?minhas=S&status__in=1,2
- title: Tabela de categorias
url: ocorrencias/categoria/
- title: Tipos de contato
url: ocorrencias/tipocontato/
- title: Eventos - title: Eventos
url: eventos/evento
children: children:
- title: Eventos - title: Eventos
url: eventos/evento/ url: eventos/evento/
@ -105,21 +51,81 @@ main_menu:
url: eventos/calendario url: eventos/calendario
- title: Alocação de equipe - title: Alocação de equipe
url: eventos/alocacaoequipe/ url: eventos/alocacaoequipe/
- title: Servidores
children:
- title: Serviços (unidades do ILB)
url: servidores/servico/
- title: Servidores e colaboradores
url: servidores/servidor/
- title: Tabelas auxiliares
children:
- title: Tipos de órgãos
url: casas/tipoorgao/
- title: Acompanhamento convênios
url: convenios/statusconvenio/
- title: Tipos de serviço SEIT
url: servicos/tiposervico/
- title: Categorias de ocorrências
url: ocorrencias/categoria/
- title: Tipos de contato
url: ocorrencias/tipocontato/
- title: Tipos de evento - title: Tipos de evento
url: eventos/tipoevento/ url: eventos/tipoevento/
- title: Funções na equipe - title: Funções na equipe de eventos
url: eventos/funcao/ url: eventos/funcao/
- title: Financeiro
url: financeiro/desembolso/
children: # Removidos
- title: Desembolsos # - title: Legislaturas
url: financeiro/desembolso/ # url: parlamentares/legislatura/
- title: Saberes # children:
url: '/' # - title: Todas
children: # url: parlamentares/legislatura/
- title: Dashboard # - title: Parlamentares
url: saberes/dashboard/ # url: parlamentares/parlamentar/
- title: Cursos sem Tutoria # - title: Tabela de cargos
url: saberes/dashboard/cursos-sem-turoria/ # url: parlamentares/cargo/
- title: Cursos com Tutoria # - title: Tabela de partidos
url: saberes/dashboard/cursos-com-turoria/ # url: parlamentares/partido/
# - title: Diagnósticos
# url: diagnosticos/diagnostico/
# children:
# - title: Administração
# url: diagnosticos/diagnostico/
# - title: Coleta de dados
# url: diagnosticos/mobile/
# - title: Gráficos e estatísticas
# url: diagnosticos/graficos
# - title: Inventário
# url: inventario/bem/
# children:
# - title: Bens
# url: inventario/bem/
# - title: Fornecedores
# url: inventario/fornecedor/
# - title: Equipamentos
# url: inventario/equipamento/
# - title: Fabricantes
# url: inventario/fabricante/
# - title: Tipos de equipamentos
# url: inventario/tipoequipamento/
# - title: Modelos de equipamentos
# url: inventario/modeloequipamento/
# - title: Servidores
# url: servidores/servidor/?user__is_active__exact=1
# children:
# - title: Pessoal
# url: servidores/servidor/?user__is_active__exact=1
# - title: Funções
# url: servidores/funcao
# - title: Férias
# url: servidores/ferias/
# - title: Licenças
# url: servidores/licenca/
# - title: Financeiro
# url: financeiro/desembolso/
# children:
# - title: Desembolsos
# url: financeiro/desembolso/

95
sigi/apps/home/views.py

@ -27,7 +27,7 @@ import calendar
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render, get_object_or_404
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from itertools import cycle from itertools import cycle
from sigi.apps.casas.models import CasaLegislativa from sigi.apps.casas.models import Orgao
from sigi.apps.convenios.models import Convenio, Projeto from sigi.apps.convenios.models import Convenio, Projeto
from sigi.apps.diagnosticos.models import Diagnostico from sigi.apps.diagnosticos.models import Diagnostico
from sigi.apps.metas.models import Meta from sigi.apps.metas.models import Meta
@ -58,7 +58,7 @@ def resumo_convenios(request):
def resumo_seit(request): def resumo_seit(request):
mes = request.GET.get('mes', None) mes = request.GET.get('mes', None)
ano = request.GET.get('ano', None) ano = request.GET.get('ano', None)
try: try:
mes = datetime.date(year=int(ano), month=int(mes), day=1) mes = datetime.date(year=int(ano), month=int(mes), day=1)
tabela_resumo_seit = busca_informacoes_seit(mes) tabela_resumo_seit = busca_informacoes_seit(mes)
@ -73,21 +73,21 @@ def resumo_seit(request):
def chart_seit(request): def chart_seit(request):
mes = request.GET.get('mes', None) mes = request.GET.get('mes', None)
ano = request.GET.get('ano', None) ano = request.GET.get('ano', None)
try: try:
mes = datetime.date(year=int(ano), month=int(mes), day=1) mes = datetime.date(year=int(ano), month=int(mes), day=1)
tabela_resumo_seit = busca_informacoes_seit(mes) tabela_resumo_seit = busca_informacoes_seit(mes)
except: except:
tabela_resumo_seit = busca_informacoes_seit() tabela_resumo_seit = busca_informacoes_seit()
data = { data = {
'type': 'line', 'type': 'line',
'prevlink': reverse('home_chartseit') + ('?ano=%s&mes=%s' % 'prevlink': reverse('home_chartseit') + ('?ano=%s&mes=%s' %
(tabela_resumo_seit['mes_anterior'].year, (tabela_resumo_seit['mes_anterior'].year,
tabela_resumo_seit['mes_anterior'].month)), tabela_resumo_seit['mes_anterior'].month)),
'nextlink': reverse('home_chartseit') + ('?ano=%s&mes=%s' % 'nextlink': reverse('home_chartseit') + ('?ano=%s&mes=%s' %
(tabela_resumo_seit['proximo_mes'].year, (tabela_resumo_seit['proximo_mes'].year,
tabela_resumo_seit['proximo_mes'].month)), tabela_resumo_seit['proximo_mes'].month)),
'options': {'bezierCurve': False, 'datasetFill': False, 'pointDot': False, 'responsive': True}, 'options': {'bezierCurve': False, 'datasetFill': False, 'pointDot': False, 'responsive': True},
'data': { 'data': {
'labels': ['%02d/%s' % (mes.month, mes.year) for mes in reversed(tabela_resumo_seit['meses'])], 'labels': ['%02d/%s' % (mes.month, mes.year) for mes in reversed(tabela_resumo_seit['meses'])],
@ -100,7 +100,7 @@ def chart_seit(request):
for servico in tabela_resumo_seit['servicos']], for servico in tabela_resumo_seit['servicos']],
} }
} }
return JsonResponse(data) return JsonResponse(data)
@never_cache @never_cache
@ -123,15 +123,19 @@ def chart_carteira(request):
colors, highlights = color_palete() colors, highlights = color_palete()
data = {'type': 'pie', data = {'type': 'pie',
'options': {'responsive': True}, 'options': {'responsive': True},
'data': [{'value': r['total_casas'], 'data': [{'value': r['total_casas'],
'color': colors.next(), 'color': colors.next(),
'highlight': highlights.next(), 'highlight': highlights.next(),
'label': Servidor.objects.get(pk=r['gerente_contas']).nome_completo 'label': r['gerentes_interlegis__nome_completo']
} }
for r in CasaLegislativa.objects.all().values('gerente_contas').annotate(total_casas=Count('pk')).order_by('gerente_contas') for r in Orgao.objects.exclude(
gerentes_interlegis=None).values(
'gerentes_interlegis__nome_completo').annotate(
total_casas=Count('pk')).order_by(
'gerentes_interlegis__nome_completo')
] ]
} }
return JsonResponse(data) return JsonResponse(data)
@never_cache @never_cache
@ -140,17 +144,21 @@ def chart_performance(request):
servidor = request.GET.get('servidor', None) servidor = request.GET.get('servidor', None)
if servidor is None: if servidor is None:
casas = CasaLegislativa.objects.exclude(gerente_contas=None) casas = Orgao.objects.exclude(gerentes_interlegis=None)
else: else:
gerente = get_object_or_404(Servidor, pk=servidor) gerente = get_object_or_404(Servidor, pk=servidor)
casas = gerente.casas_que_gerencia casas = gerente.casas_que_gerencia
data = { data = {
'type': 'pie', 'type': 'pie',
'options': {'responsive': True}, 'options': {'responsive': True},
'data': [ 'data': [
{'label': _(u"Utilizam serviços"), 'value': casas.exclude(servico=None).count(), 'color': '#91e8e1'}, {'label': _(u"Utilizam serviços"),
{'label': _(u"Não utilizam serviços"), 'value': casas.filter(servico=None).count(), 'color': '#f7a35c'}, 'value': casas.exclude(servico=None).count(),
'color': '#91e8e1'},
{'label': _(u"Não utilizam serviços"),
'value': casas.filter(servico=None).count(),
'color': '#f7a35c'},
] ]
} }
@ -160,43 +168,52 @@ def chart_performance(request):
@login_required @login_required
def report_sem_convenio(request): def report_sem_convenio(request):
modo = request.GET.get('modo', None) modo = request.GET.get('modo', None)
format = request.GET.get('f', 'pdf') fmt = request.GET.get('f', 'pdf')
sc = sem_convenio() sc = sem_convenio()
if modo == 'H': if modo == 'H':
casas = sc['hospedagem'] casas = sc['hospedagem']
titulo = _(u"Casas sem convenio que utilizam algum serviço de hospedagem") titulo = _(u"Casas sem convenio que utilizam algum serviço de "
u"hospedagem")
elif modo == 'R': elif modo == 'R':
casas = sc['registro'] casas = sc['registro']
titulo = _(u"Casas sem convenio que utilizam somente serviço de registro") titulo = _(u"Casas sem convenio que utilizam somente serviço de "
u"registro")
else: else:
casas = sc['total'] casas = sc['total']
titulo = _(u"Casas sem convenio que utilizam algum serviço de registro e/ou hospedagem") titulo = _(u"Casas sem convenio que utilizam algum serviço de registro "
u"e/ou hospedagem")
if format == 'csv':
if fmt == 'csv':
response = HttpResponse(content_type='text/csv') response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=casas.csv' response['Content-Disposition'] = 'attachment; filename=casas.csv'
writer = csv.writer(response) writer = csv.writer(response)
writer.writerow([titulo.encode('utf8')]) writer.writerow([titulo.encode('utf8')])
writer.writerow([u'']) writer.writerow([u''])
writer.writerow([u'casa', u'uf', u'gerente', u'serviços'.encode('utf8')]) writer.writerow([u'casa', u'uf', u'gerentes',
u'serviços'.encode('utf8')])
for casa in casas: for casa in casas:
writer.writerow([ writer.writerow([
casa.nome.encode('utf8'), casa.nome.encode('utf8'),
casa.municipio.uf.sigla.encode('utf8'), casa.municipio.uf.sigla.encode('utf8'),
casa.gerente_contas.nome_completo.encode('utf8'), casa.lista_gerentes(fmt='lista').encode('utf8'),
(u', '.join(casa.servico_set.filter(data_desativacao__isnull=True).values_list('tipo_servico__nome', flat=True))).encode('utf8'), (u', '.join(casa.servico_set.filter(
data_desativacao__isnull=True).values_list(
'tipo_servico__nome', flat=True))).encode('utf8'),
]) ])
return response return response
elif format == 'json': elif fmt == 'json':
data = { data = {
'titulo': titulo, 'titulo': titulo,
'casas': [ 'casas': [
{'nome': casa.nome, {'nome': casa.nome,
'uf': casa.municipio.uf.sigla, 'uf': casa.municipio.uf.sigla,
'gerente': casa.gerente_contas.nome_completo, 'gerentes': list(casa.gerentes_interlegis.all().values_list(
'servicos': list(casa.servico_set.filter(data_desativacao__isnull=True).values_list('tipo_servico__nome', flat=True))} 'nome_completo', flat=True)),
'servicos': list(casa.servico_set.filter(
data_desativacao__isnull=True).values_list(
'tipo_servico__nome', flat=True))}
for casa in casas for casa in casas
] ]
} }
@ -204,14 +221,14 @@ def report_sem_convenio(request):
else: else:
context = {'casas': casas, 'titulo': titulo} context = {'casas': casas, 'titulo': titulo}
return render_to_pdf('home/sem_convenio.html', context) return render_to_pdf('home/sem_convenio.html', context)
def busca_informacoes_camara(): def busca_informacoes_camara():
""" """
Busca informacoes no banco para montar tabela de resumo de camaras por projeto Busca informacoes no banco para montar tabela de resumo de camaras por projeto
Retorna um dicionario de listas Retorna um dicionario de listas
""" """
camaras = CasaLegislativa.objects.filter(tipo__sigla='CM') camaras = Orgao.objects.filter(tipo__sigla='CM')
convenios = Convenio.objects.filter(casa_legislativa__tipo__sigla='CM') convenios = Convenio.objects.filter(casa_legislativa__tipo__sigla='CM')
projetos = Projeto.objects.all() projetos = Projeto.objects.all()
@ -280,7 +297,7 @@ def busca_informacoes_camara():
# Unindo as duas listass para que o cabecalho da esquerda fique junto com sua # Unindo as duas listass para que o cabecalho da esquerda fique junto com sua
# respectiva linha # respectiva linha
lista_zip = zip(cabecalho_esquerda, linhas) lista_zip = zip(cabecalho_esquerda, linhas)
# Retornando listas em forma de dicionario # Retornando listas em forma de dicionario
return { return {
'cabecalho_topo': cabecalho_topo, 'cabecalho_topo': cabecalho_topo,
@ -292,10 +309,10 @@ def busca_informacoes_camara():
def sem_convenio(): def sem_convenio():
total = CasaLegislativa.objects.exclude(servico=None).filter(servico__data_desativacao=None, convenio=None).order_by('municipio__uf__sigla', 'nome').distinct('municipio__uf__sigla', 'nome') total = Orgao.objects.exclude(servico=None).filter(servico__data_desativacao=None, convenio=None).order_by('municipio__uf__sigla', 'nome').distinct('municipio__uf__sigla', 'nome')
hospedagem = CasaLegislativa.objects.exclude(servico=None).filter(servico__data_desativacao=None, servico__tipo_servico__modo='H', convenio=None).order_by('municipio__uf__sigla', 'nome').distinct('municipio__uf__sigla', 'nome') hospedagem = Orgao.objects.exclude(servico=None).filter(servico__data_desativacao=None, servico__tipo_servico__modo='H', convenio=None).order_by('municipio__uf__sigla', 'nome').distinct('municipio__uf__sigla', 'nome')
reg_keys = set(total.values_list('pk', flat=True)).difference(set(hospedagem.values_list('pk', flat=True))) reg_keys = set(total.values_list('pk', flat=True)).difference(set(hospedagem.values_list('pk', flat=True)))
registro = CasaLegislativa.objects.filter(pk__in=reg_keys).order_by('municipio__uf__sigla', 'nome') registro = Orgao.objects.filter(pk__in=reg_keys).order_by('municipio__uf__sigla', 'nome')
return { return {
'total': total, 'total': total,
'hospedagem': hospedagem, 'hospedagem': hospedagem,
@ -325,13 +342,13 @@ def busca_informacoes_seit(mes_atual=None):
mes_atual = datetime.date.today().replace(day=1) mes_atual = datetime.date.today().replace(day=1)
mes_anterior = mes_atual - datetime.timedelta(days=1) mes_anterior = mes_atual - datetime.timedelta(days=1)
proximo_mes = mes_atual + datetime.timedelta(days=calendar.monthrange(mes_atual.year, mes_atual.month)[1]) proximo_mes = mes_atual + datetime.timedelta(days=calendar.monthrange(mes_atual.year, mes_atual.month)[1])
meses = [] meses = []
mes = mes_atual mes = mes_atual
for i in range(1, 13): for i in range(1, 13):
meses.append(mes) meses.append(mes)
mes = (mes - datetime.timedelta(days=1)).replace(day=1) mes = (mes - datetime.timedelta(days=1)).replace(day=1)
result = { result = {
'mes_atual': mes_atual, 'mes_atual': mes_atual,
'mes_anterior': mes_anterior, 'mes_anterior': mes_anterior,
@ -343,7 +360,7 @@ def busca_informacoes_seit(mes_atual=None):
'Novas casas em %s/%s' % (mes_atual.month, mes_atual.year) 'Novas casas em %s/%s' % (mes_atual.month, mes_atual.year)
], ],
'servicos': [], 'servicos': [],
} }
for tipo_servico in TipoServico.objects.all(): for tipo_servico in TipoServico.objects.all():
por_mes = [] por_mes = []
@ -357,7 +374,7 @@ def busca_informacoes_seit(mes_atual=None):
'novos_mes_anterior': tipo_servico.servico_set.filter(data_ativacao__year=mes_anterior.year, data_ativacao__month=mes_anterior.month).count(), 'novos_mes_anterior': tipo_servico.servico_set.filter(data_ativacao__year=mes_anterior.year, data_ativacao__month=mes_anterior.month).count(),
'novos_mes_atual': tipo_servico.servico_set.filter(data_ativacao__year=mes_atual.year, data_ativacao__month=mes_atual.month).count(), 'novos_mes_atual': tipo_servico.servico_set.filter(data_ativacao__year=mes_atual.year, data_ativacao__month=mes_atual.month).count(),
'novos_por_mes': por_mes, 'novos_por_mes': por_mes,
'cor': colors.next(), 'cor': colors.next(),
} }
) )
@ -393,5 +410,5 @@ def color_palete():
'#B3B6F1', '#B3B6F1',
'#BB9098', '#BB9098',
'#BDF1ED', ]) '#BDF1ED', ])
return (colors, highlights) return (colors, highlights)

21
sigi/apps/inventario/migrations/0002_auto_20210406_1945.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('inventario', '0001_initial'),
('casas', '0014_auto_20210406_1945'),
]
operations = [
migrations.AlterField(
model_name='bem',
name='casa_legislativa',
field=models.ForeignKey(to='casas.Orgao'),
preserve_default=True,
),
]

39
sigi/apps/inventario/migrations/0003_auto_20210416_0841.py

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventario', '0002_auto_20210406_1945'),
]
operations = [
migrations.AlterField(
model_name='bem',
name='fornecedor',
field=models.ForeignKey(to='inventario.Fornecedor', on_delete=django.db.models.deletion.PROTECT),
preserve_default=True,
),
migrations.AlterField(
model_name='equipamento',
name='fabricante',
field=models.ForeignKey(to='inventario.Fabricante', on_delete=django.db.models.deletion.PROTECT),
preserve_default=True,
),
migrations.AlterField(
model_name='equipamento',
name='modelo',
field=models.ForeignKey(to='inventario.ModeloEquipamento', on_delete=django.db.models.deletion.PROTECT),
preserve_default=True,
),
migrations.AlterField(
model_name='modeloequipamento',
name='tipo',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, verbose_name='tipo de equipamento', to='inventario.TipoEquipamento'),
preserve_default=True,
),
]

20
sigi/apps/inventario/models.py

@ -46,6 +46,7 @@ class TipoEquipamento(models.Model):
class ModeloEquipamento(models.Model): class ModeloEquipamento(models.Model):
tipo = models.ForeignKey( tipo = models.ForeignKey(
TipoEquipamento, TipoEquipamento,
on_delete=models.PROTECT,
verbose_name=_(u'tipo de equipamento') verbose_name=_(u'tipo de equipamento')
) )
modelo = models.CharField(max_length=30) modelo = models.CharField(max_length=30)
@ -60,8 +61,14 @@ class ModeloEquipamento(models.Model):
class Equipamento(models.Model): class Equipamento(models.Model):
fabricante = models.ForeignKey(Fabricante) fabricante = models.ForeignKey(
modelo = models.ForeignKey(ModeloEquipamento) Fabricante,
on_delete=models.PROTECT
)
modelo = models.ForeignKey(
ModeloEquipamento,
on_delete=models.PROTECT
)
class Meta: class Meta:
unique_together = (('fabricante', 'modelo'),) unique_together = (('fabricante', 'modelo'),)
@ -72,9 +79,12 @@ class Equipamento(models.Model):
class Bem(models.Model): class Bem(models.Model):
casa_legislativa = models.ForeignKey('casas.CasaLegislativa') casa_legislativa = models.ForeignKey(
equipamento = models.ForeignKey(Equipamento) 'casas.Orgao',
fornecedor = models.ForeignKey(Fornecedor) on_delete=models.CASCADE
)
equipamento = models.ForeignKey(Equipamento, on_delete=models.CASCADE)
fornecedor = models.ForeignKey(Fornecedor, on_delete=models.PROTECT)
num_serie = models.CharField( num_serie = models.CharField(
_(u'número de série'), _(u'número de série'),
max_length=64, max_length=64,

3
sigi/apps/mdl/admin.py

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

6007
sigi/apps/mdl/base_models.py

File diff suppressed because it is too large

116
sigi/apps/mdl/migrations/0001_initial.py

@ -1,116 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='Cohort',
fields=[
],
options={
'db_table': 'mdl_cohort',
'managed': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='CohortMembers',
fields=[
],
options={
'db_table': 'mdl_cohort_members',
'managed': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='Context',
fields=[
],
options={
'db_table': 'mdl_context',
'managed': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='Course',
fields=[
],
options={
'ordering': ['sortorder'],
'db_table': 'mdl_course',
'managed': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='CourseCategories',
fields=[
],
options={
'ordering': ['sortorder'],
'db_table': 'mdl_course_categories',
'managed': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='CourseCompletions',
fields=[
],
options={
'db_table': 'mdl_course_completions',
'managed': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='CourseStats',
fields=[
],
options={
'db_table': 'sigi_course_stats',
'managed': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='Enrol',
fields=[
],
options={
'ordering': ['sortorder'],
'db_table': 'mdl_enrol',
'managed': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='User',
fields=[
],
options={
'db_table': 'mdl_user',
'managed': False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='UserEnrolments',
fields=[
],
options={
'db_table': 'mdl_user_enrolments',
'managed': False,
},
bases=(models.Model,),
),
]

360
sigi/apps/mdl/models.py

@ -1,360 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
class CourseStats(models.Model):
# databaseview: (postgresql dialect):
# -- View: sigi_course_stats
#
# DROP VIEW sigi_course_stats;
#
# CREATE OR REPLACE VIEW sigi_course_stats AS
# SELECT cc.id AS categoryid, c.id AS courseid,
# CASE
# WHEN e.enrol = 'ilbeadtutorado' AND ue.status = 1 THEN 'N' -- Rejeitada
# WHEN e.enrol = 'ilbead' AND ue.timeend > date_part('epoch', now()) THEN 'C' -- Em curso
# WHEN e.enrol = 'ilbead' and ue.timeend < date_part('epoch', now()) and co.timecompleted is null and gg.finalgrade is null then 'L' -- Abandono
# WHEN (co.timestarted = 0 OR co.timestarted IS NULL) AND gg.finalgrade IS NOT NULL THEN 'R' -- Reprovada
# WHEN co.timestarted = 0 OR co.timestarted IS NULL THEN 'L' -- Abandono
# WHEN co.timestarted > 0 AND co.timecompleted IS NULL THEN 'R' -- Reprovado
# WHEN co.timecompleted IS NOT NULL THEN 'A' -- Aprovado
# ELSE 'I' -- Indeterminado
# END AS completionstatus, count(ue.id) AS usercount, avg(gg.finalgrade) as gradeaverage
# FROM mdl_course_categories cc
# JOIN mdl_course c ON c.category = cc.id
# JOIN mdl_enrol e ON e.courseid = c.id
# JOIN mdl_user_enrolments ue ON ue.enrolid = e.id
# JOIN mdl_grade_items gi ON gi.courseid = c.id AND gi.itemtype = 'course'
# LEFT JOIN mdl_grade_grades gg ON gg.itemid = gi.id AND gg.userid = ue.userid
# LEFT JOIN mdl_course_completions co ON co.userid = ue.userid AND co.course = c.id
# GROUP BY cc.id, c.id, completionstatus;
COMPLETIONSTATUS_CHOICES = (
('N', u'Matrículas rejeitadas'),
('C', u'Em curso'),
('R', u'Reprovação'),
('L', u'Abandono'),
('A', u'Aprovação'),
('I', u'Indeterminado'),)
category = models.ForeignKey('CourseCategories', db_column='categoryid', primary_key=True)
course = models.ForeignKey('Course', db_column='courseid')
completionstatus = models.CharField(max_length=1, choices=COMPLETIONSTATUS_CHOICES)
usercount = models.IntegerField()
gradeaverage = models.FloatField()
class Meta:
managed = False
db_table = 'sigi_course_stats'
def __unicode__(self):
return '%s - %s: %s' % (self.category.name, self.course.fullname, self.usercount)
class Cohort(models.Model):
id = models.BigIntegerField(primary_key=True)
context = models.ForeignKey('Context', db_column='contextid')
name = models.CharField(max_length=254)
idnumber = models.CharField(max_length=100, blank=True)
description = models.TextField(blank=True)
descriptionformat = models.SmallIntegerField()
component = models.CharField(max_length=100)
timecreated = models.BigIntegerField()
timemodified = models.BigIntegerField()
visible = models.SmallIntegerField()
# Manytomany
members = models.ManyToManyField('User', through='CohortMembers')
class Meta:
managed = False
db_table = 'mdl_cohort'
def __unicode__(self):
return self.name
class CohortMembers(models.Model):
id = models.BigIntegerField(primary_key=True)
cohort = models.ForeignKey('Cohort', db_column='cohortid')
user = models.ForeignKey('User', db_column='userid')
timeadded = models.BigIntegerField()
class Meta:
managed = False
db_table = 'mdl_cohort_members'
class Context(models.Model):
CONTEXT_SYSTEM = 10 # System context level - only one instance in every system
CONTEXT_USER = 30 # User context level - one instance for each user describing what others can do to user
CONTEXT_COURSECAT = 40 # Course category context level - one instance for each category
CONTEXT_COURSE = 50 # Course context level - one instances for each course
CONTEXT_MODULE = 70 # Course module context level - one instance for each course module
CONTEXT_BLOCK = 80 # Block context level - one instance for each block, sticky blocks are tricky
# because ppl think they should be able to override them at lower contexts.
# Any other context level instance can be parent of block context.
id = models.BigIntegerField(primary_key=True)
contextlevel = models.BigIntegerField()
instanceid = models.BigIntegerField()
path = models.CharField(max_length=255, blank=True)
depth = models.SmallIntegerField()
class Meta:
managed = False
db_table = 'mdl_context'
def __unicode__(self):
return self.path
class Course(models.Model):
id = models.BigIntegerField(primary_key=True)
category = models.ForeignKey('CourseCategories', db_column='category', related_name='courses')
sortorder = models.BigIntegerField()
fullname = models.CharField(max_length=254)
shortname = models.CharField(max_length=255)
idnumber = models.CharField(max_length=100)
summary = models.TextField(blank=True)
format = models.CharField(max_length=21)
showgrades = models.SmallIntegerField()
newsitems = models.IntegerField()
startdate = models.BigIntegerField()
marker = models.BigIntegerField()
maxbytes = models.BigIntegerField()
showreports = models.SmallIntegerField()
visible = models.SmallIntegerField()
groupmode = models.SmallIntegerField()
groupmodeforce = models.SmallIntegerField()
lang = models.CharField(max_length=30)
theme = models.CharField(max_length=50)
timecreated = models.BigIntegerField()
timemodified = models.BigIntegerField()
requested = models.SmallIntegerField()
defaultgroupingid = models.BigIntegerField()
enrolmax = models.BigIntegerField()
enablecompletion = models.SmallIntegerField()
legacyfiles = models.SmallIntegerField()
summaryformat = models.SmallIntegerField()
completionnotify = models.SmallIntegerField()
visibleold = models.SmallIntegerField()
calendartype = models.CharField(max_length=30)
cacherev = models.BigIntegerField()
class Meta:
managed = False
db_table = 'mdl_course'
ordering = ['sortorder', ]
def __unicode__(self):
return self.fullname
def total_alunos(self):
return sum(e.user_enrolments.count() for e in self.enrols.all())
def total_ativos(self):
return sum(e.user_enrolments.filter(status=0).count() for e in self.enrols.all())
def get_matriculas(self):
q = UserEnrolments.objects.none()
for e in self.enrols.all():
q = q | e.user_enrolments.all()
return q
class CourseCategories(models.Model):
id = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=255)
description = models.TextField(blank=True)
parent = models.ForeignKey('CourseCategories', db_column='parent', related_name='children')
sortorder = models.BigIntegerField()
coursecount = models.BigIntegerField()
visible = models.SmallIntegerField()
timemodified = models.BigIntegerField()
depth = models.BigIntegerField()
path = models.CharField(max_length=255)
theme = models.CharField(max_length=50, blank=True)
descriptionformat = models.SmallIntegerField()
visibleold = models.SmallIntegerField()
idnumber = models.CharField(max_length=100, blank=True)
class Meta:
managed = False
db_table = 'mdl_course_categories'
ordering = ['sortorder', ]
def __unicode__(self):
return self.name
def context(self):
return Context.objects.get(instanceid=self.id, contextlevel=Context.CONTEXT_COURSECAT)
def total_turmas(self):
return self.coursecount + sum([c.coursecount for c in self.children.all()])
def total_alunos(self):
total = 0
total = total + sum(c.total_alunos() for c in self.courses.all())
total = total + sum(c.total_alunos() for c in self.children.all())
return total
def cohortids(self):
cids = [c.pk for c in self.context().cohort_set.all()]
for c in self.children.all():
cids = cids + c.cohortids()
return cids
def total_alunos_cohort(self):
return sum([c.members.distinct().count() for c in Cohort.objects.filter(pk__in=self.cohortids())])
def get_all_courses(self, only_visible=False):
if only_visible:
q = self.courses.filter(visible=1)
else:
q = self.courses.all()
for c in self.children.all():
q = q | c.get_all_courses(only_visible=only_visible)
return q
class CourseCompletions(models.Model):
id = models.BigIntegerField(primary_key=True)
user = models.ForeignKey('User', db_column='userid')
course = models.ForeignKey('Course', db_column='course')
timeenrolled = models.BigIntegerField()
timestarted = models.BigIntegerField()
timecompleted = models.BigIntegerField(blank=True, null=True)
reaggregate = models.BigIntegerField()
class Meta:
managed = False
db_table = 'mdl_course_completions'
class Enrol(models.Model):
id = models.BigIntegerField(primary_key=True)
enrol = models.CharField(max_length=20)
status = models.BigIntegerField()
course = models.ForeignKey('Course', db_column='courseid', related_name='enrols')
sortorder = models.BigIntegerField()
name = models.CharField(max_length=255, blank=True)
enrolperiod = models.BigIntegerField(blank=True, null=True)
enrolstartdate = models.BigIntegerField(blank=True, null=True)
enrolenddate = models.BigIntegerField(blank=True, null=True)
expirynotify = models.SmallIntegerField(blank=True, null=True)
expirythreshold = models.BigIntegerField(blank=True, null=True)
notifyall = models.SmallIntegerField(blank=True, null=True)
password = models.CharField(max_length=50, blank=True)
cost = models.CharField(max_length=20, blank=True)
currency = models.CharField(max_length=3, blank=True)
roleid = models.BigIntegerField(blank=True, null=True)
customint1 = models.BigIntegerField(blank=True, null=True)
customint2 = models.BigIntegerField(blank=True, null=True)
customint3 = models.BigIntegerField(blank=True, null=True)
customint4 = models.BigIntegerField(blank=True, null=True)
customchar1 = models.CharField(max_length=255, blank=True)
customchar2 = models.CharField(max_length=255, blank=True)
customdec1 = models.DecimalField(max_digits=12, decimal_places=7, blank=True, null=True)
customdec2 = models.DecimalField(max_digits=12, decimal_places=7, blank=True, null=True)
customtext1 = models.TextField(blank=True)
customtext2 = models.TextField(blank=True)
timecreated = models.BigIntegerField()
timemodified = models.BigIntegerField()
customint5 = models.BigIntegerField(blank=True, null=True)
customint6 = models.BigIntegerField(blank=True, null=True)
customint7 = models.BigIntegerField(blank=True, null=True)
customint8 = models.BigIntegerField(blank=True, null=True)
customchar3 = models.CharField(max_length=1333, blank=True)
customtext3 = models.TextField(blank=True)
customtext4 = models.TextField(blank=True)
class Meta:
managed = False
db_table = 'mdl_enrol'
ordering = ['sortorder', ]
def __unicode__(self):
if not self.name:
return self.enrol
return self.name
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
auth = models.CharField(max_length=20)
confirmed = models.SmallIntegerField()
policyagreed = models.SmallIntegerField()
deleted = models.SmallIntegerField()
mnethostid = models.BigIntegerField()
username = models.CharField(max_length=100)
password = models.CharField(max_length=255)
firstname = models.CharField(max_length=100)
lastname = models.CharField(max_length=100)
email = models.CharField(max_length=100)
emailstop = models.SmallIntegerField()
icq = models.CharField(max_length=15)
skype = models.CharField(max_length=50)
yahoo = models.CharField(max_length=50)
aim = models.CharField(max_length=50)
msn = models.CharField(max_length=50)
phone1 = models.CharField(max_length=20)
phone2 = models.CharField(max_length=20)
institution = models.CharField(max_length=255)
department = models.CharField(max_length=255)
address = models.CharField(max_length=255)
city = models.CharField(max_length=120)
country = models.CharField(max_length=2)
lang = models.CharField(max_length=30)
theme = models.CharField(max_length=50)
timezone = models.CharField(max_length=100)
firstaccess = models.BigIntegerField()
lastaccess = models.BigIntegerField()
lastlogin = models.BigIntegerField()
currentlogin = models.BigIntegerField()
lastip = models.CharField(max_length=45)
secret = models.CharField(max_length=15)
picture = models.BigIntegerField()
url = models.CharField(max_length=255)
description = models.TextField(blank=True)
mailformat = models.SmallIntegerField()
maildigest = models.SmallIntegerField()
maildisplay = models.SmallIntegerField()
autosubscribe = models.SmallIntegerField()
trackforums = models.SmallIntegerField()
timemodified = models.BigIntegerField()
trustbitmask = models.BigIntegerField()
imagealt = models.CharField(max_length=255, blank=True)
idnumber = models.CharField(max_length=255)
descriptionformat = models.SmallIntegerField()
timecreated = models.BigIntegerField()
suspended = models.SmallIntegerField()
lastnamephonetic = models.CharField(max_length=255, blank=True)
firstnamephonetic = models.CharField(max_length=255, blank=True)
middlename = models.CharField(max_length=255, blank=True)
alternatename = models.CharField(max_length=255, blank=True)
calendartype = models.CharField(max_length=30)
class Meta:
managed = False
db_table = 'mdl_user'
def __unicode__(self):
return u'%s %s' % (self.firstname, self.lastname)
class UserEnrolments(models.Model):
id = models.BigIntegerField(primary_key=True)
status = models.BigIntegerField()
enrol = models.ForeignKey('Enrol', db_column='enrolid', related_name='user_enrolments')
user = models.ForeignKey('User', db_column='userid', related_name='Enrolments')
timestart = models.BigIntegerField()
timeend = models.BigIntegerField()
modifierid = models.BigIntegerField()
timecreated = models.BigIntegerField()
timemodified = models.BigIntegerField()
class Meta:
managed = False
db_table = 'mdl_user_enrolments'

3
sigi/apps/mdl/views.py

@ -1,3 +0,0 @@
from django.shortcuts import render
# Create your views here.

21
sigi/apps/metas/migrations/0002_auto_20210406_1945.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('metas', '0001_initial'),
('casas', '0014_auto_20210406_1945'),
]
operations = [
migrations.AlterField(
model_name='planodiretor',
name='casa_legislativa',
field=models.ForeignKey(verbose_name='Casa Legislativa', to='casas.Orgao'),
preserve_default=True,
),
]

21
sigi/apps/metas/models.py

@ -3,7 +3,7 @@ from datetime import date
from django.db import models from django.db import models
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from sigi.apps.casas.models import CasaLegislativa from sigi.apps.casas.models import Orgao
from sigi.apps.convenios.models import Projeto, Convenio from sigi.apps.convenios.models import Projeto, Convenio
from sigi.apps.diagnosticos.models import Diagnostico from sigi.apps.diagnosticos.models import Diagnostico
from sigi.apps.financeiro.models import Desembolso from sigi.apps.financeiro.models import Desembolso
@ -18,7 +18,12 @@ class Meta(models.Model):
('COUNT_PDIR', _(u'Quantidade de planos diretores')), ('COUNT_PDIR', _(u'Quantidade de planos diretores')),
('COUNT_CONV', _(u'Quantidade de casas conveniadas')), ('COUNT_CONV', _(u'Quantidade de casas conveniadas')),
) )
projeto = models.ForeignKey(Projeto, verbose_name=_(u'Projeto'), help_text=_(u'Projeto ao qual a meta se refere')) projeto = models.ForeignKey(
Projeto,
on_delete=models.CASCADE,
verbose_name=_(u'Projeto'),
help_text=_(u'Projeto ao qual a meta se refere')
)
titulo = models.CharField(_(u'Título'), max_length=40, help_text=_(u'Título da meta que aparecerá no dashboard')) titulo = models.CharField(_(u'Título'), max_length=40, help_text=_(u'Título da meta que aparecerá no dashboard'))
descricao = models.TextField(_(u'Descrição')) descricao = models.TextField(_(u'Descrição'))
data_inicio = models.DateField(_(u'Data inicial'), help_text=_(u'Início do período de cômputo da meta')) data_inicio = models.DateField(_(u'Data inicial'), help_text=_(u'Início do período de cômputo da meta'))
@ -114,8 +119,16 @@ class PlanoDiretor(models.Model):
('E', _(u'Entregue')), ('E', _(u'Entregue')),
('I', _(u'Implantado')), ('I', _(u'Implantado')),
) )
projeto = models.ForeignKey(Projeto, verbose_name=_(u'Projeto')) projeto = models.ForeignKey(
casa_legislativa = models.ForeignKey(CasaLegislativa, verbose_name=_(u'Casa Legislativa')) Projeto,
on_delete=models.CASCADE,
verbose_name=_(u'Projeto')
)
casa_legislativa = models.ForeignKey(
Orgao,
on_delete=models.CASCADE,
verbose_name=_(u'Casa Legislativa')
)
casa_legislativa.casa_uf_filter = True casa_legislativa.casa_uf_filter = True
status = models.CharField(_(u'Status'), max_length=1, choices=STATUS_CHOICE, default='E') status = models.CharField(_(u'Status'), max_length=1, choices=STATUS_CHOICE, default='E')
data_entrega = models.DateField(_(u'Data de entrega'), blank=True, null=True) data_entrega = models.DateField(_(u'Data de entrega'), blank=True, null=True)

58
sigi/apps/metas/static/metas/css/openmap.css

@ -0,0 +1,58 @@
body, html, .mapbox, #map {
height: 100%;
}
.filterwrap {
background-color: rgba(255,255,255,0.5);
position: absolute;
top: 0;
left: 0;
z-index: 314159;
height: 100%;
max-height: 100%;
overflow-y: auto;
}
.sigi-logo {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
z-index: 314159;
background-color: transparent;
width: 100%;
text-align: right;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
padding-right: 20px;
}
.sigi-logo h3 {
font-weight: bolder;
margin-bottom: 0px;
}
.sigi-logo a {
pointer-events: auto;
}
.sigi-logo div {
float: right;
}
.sigi-logo img {
margin: 15px;
width: 60px;
height: 60px;
}
.region-ufs {
margin-left: 15px;
}
#search-text {
min-width: 300px;
}
.ui-autocomplete {
max-width: 300px;
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
box-shadow: 0 1px 2px rgba(0,0,0,.05);
border-color: #ddd;
margin-bottom: 20px;
background-color: #fff;
border: 1px solid transparent;
border-radius: 4px;
padding: 15px;
font-size: 10px;
}

93
sigi/apps/metas/templates/metas/lista_casas.html

@ -0,0 +1,93 @@
{% extends "base_report.html" %}
{% load mapa_tags %}
{% load i18n %}
{% block extra_head %}
<style>
table.data, table.data td, table.data th {
border: 1px solid #CCCCCC;
border-collapse: collapse;
font-size: 10px;
padding: 2px;
}
table.filters, table.filters td, table.filters th {
border-bottom: 1px solid #CCCCCC;
font-size: 10px;
padding-top: 3px;
vertical-align: bottom;
text-align: left;
line-height: 16px;
}
table.filters th {
width: 12%;
}
td.nome_uf {
padding: 0 5px !important;
}
ul {
list-style-type: none;
margin: 0px;
padding: 0px;
}
</style>
{% endblock %}
{% block pagesize %}A4 landscape{% endblock pagesize %}
{% block title %}{% trans 'Lista de Casas atendidas' %}{% endblock title %}
{% block report %}
<h1>{% trans 'Lista de Casas atendidas' %}</h1>
<table class="filters">
{% if tipos_orgao %}
<tr><th>{% trans 'Tipos de órgão' %}</th><td>{% for t in tipos_orgao %}{{ t.nome }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if tipos_servico %}
<tr><th>{% trans 'Tipos de serviço' %}</th><td>{% for s in tipos_servico %}{{ s.nome }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if tipos_convenio %}
<tr><th>{% trans 'Tipos de convênio' %}</th><td>{% for c in tipos_convenio %}{{ c.nome }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if gerentes %}
<tr><th>{% trans 'Gerentes Interlegis' %}</th><td>{% for g in gerentes %}{{ g.nome_completo }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if ufs %}
<tr><th>{% trans 'Estados' %}</th><td>{% for uf in ufs %}{{ uf.nome }}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
</table>
<br/>
<table class="data" repeat="1">
<tr>
<th>{% trans 'Casa Legislativa' %}</th>
<th>{% trans 'Estado' %}</th>
<th>{% trans 'Região' %}</th>
<th>{% trans 'Serviços' %}</th>
<th>{% trans 'Convênios' %}</th>
<th>{% trans 'Gerente(s)' %}</th>
</tr>
{% for casa in casas %}
<tr>
<td>{{ casa.nome }}&nbsp;</td>
<td>{{ casa.municipio.uf.nome }}</td>
<td>{{ casa.municipio.uf.get_regiao_display }}</td>
<td><ul>{% for s in casa.servico_set.all %}
{% if s.data_desativacao == None %}
<li>{{ s }}</li>
{% endif %}
{% endfor %}</ul></td>
<td><ul>{% for c in casa.convenio_set.all %}
<li>{{ c }}</li>
{% endfor %}
</ul></td>
<td><ul>{% for g in casa.gerentes_interlegis.all %}
<li>{{ g }}</li>
{% endfor %}</ul>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save