mirror of https://github.com/interlegis/sigi.git
Breno Teixeira
11 years ago
82 changed files with 40534 additions and 0 deletions
@ -0,0 +1,243 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.contrib import admin |
||||
|
from django.contrib.contenttypes import generic |
||||
|
from django.http import HttpResponse, HttpResponseRedirect |
||||
|
|
||||
|
from geraldo.generators import PDFGenerator |
||||
|
|
||||
|
from sigi.apps.casas.forms import CasaLegislativaForm |
||||
|
from sigi.apps.casas.models import CasaLegislativa, Presidente, Funcionario, TipoCasaLegislativa |
||||
|
from sigi.apps.casas.reports import CasasLegislativasLabels, CasasLegislativasReport |
||||
|
from sigi.apps.casas.views import report_complete, labels_report, export_csv, \ |
||||
|
labels_report_sem_presidente, report, \ |
||||
|
adicionar_casas_carrinho |
||||
|
from sigi.apps.utils import queryset_ascii |
||||
|
from sigi.apps.contatos.models import Telefone |
||||
|
from sigi.apps.convenios.models import Projeto, Convenio, EquipamentoPrevisto, Anexo |
||||
|
from sigi.apps.mesas.models import Legislatura |
||||
|
from sigi.apps.diagnosticos.models import Diagnostico |
||||
|
from sigi.apps.inventario.models import Bem |
||||
|
from sigi.apps.servicos.models import Servico |
||||
|
from sigi.apps.metas.models import PlanoDiretor |
||||
|
from sigi.apps.ocorrencias.models import Ocorrencia |
||||
|
|
||||
|
class TelefonesInline(generic.GenericTabularInline): |
||||
|
model = Telefone |
||||
|
readonly_fields = ('ult_alteracao',) |
||||
|
extra = 1 |
||||
|
|
||||
|
class PresidenteInline(admin.StackedInline): |
||||
|
model = Presidente |
||||
|
exclude = ['cargo','funcao'] |
||||
|
readonly_fields = ('ult_alteracao',) |
||||
|
extra = 1 |
||||
|
max_num = 1 |
||||
|
inlines = (TelefonesInline) |
||||
|
|
||||
|
class FuncionariosInline(admin.StackedInline): |
||||
|
model = Funcionario |
||||
|
fieldsets = ((None, { |
||||
|
'fields': (('nome', 'sexo', 'nota', 'email'), ('cargo', 'funcao', 'setor', 'tempo_de_servico'), 'ult_alteracao') |
||||
|
}),) |
||||
|
readonly_fields = ('ult_alteracao',) |
||||
|
extra = 1 |
||||
|
inlines = (TelefonesInline,) |
||||
|
def queryset(self, request): |
||||
|
return self.model.objects.exclude(cargo="Presidente") |
||||
|
|
||||
|
class ConveniosInline(admin.StackedInline): |
||||
|
model = Convenio |
||||
|
fieldsets = ( |
||||
|
(None, {'fields': (('link_convenio', 'num_processo_sf','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_tramitacoes', 'get_anexos', 'get_equipamentos',), |
||||
|
)} |
||||
|
), |
||||
|
) |
||||
|
readonly_fields = ['get_tramitacoes', 'get_anexos', 'get_equipamentos', 'link_convenio',] |
||||
|
extra = 0 |
||||
|
def get_tramitacoes(self, obj): |
||||
|
return '<br/>'.join([t.__unicode__() for t in obj.tramitacao_set.all()]) |
||||
|
get_tramitacoes.short_description = 'Tramitações' |
||||
|
get_tramitacoes.allow_tags = True |
||||
|
|
||||
|
def get_anexos(self, obj): |
||||
|
return '<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 = 'Anexos' |
||||
|
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 = 'Equipamentos previstos' |
||||
|
get_equipamentos.allow_tags = True |
||||
|
|
||||
|
def link_convenio(self, obj): |
||||
|
if obj.pk is None: |
||||
|
return "" |
||||
|
from django.core.urlresolvers import reverse |
||||
|
url = reverse('admin:%s_%s_change' %(obj._meta.app_label, obj._meta.module_name), args=[obj.pk] ) |
||||
|
url = url + '?_popup=1' |
||||
|
return """<input id="edit_convenio-%s" type="hidden"/> |
||||
|
<a id="lookup_edit_convenio-%s" href="%s" class="changelink" onclick="return showRelatedObjectLookupPopup(this)"> |
||||
|
Editar |
||||
|
</a>""" % (obj.pk, obj.pk, url) |
||||
|
|
||||
|
link_convenio.short_description = 'Editar convenio' |
||||
|
link_convenio.allow_tags = True |
||||
|
|
||||
|
class LegislaturaInline(admin.TabularInline): |
||||
|
model = Legislatura |
||||
|
fields = ['numero', 'data_inicio', 'data_fim', 'data_eleicao', 'total_parlamentares', 'link_parlamentares',] |
||||
|
readonly_fields = ['link_parlamentares',] |
||||
|
|
||||
|
def link_parlamentares(self, obj): |
||||
|
if obj.pk is None: |
||||
|
return "" |
||||
|
from django.core.urlresolvers import reverse |
||||
|
url = reverse('admin:%s_%s_change' %(obj._meta.app_label, obj._meta.module_name), args=[obj.pk] ) |
||||
|
url = url + '?_popup=1' |
||||
|
return """<input id="edit_legislatura-%s" type="hidden"/> |
||||
|
<a id="lookup_edit_legislatura-%s" href="%s" class="changelink" onclick="return showRelatedObjectLookupPopup(this)"> |
||||
|
Editar |
||||
|
</a>""" % (obj.pk, obj.pk, url) |
||||
|
|
||||
|
link_parlamentares.short_description = 'Parlamentares' |
||||
|
link_parlamentares.allow_tags = True |
||||
|
|
||||
|
class DiagnosticoInline(admin.TabularInline): |
||||
|
model = Diagnostico |
||||
|
fields = ['data_visita_inicio', 'data_visita_fim', 'publicado', 'data_publicacao', 'responsavel', 'link_diagnostico',] |
||||
|
readonly_fields = ['data_visita_inicio', 'data_visita_fim', 'publicado', 'data_publicacao', 'responsavel', 'link_diagnostico',] |
||||
|
extra = 0 |
||||
|
max_num = 0 |
||||
|
can_delete = False |
||||
|
|
||||
|
def link_diagnostico(self, obj): |
||||
|
if obj.pk is None: |
||||
|
return "" |
||||
|
from django.core.urlresolvers import reverse |
||||
|
url = reverse('admin:%s_%s_change' %(obj._meta.app_label, obj._meta.module_name), args=["%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 = 'Ver PDF' |
||||
|
link_diagnostico.allow_tags = True |
||||
|
|
||||
|
class BemInline(admin.TabularInline): |
||||
|
model = Bem |
||||
|
|
||||
|
class ServicoInline(admin.TabularInline): |
||||
|
model = Servico |
||||
|
fields = ['url', 'contato_tecnico', 'contato_administrativo', 'hospedagem_interlegis', 'data_ativacao', 'data_alteracao', 'data_desativacao'] |
||||
|
readonly_fields = ['url', 'contato_tecnico', 'contato_administrativo', 'hospedagem_interlegis', 'data_ativacao', 'data_alteracao', 'data_desativacao'] |
||||
|
extra = 0 |
||||
|
max_num = 0 |
||||
|
can_delete = False |
||||
|
|
||||
|
class PlanoDiretorInline(admin.TabularInline): |
||||
|
model = PlanoDiretor |
||||
|
|
||||
|
class OcorrenciaInline(admin.TabularInline): |
||||
|
model = Ocorrencia |
||||
|
fields = ('data_criacao', 'assunto', 'prioridade', 'status', 'data_modificacao', 'setor_responsavel',) |
||||
|
readonly_fields = ('data_criacao', 'assunto', 'prioridade', 'status', 'data_modificacao', 'setor_responsavel',) |
||||
|
extra = 0 |
||||
|
max_num = 0 |
||||
|
can_delete = False |
||||
|
|
||||
|
class CasaLegislativaAdmin(admin.ModelAdmin): |
||||
|
form = CasaLegislativaForm |
||||
|
change_form_template = 'casas/change_form.html' |
||||
|
change_list_template = 'casas/change_list.html' |
||||
|
actions = ['adicionar_casas',] |
||||
|
inlines = (TelefonesInline, PresidenteInline, FuncionariosInline, ConveniosInline, LegislaturaInline, |
||||
|
DiagnosticoInline, BemInline, ServicoInline, PlanoDiretorInline, OcorrenciaInline, ) |
||||
|
list_display = ('nome','municipio','logradouro', 'ult_alt_endereco', 'get_convenios') |
||||
|
list_display_links = ('nome',) |
||||
|
list_filter = ('tipo', 'municipio', 'search_text') |
||||
|
ordering = ('nome','municipio__uf') |
||||
|
queyrset = queryset_ascii |
||||
|
fieldsets = ( |
||||
|
(None, { |
||||
|
'fields': ('tipo', 'nome', 'cnpj', 'num_parlamentares') |
||||
|
}), |
||||
|
('Endereço', { |
||||
|
'fields': ('data_instalacao', 'logradouro', 'bairro', |
||||
|
'municipio', 'cep', 'pagina_web','email', 'ult_alt_endereco'), |
||||
|
}), |
||||
|
('Outras informações', { |
||||
|
'classes': ('collapse',), |
||||
|
'fields': ('observacoes', 'foto'), |
||||
|
}), |
||||
|
) |
||||
|
raw_id_fields = ('municipio',) |
||||
|
readonly_fields = ['num_parlamentares',] |
||||
|
search_fields = ('search_text','cnpj', 'bairro', 'logradouro', |
||||
|
'cep', 'municipio__nome', 'municipio__uf__nome', |
||||
|
'municipio__codigo_ibge', 'pagina_web', 'observacoes') |
||||
|
|
||||
|
def get_convenios(self, obj): |
||||
|
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.allow_tags= True |
||||
|
|
||||
|
def changelist_view(self, request, extra_context=None): |
||||
|
return super(CasaLegislativaAdmin, self).changelist_view( |
||||
|
request, |
||||
|
extra_context={'query_str': '?' + request.META['QUERY_STRING']} |
||||
|
) |
||||
|
|
||||
|
def lookup_allowed(self, lookup, value): |
||||
|
return super(CasaLegislativaAdmin, self).lookup_allowed(lookup, value) or \ |
||||
|
lookup in ['municipio__uf__codigo_ibge__exact', 'convenio__projeto__id__exact'] |
||||
|
|
||||
|
|
||||
|
def etiqueta(self,request,queryset): |
||||
|
return labels_report(request,queryset=queryset) |
||||
|
etiqueta.short_description = "Gerar etiqueta(s) da(s) casa(s) selecionada(s)" |
||||
|
|
||||
|
def etiqueta_sem_presidente(self,request,queryset): |
||||
|
return labels_report_sem_presidente(request,queryset=queryset) |
||||
|
etiqueta_sem_presidente.short_description = "Gerar etiqueta(s) sem presidente da(s) casa(s) selecionada(s)" |
||||
|
|
||||
|
def relatorio(self,request,queryset): |
||||
|
return report(request,queryset=queryset) |
||||
|
relatorio.short_description = u"Exportar a(s) casa(s) selecionada(s) para PDF" |
||||
|
|
||||
|
def relatorio_completo(self,request,queryset): |
||||
|
return report_complete(request,queryset=queryset) |
||||
|
relatorio_completo.short_description = u"Gerar relatório completo da(s) casa(s) selecionada(s)" |
||||
|
|
||||
|
def relatorio_csv(self,request,queryset): |
||||
|
return export_csv(request) |
||||
|
relatorio_csv.short_description = u"Exportar casa(s) selecionada(s) para CSV" |
||||
|
|
||||
|
def adicionar_casas(self, request, queryset): |
||||
|
if 'carrinho_casas' in request.session: |
||||
|
#if request.session.has_key('carrinho_casas'): |
||||
|
q1 = len(request.session['carrinho_casas']) |
||||
|
else: |
||||
|
q1 = 0 |
||||
|
response = adicionar_casas_carrinho(request,queryset=queryset) |
||||
|
q2 = len(request.session['carrinho_casas']) |
||||
|
quant = q2 - q1 |
||||
|
if quant: |
||||
|
self.message_user(request,str(q2-q1)+" Casas Legislativas adicionadas no carrinho" ) |
||||
|
else: |
||||
|
self.message_user(request,"As Casas Legislativas selecionadas já foram adicionadas anteriormente" ) |
||||
|
return HttpResponseRedirect('.') |
||||
|
|
||||
|
adicionar_casas.short_description = u"Armazenar casas no carrinho para exportar" |
||||
|
|
||||
|
|
||||
|
def get_actions(self, request): |
||||
|
actions = super(CasaLegislativaAdmin, self).get_actions(request) |
||||
|
if 'delete_selected' in actions: |
||||
|
del actions['delete_selected'] |
||||
|
return actions |
||||
|
|
||||
|
admin.site.register(CasaLegislativa, CasaLegislativaAdmin) |
||||
|
admin.site.register(TipoCasaLegislativa) |
@ -0,0 +1,17 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django import forms |
||||
|
from localflavor.br.forms import BRZipCodeField |
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
|
||||
|
|
||||
|
class CasaLegislativaForm(forms.ModelForm): |
||||
|
#cnpj = BRCNPJField( |
||||
|
# label='CNPJ', |
||||
|
# required=False, |
||||
|
# help_text='Utilize o formato <em>XX.XXX.XXX/XXXX-XX</em> ou ' |
||||
|
# 'insira apenas os dígitos.' |
||||
|
#) |
||||
|
cep = BRZipCodeField(label='CEP', help_text='Formato: <em>XXXXX-XXX</em>.') |
||||
|
|
||||
|
class Meta: |
||||
|
model = CasaLegislativa |
@ -0,0 +1,303 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.db import models |
||||
|
from django.contrib.contenttypes import generic |
||||
|
from sigi.apps.parlamentares.models import Parlamentar |
||||
|
from sigi.apps.utils import SearchField |
||||
|
from datetime import datetime |
||||
|
import random |
||||
|
from unicodedata import normalize |
||||
|
from sigi.apps.contatos.models import Municipio |
||||
|
|
||||
|
class TipoCasaLegislativa(models.Model): |
||||
|
""" Modelo para representar o tipo da Casa Legislativa |
||||
|
|
||||
|
Geralmente: Câmara Municipal, Assembléia Legislativa, |
||||
|
Câmara Distrital ou Legislativo Federal |
||||
|
""" |
||||
|
|
||||
|
sigla = models.CharField( |
||||
|
max_length=5 |
||||
|
) |
||||
|
nome = models.CharField( |
||||
|
max_length=100 |
||||
|
) |
||||
|
def __unicode__(self): |
||||
|
return self.nome |
||||
|
|
||||
|
|
||||
|
class CasaLegislativa(models.Model): |
||||
|
""" Modelo para representar uma Casa Legislativa |
||||
|
""" |
||||
|
nome = models.CharField( |
||||
|
max_length=60, |
||||
|
help_text='Exemplo: <em>Câmara Municipal de Pains</em>.' |
||||
|
) |
||||
|
|
||||
|
# Guarda um campo para ser usado em buscas em caixa baixa e sem acento |
||||
|
search_text = SearchField(field_names=['nome']) |
||||
|
search_text.projeto_filter = True |
||||
|
tipo = models.ForeignKey(TipoCasaLegislativa, verbose_name="Tipo") |
||||
|
cnpj = models.CharField('CNPJ', max_length=32, blank=True) |
||||
|
observacoes = models.TextField(u'observações', blank=True) |
||||
|
# num_parlamentares = models.PositiveIntegerField('Número de parlamentares') |
||||
|
codigo_interlegis = models.CharField('Código Interlegis', max_length=3, blank=True) |
||||
|
codigo_interlegis.ts_filter = True |
||||
|
|
||||
|
# Informações de contato |
||||
|
logradouro = models.CharField( |
||||
|
max_length=100, |
||||
|
help_text='Avenida, rua, praça, jardim, parque...' |
||||
|
) |
||||
|
bairro = models.CharField(max_length=100, blank=True) |
||||
|
municipio = models.ForeignKey( |
||||
|
'contatos.Municipio', |
||||
|
verbose_name='município' |
||||
|
) |
||||
|
municipio.uf_filter = True |
||||
|
cep = models.CharField(max_length=32) |
||||
|
email = models.EmailField('e-mail', max_length=128, blank=True) |
||||
|
pagina_web = models.URLField( |
||||
|
u'página web', |
||||
|
help_text='Exemplo: <em>http://www.camarapains.mg.gov.br</em>.', |
||||
|
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') |
||||
|
|
||||
|
foto = models.ImageField( |
||||
|
upload_to='imagens/casas', |
||||
|
width_field='foto_largura', |
||||
|
height_field='foto_altura', |
||||
|
blank=True |
||||
|
) |
||||
|
foto_largura = 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) |
||||
|
|
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('nome',) |
||||
|
unique_together = ('municipio', 'tipo') |
||||
|
verbose_name = 'Casa Legislativa' |
||||
|
verbose_name_plural = 'Casas Legislativas' |
||||
|
|
||||
|
@property |
||||
|
def num_parlamentares(self): |
||||
|
if not self.legislatura_set.exists(): |
||||
|
return 0 |
||||
|
return self.legislatura_set.latest('data_inicio').total_parlamentares |
||||
|
|
||||
|
@property |
||||
|
def telefone(self): |
||||
|
""" Link para acessar diretamente o primeiro telefone cadastrado da casa |
||||
|
Util para relatorios antigos |
||||
|
""" |
||||
|
telefones = self.telefones.all() |
||||
|
if telefones: |
||||
|
return telefones[0] |
||||
|
return None |
||||
|
|
||||
|
@property |
||||
|
def presidente(self): |
||||
|
""" Link para acessar diretamente o contato do presidente da casa |
||||
|
Util para relatorios antigos |
||||
|
""" |
||||
|
try: |
||||
|
if self.funcionario_set.filter(setor='presidente').count() > 1: |
||||
|
return self.funcionario_set.filter(setor='presidente')[0] |
||||
|
else: |
||||
|
return self.funcionario_set.get(setor='presidente') |
||||
|
except Funcionario.DoesNotExist: |
||||
|
return None |
||||
|
|
||||
|
@property |
||||
|
def total_parlamentares(self): |
||||
|
""" |
||||
|
Calcula o total de parlamentares atual da Casa: |
||||
|
- O total de parlamentares da mesas.legislatura mais recente, ou |
||||
|
- num_parlamentares ou |
||||
|
- 0 se não tiver nenhuma das informações |
||||
|
""" |
||||
|
|
||||
|
if self.legislatura_set.exists(): |
||||
|
return self.legislatura_set.all()[0].total_parlamentares |
||||
|
|
||||
|
if self.num_parlamentares is not None: |
||||
|
return self.num_parlamentares |
||||
|
|
||||
|
return 0 |
||||
|
|
||||
|
def gerarCodigoInterlegis(self): |
||||
|
codigo = self.codigo_interlegis |
||||
|
|
||||
|
if codigo == '': |
||||
|
if self.tipo.sigla == 'AL': # Assembléias são tratadas a parte |
||||
|
codigo = 'A' + self.municipio.uf.sigla |
||||
|
if CasaLegislativa.objects.filter(codigo_interlegis=codigo).count() <= 0: |
||||
|
# Só grava o código se ele for inédito |
||||
|
self.codigo_interlegis = codigo |
||||
|
self.save() |
||||
|
return codigo |
||||
|
# Se já existe, então trata a Assembleia como uma Casa qualquer. |
||||
|
|
||||
|
cityName = normalize('NFKD', unicode(self.municipio.nome)).encode('ascii','ignore') |
||||
|
cityName = cityName.upper().strip() |
||||
|
cityName = cityName.replace(' DA ',' ') |
||||
|
cityName = cityName.replace(' DE ',' ') |
||||
|
cityName = cityName.replace(' DO ',' ') |
||||
|
|
||||
|
# estratégia 1 - Pegar as 1ª letra de cada nome da cidade |
||||
|
codigo = ''.join([x[0] for x in cityName.split(' ')[:3]]) |
||||
|
|
||||
|
# Se o código ficou com menos que três letras, pegar as 2 primeiras |
||||
|
if len(codigo) < 3: |
||||
|
codigo = ''.join([x[0:2] for x in cityName.split(' ')[:3]])[:3] |
||||
|
|
||||
|
# Se ainda ficou com menos de três letras, então o nome da cidade só |
||||
|
# tem uma palavra. Pegue as três primeiras letras da palavra |
||||
|
if len(codigo) < 3: |
||||
|
codigo = cityName[:3] |
||||
|
|
||||
|
# Se o código já existir, substituir a última letra do código pela |
||||
|
# última letra do nome da cidade, e ir recuando, letra a letra, |
||||
|
# até achar um novo código. |
||||
|
|
||||
|
cityName = cityName.replace(' ', '') |
||||
|
ultima = len(cityName) |
||||
|
|
||||
|
while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ |
||||
|
count() > 0 and ultima > 0: |
||||
|
codigo = codigo[:2] + cityName[ultima - 1: ultima] |
||||
|
ultima -= 1 |
||||
|
|
||||
|
# Se usou todas as letras do nome na última posição e ainda assim |
||||
|
# não gerou um código único, então vamos compor o nome usando as |
||||
|
# três primeiras consoantes. |
||||
|
|
||||
|
if CasaLegislativa.objects.filter(codigo_interlegis=codigo).count() > 0: |
||||
|
codigo_cons = cityName.replace('A','').replace('E','').\ |
||||
|
replace('I','').replace('O','').replace('U','')[:3] |
||||
|
if len(codigo_cons) == 3 and \ |
||||
|
CasaLegislativa.objects.filter(codigo_interlegis=codigo).count() > 0: |
||||
|
codigo = codigo_cons |
||||
|
|
||||
|
# Se ainda não gerou um nome único, vamos colocar dígitos no |
||||
|
# último caractere, de A a Z |
||||
|
|
||||
|
i = 'A' |
||||
|
|
||||
|
while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ |
||||
|
count() > 0 and i <= 'Z': |
||||
|
codigo = codigo[:2] + str(i) |
||||
|
i = chr(ord(i) + 1) |
||||
|
|
||||
|
# Se não encontrou, comece a gerar strings com 3 letras aleatórias |
||||
|
# tiradas do nome da cidade, até gerar uma que não existe. Tentar |
||||
|
# 100 vezes apenas |
||||
|
|
||||
|
i = 0 |
||||
|
|
||||
|
while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ |
||||
|
count() > 0 and i < 100: |
||||
|
codigo = random.choice(cityName) + random.choice(cityName) + \ |
||||
|
random.choice(cityName) |
||||
|
i += 1 |
||||
|
|
||||
|
# Caramba! Só resta então gerar o código com 3 letras aleatórias |
||||
|
# quaisquer do alfabeto! |
||||
|
|
||||
|
i = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
||||
|
|
||||
|
while CasaLegislativa.objects.filter(codigo_interlegis=codigo). \ |
||||
|
count() > 0: |
||||
|
codigo = random.choice(i) + random.choice(i) + \ |
||||
|
random.choice(i) |
||||
|
|
||||
|
self.codigo_interlegis = codigo |
||||
|
self.save() |
||||
|
|
||||
|
return codigo |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.nome |
||||
|
|
||||
|
def save(self, *args, **kwargs): |
||||
|
address_changed = False |
||||
|
|
||||
|
if self.pk is not None: |
||||
|
original = CasaLegislativa.objects.get(pk=self.pk) |
||||
|
if (self.logradouro != original.logradouro or |
||||
|
self.bairro != original.bairro or |
||||
|
self.municipio != original.municipio or |
||||
|
self.cep != original.cep): |
||||
|
address_changed = True |
||||
|
else: |
||||
|
address_changed = True |
||||
|
|
||||
|
if address_changed: |
||||
|
self.ult_alt_endereco = datetime.now() |
||||
|
|
||||
|
return super(CasaLegislativa, self).save(*args, **kwargs) |
||||
|
|
||||
|
class Funcionario(models.Model): |
||||
|
""" Modelo para registrar contatos vinculados às |
||||
|
Casas Legislativas |
||||
|
""" |
||||
|
|
||||
|
SETOR_CHOICES = [ |
||||
|
("presidente","Presidente"), |
||||
|
("contato_interlegis","Contato Interlegis"), |
||||
|
("infraestrutura_fisica","Infraestrutura Física"), |
||||
|
("estrutura_de_ti","Estrutura de TI"), |
||||
|
("organizacao_do_processo_legislativo","Organização do Processo Legislativo"), |
||||
|
("producao_legislativa","Produção Legislativa"), |
||||
|
("estrutura_de_comunicacao_social","Estrutura de Comunicação Social"), |
||||
|
("estrutura_de_recursos_humanos","Estrutura de Recursos Humanos"), |
||||
|
("gestao","Gestão"), |
||||
|
("outros","Outros"), |
||||
|
] |
||||
|
SEXO_CHOICES = [ |
||||
|
("M", "Masculino"), |
||||
|
("F", "Feminino") |
||||
|
] |
||||
|
|
||||
|
casa_legislativa = models.ForeignKey(CasaLegislativa) |
||||
|
nome = models.CharField('nome completo', max_length=60, blank=False) |
||||
|
nome.alphabetic_filter = True |
||||
|
sexo = models.CharField(max_length=1, choices=SEXO_CHOICES, default="M") |
||||
|
nota = models.CharField(max_length=70, null=True, blank=True) |
||||
|
email = models.CharField('e-mail', max_length=75, blank=True) |
||||
|
telefones = generic.GenericRelation('contatos.Telefone') |
||||
|
endereco = generic.GenericRelation('contatos.Endereco') |
||||
|
cargo = models.CharField(max_length=100, null=True, blank=True) |
||||
|
funcao = models.CharField(u'função', max_length=100, null=True, blank=True) |
||||
|
setor = models.CharField(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=False) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('nome',) |
||||
|
verbose_name = 'contato Casa Legislativa' |
||||
|
verbose_name_plural = 'contatos Casas Legislativa' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.nome |
||||
|
|
||||
|
class PresidenteManager(models.Manager): |
||||
|
def get_query_set(self): |
||||
|
qs = super(PresidenteManager, self).get_query_set() |
||||
|
qs = qs.filter(setor='presidente') |
||||
|
return qs |
||||
|
|
||||
|
class Presidente(Funcionario): |
||||
|
class Meta: |
||||
|
proxy = True |
||||
|
|
||||
|
objects = PresidenteManager() |
||||
|
|
||||
|
def save(self, *args, **kwargs): |
||||
|
self.setor = 'presidente' |
||||
|
self.cargo = 'Presidente' |
||||
|
self.funcao = 'Presidente' |
||||
|
return super(Presidente, self).save(*args, **kwargs) |
||||
|
|
@ -0,0 +1,574 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from reportlab.lib.pagesizes import A4 |
||||
|
from reportlab.lib.units import cm |
||||
|
from reportlab.lib.enums import TA_CENTER, TA_RIGHT |
||||
|
from geraldo import Report, DetailBand, Label, ObjectValue, ManyElements, \ |
||||
|
ReportGroup, ReportBand, landscape, SubReport, BAND_WIDTH,SystemField |
||||
|
|
||||
|
from sigi.apps.relatorios.reports import ReportDefault |
||||
|
|
||||
|
from geraldo.graphics import Image |
||||
|
|
||||
|
def string_to_cm(texto): |
||||
|
tamanho = 0 |
||||
|
minEspeciais = { |
||||
|
'f':0.1, |
||||
|
'i':0.05, |
||||
|
'j':0.05, |
||||
|
'l':0.05, |
||||
|
'm':0.2, |
||||
|
'r':0.1, |
||||
|
't':0.15, |
||||
|
} |
||||
|
maiuEspeciais = { |
||||
|
'I':0.05, |
||||
|
'J':0.15, |
||||
|
'L':0.15, |
||||
|
'P':0.15, |
||||
|
} |
||||
|
for c in texto: |
||||
|
if c > 'a' and c<'z': |
||||
|
if c in minEspeciais: |
||||
|
tamanho += minEspeciais[c] |
||||
|
else: |
||||
|
tamanho += 0.17 |
||||
|
else: |
||||
|
if c in maiuEspeciais: |
||||
|
tamanho += maiuEspeciais[c] |
||||
|
else: |
||||
|
tamanho += 0.2 |
||||
|
return tamanho |
||||
|
|
||||
|
|
||||
|
|
||||
|
class CasasLegislativasLabels(Report): |
||||
|
""" |
||||
|
Usage example:: |
||||
|
|
||||
|
>>> from geraldo.generators import PDFGenerator |
||||
|
>>> queryset = CasaLegislativa.objects.filter(municipio__uf__sigla='MG') |
||||
|
>>> report = LabelsReport(queryset) |
||||
|
>>> report.generate_by(PDFGenerator, filename='./inline-detail-report.pdf') |
||||
|
|
||||
|
""" |
||||
|
formato = '' |
||||
|
label_margin_top = 0.6 |
||||
|
label_margin_left = 0.2 |
||||
|
label_margin_right = 0.2 |
||||
|
largura_etiqueta = 6.9 |
||||
|
altura_etiqueta = 3.25 |
||||
|
tamanho_fonte = 6 |
||||
|
delta = start = 0.5 |
||||
|
|
||||
|
def __init__(self, queryset, formato): |
||||
|
super(CasasLegislativasLabels, self).__init__(queryset=queryset) |
||||
|
self.formato = formato |
||||
|
self.page_size = A4 |
||||
|
|
||||
|
if formato == '3x9_etiqueta': |
||||
|
self.margin_top = 0.25*cm |
||||
|
self.margin_bottom = 0.0*cm |
||||
|
self.margin_left = 0.2*cm |
||||
|
self.margin_right = 0.0*cm |
||||
|
self.delta = 0.3 |
||||
|
self.start = 0 |
||||
|
self.label_margin_top = 0.35 |
||||
|
self.label_margin_left = 0.4 |
||||
|
self.label_margin_right = 0.2 |
||||
|
else: |
||||
|
self.margin_top = 0.8*cm |
||||
|
self.margin_bottom = 0.8*cm |
||||
|
self.margin_left = 0.4*cm |
||||
|
self.margin_right = 0.4*cm |
||||
|
self.largura_etiqueta = 9.9 |
||||
|
self.altura_etiqueta = 5.6 |
||||
|
self.tamanho_fonte = 11 |
||||
|
self.label_margin_top = 0.5 |
||||
|
self.label_margin_left = 0.5 |
||||
|
self.label_margin_right = 0.5 |
||||
|
|
||||
|
calc_width = (self.largura_etiqueta-self.label_margin_left-self.label_margin_right)*cm |
||||
|
calc_height = lambda rows: (self.delta*rows)*cm |
||||
|
calc_top = lambda row: (self.label_margin_top+row*self.delta)*cm |
||||
|
calc_left = self.label_margin_left*cm |
||||
|
|
||||
|
my_elements = [ |
||||
|
Label( |
||||
|
text='A Sua Excelência o(a) Senhor(a):', |
||||
|
top=calc_top(0), left=calc_left, width=calc_width, |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='presidente', |
||||
|
top=calc_top(1), left=calc_left, width=calc_width, |
||||
|
get_value=lambda instance: |
||||
|
unicode(instance.presidente or "").upper() |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='nome', |
||||
|
top=calc_top(2), left=calc_left, width=calc_width, height=calc_height(2), |
||||
|
get_value=lambda instance: |
||||
|
("Presidente da %s" % instance.nome) |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='logradouro', |
||||
|
top=calc_top(4), left=calc_left, width=calc_width, height=calc_height(2), |
||||
|
get_value=lambda instance: |
||||
|
"%s - %s - %s." % (instance.logradouro, instance.bairro, instance.municipio), |
||||
|
), |
||||
|
|
||||
|
ObjectValue( |
||||
|
attribute_name='cep', |
||||
|
top=calc_top(8), left=calc_left, width=calc_width, |
||||
|
get_value=lambda instance: |
||||
|
"CEP: %s" % instance.cep |
||||
|
), |
||||
|
] |
||||
|
self.band_detail = DetailBand( |
||||
|
width=(self.largura_etiqueta)*cm, |
||||
|
height=(self.altura_etiqueta)*cm, |
||||
|
elements=my_elements, |
||||
|
display_inline=True, |
||||
|
default_style={'fontName': 'Helvetica', 'fontSize': self.tamanho_fonte}) |
||||
|
|
||||
|
|
||||
|
class CasasLegislativasLabelsSemPresidente(CasasLegislativasLabels): |
||||
|
def __init__(self, queryset, formato): |
||||
|
super(CasasLegislativasLabelsSemPresidente, self).__init__(queryset=queryset, formato=formato) |
||||
|
|
||||
|
calc_width = (self.largura_etiqueta-self.label_margin_left-self.label_margin_right)*cm |
||||
|
calc_height = lambda rows: (self.delta*rows)*cm |
||||
|
calc_top = lambda row: (self.label_margin_top+row*self.delta)*cm |
||||
|
calc_left = self.label_margin_left*cm |
||||
|
|
||||
|
my_elements = [ |
||||
|
Label( |
||||
|
text='A Sua Excelência o(a) Senhor(a):', |
||||
|
top=calc_top(0), left=calc_left, width=calc_width, |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='nome', |
||||
|
top=calc_top(1), left=calc_left, width=calc_width, height=calc_height(2), |
||||
|
get_value=lambda instance: |
||||
|
("Presidente da %s" % instance.nome) |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='logradouro', |
||||
|
top=calc_top(3), left=calc_left, width=calc_width, height=calc_height(2), |
||||
|
get_value=lambda instance: |
||||
|
"%s - %s - %s." % (instance.logradouro, instance.bairro, instance.municipio), |
||||
|
), |
||||
|
|
||||
|
ObjectValue( |
||||
|
attribute_name='cep', |
||||
|
top=calc_top(8), left=calc_left, width=calc_width, |
||||
|
get_value=lambda instance: |
||||
|
"CEP: %s" % instance.cep |
||||
|
), |
||||
|
] |
||||
|
self.band_detail = DetailBand( |
||||
|
width=(self.largura_etiqueta)*cm, |
||||
|
height=(self.altura_etiqueta)*cm, |
||||
|
elements=my_elements, |
||||
|
display_inline=True, |
||||
|
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= ReportDefault.band_page_header.BASE_DIR + '/media/images/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= ReportDefault.band_page_header.BASE_DIR + '/media/images/logo-senado.png', |
||||
|
left=1*cm,right=1*cm,top=0.1*cm,bottom=1*cm, |
||||
|
width=3*cm,height=3*cm, |
||||
|
), |
||||
|
Label(text="SENADO FEDERAL",top=1*cm,left=0,width=BAND_WIDTH, |
||||
|
style={'fontName': 'Helvetica-Bold','fontSize':14, 'alignment': TA_CENTER} |
||||
|
), |
||||
|
Label(text="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="UF", |
||||
|
left=label_left[0]*cm, |
||||
|
top=label_top, |
||||
|
), |
||||
|
Label( |
||||
|
text="Municipio", |
||||
|
left=label_left[1]*cm, |
||||
|
top=label_top, |
||||
|
), |
||||
|
Label( |
||||
|
text="Presidente", |
||||
|
left=label_left[2]*cm, |
||||
|
top=label_top, |
||||
|
), |
||||
|
Label( |
||||
|
text="Endereço", |
||||
|
left=label_left[3]*cm, |
||||
|
top=label_top, |
||||
|
), |
||||
|
Label( |
||||
|
text="Endereço na Internet", |
||||
|
left=label_left[4]*cm, |
||||
|
top=label_top, |
||||
|
), |
||||
|
Label( |
||||
|
text="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="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="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': 'Sul','SD': 'Sudeste','CO': 'Centro-Oeste','NE': 'Nordeste','NO': 'Norte',} |
||||
|
[instance.municipio.uf.regiao] |
||||
|
), |
||||
|
Label( |
||||
|
text="U.F.: ", |
||||
|
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="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="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="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="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="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="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="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="Telefone(s)", |
||||
|
style = {'fontSize':14,'alignment': TA_CENTER}, |
||||
|
width=BAND_WIDTH, |
||||
|
top=1*cm, |
||||
|
), |
||||
|
Label(text="Número",left=tel_left[0]*cm,top=tel_top), |
||||
|
Label(text="Tipo",left=tel_left[1]*cm,top=tel_top), |
||||
|
Label(text="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':'Fixo','M':u'Móvel','X':'Fax','I':'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="Contato(s)", |
||||
|
style = {'fontSize':14,'alignment': TA_CENTER}, |
||||
|
width=BAND_WIDTH, |
||||
|
top=1*cm, |
||||
|
), |
||||
|
Label(text="Nome",left=cont_left[0]*cm,top=cont_top), |
||||
|
Label(text="Nota",left=cont_left[1]*cm,top=cont_top), |
||||
|
Label(text="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="Convênio(s)", |
||||
|
style = {'fontSize':14,'alignment': TA_CENTER}, |
||||
|
width=BAND_WIDTH, |
||||
|
top=1*cm, |
||||
|
), |
||||
|
Label(text="Projeto",left=convenio_left[0]*cm,top=convenio_top), |
||||
|
Label(text="Nº Convenio",left=convenio_left[1]*cm,top=convenio_top), |
||||
|
Label(text="Nº Processo SF",left=convenio_left[2]*cm,top=convenio_top), |
||||
|
Label(text="Adesão",left=convenio_left[3]*cm,top=convenio_top), |
||||
|
Label(text="Convênio",left=convenio_left[4]*cm,top=convenio_top), |
||||
|
Label(text="Equipada",left=convenio_left[5]*cm,top=convenio_top), |
||||
|
Label(text="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 != 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 != 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 != 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 != None else '-' |
||||
|
), |
||||
|
], |
||||
|
#borders = {'all':True}, |
||||
|
), |
||||
|
) |
||||
|
] |
||||
|
|
||||
|
|
@ -0,0 +1,234 @@ |
|||||
|
{% extends "admin/carrinho.html" %} |
||||
|
{% load admin_list i18n %} |
||||
|
{% block extrastyle %} |
||||
|
{{ block.super }} |
||||
|
{% include "admin/tabs_style.html" %} |
||||
|
|
||||
|
|
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block title %}Casas legislativas no Carrinho | SIGI{% endblock %} |
||||
|
{% block content_title %}<h1>Casas Legislativas no Carrinho</h1>{% endblock %} |
||||
|
|
||||
|
{% block mensagem%} |
||||
|
<ul class="messagelist"> |
||||
|
{%if carIsEmpty%} |
||||
|
<li class="warning">O carrinho está vazio, sendo assim todas as casas entram na lista para exportação de acordo com os filtros aplicados.</li> |
||||
|
{%else%} |
||||
|
<li>{{paginas.paginator.count}} Casas Legislativas no carrinho.</li> |
||||
|
{%endif%} |
||||
|
</ul> |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block action %}deleta_itens_carrinho{% endblock %} |
||||
|
|
||||
|
{% block tabela %} |
||||
|
<table> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
{%if not carIsEmpty%} |
||||
|
<th class="sorted ascending"><!-- <input type="checkbox" id="action-toggle" style="display: inline;">--> |
||||
|
</th> |
||||
|
{% endif %} |
||||
|
<th class="sorted ascending">Nome</th> |
||||
|
<th class="sorted ascending">Município</th> |
||||
|
<th class="sorted ascending">Presidente</th> |
||||
|
<th class="sorted ascending">Endereço</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
{% for casa in paginas.object_list %} |
||||
|
<tr class="{% cycle 'row1' 'row2' %}"> |
||||
|
{%if not carIsEmpty%} |
||||
|
<th><input type="checkbox" name="_selected_action" |
||||
|
value="{{casa.id}}" class="action-select" /></th> |
||||
|
{% endif %} |
||||
|
<td style="text-align: left;">{{casa.nome}}</td> |
||||
|
<td>{{casa.municipio}}</td> |
||||
|
<td>{{casa.presidente|default_if_none:""}}</td> |
||||
|
<td>{{casa.logradouro}}</td> |
||||
|
</tr> |
||||
|
{% endfor %} |
||||
|
</tbody> |
||||
|
</table> |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block botoes %} |
||||
|
<div id="tabs"> |
||||
|
<ul> |
||||
|
<li><a href="#tabs-1">Etiqueta</a></li> |
||||
|
<li><a href="#tabs-2">Relatório</a></li> |
||||
|
<li><a href="#tabs-3">Arquivo CSV (Excel, Calc)</a></li> |
||||
|
<li><a href="#tabs-4">Etiqueta Parlamentares</a></li> |
||||
|
</ul> |
||||
|
|
||||
|
<div id="tabs-1"> |
||||
|
<form action="../labels/{{query_str}}" method="post"> |
||||
|
<fieldset><legend>Tipo de etiqueta</legend> |
||||
|
<ul class="tabs-conteudo"> |
||||
|
<li><input type="radio" name="tipo_etiqueta" |
||||
|
value="com_presidente"><label>Com Presidente</label></li> |
||||
|
<li><input type="radio" name="tipo_etiqueta" |
||||
|
value="sem_presidente" checked="checked"> |
||||
|
<label>Sem Presidente</label></li> |
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
<fieldset><legend>Formato da Etiqueta</legend> |
||||
|
<ul class="formato_etiqueta"> |
||||
|
<li><input type="radio" name="tamanho_etiqueta" |
||||
|
value="2x5_etiqueta"><label>2x5</label></li> |
||||
|
<li><input type="radio" name="tamanho_etiqueta" |
||||
|
value="3x9_etiqueta" checked="checked"><label>3x9</label></li> |
||||
|
|
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
<ul class="botoes"> |
||||
|
<li><input type="submit" value="Gerar Etiqueta" /></li> |
||||
|
</ul> |
||||
|
</form> |
||||
|
|
||||
|
</div> |
||||
|
<div id="tabs-2"> |
||||
|
<form action="../reports/{{query_str}}" method="post"> |
||||
|
<fieldset><legend>Tipo de relatório</legend> |
||||
|
<ul class="tabs-conteudo"> |
||||
|
<li><input type="radio" name="tipo_relatorio" value="simples" |
||||
|
checked="checked"><label>Simples</label></li> |
||||
|
<li><input type="radio" name="tipo_relatorio" value="completo"><label>Completo</label></li> |
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
<ul class="botoes"> |
||||
|
<li><input type="submit" value="Gerar Relatório" /></li> |
||||
|
</ul> |
||||
|
</form> |
||||
|
</div> |
||||
|
<div id="tabs-3"> |
||||
|
<form action="../csv/{{query_str}}" method="post"> |
||||
|
<fieldset><legend>Escolha os atributos para exportar</legend> |
||||
|
<ul id="sortable" class="tabs-conteudo"> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" value="CNPJ" |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>CNPJ</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Código IBGE" class="action-select" checked="checked" /> |
||||
|
<label>Código IBGE</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Código TSE" class="action-select" checked="checked" /> |
||||
|
<label>Código TSE</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" value="Nome" |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>Nome</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Município" class="action-select" checked="checked" /> |
||||
|
<label>Município</label></li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Presidente" class="action-select" checked="checked" /> |
||||
|
<label>Presidente</label></li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Logradouro" class="action-select" checked="checked" /> |
||||
|
<label>Endereço</label></li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Bairro" class="action-select" checked="checked" /> |
||||
|
<label>Bairro</label></li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" value="CEP" |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>CEP</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Telefone" class="action-select" checked="checked" /> |
||||
|
<label>Telefone</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Página web" class="action-select" checked="checked" /> |
||||
|
<label>Página Web</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Email" class="action-select" checked="checked" /> |
||||
|
<label>Email</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Número de parlamentares" class="action-select" checked="checked" /> |
||||
|
<label>Número de parlamentares</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Última alteração de endereco" class="action-select" checked="checked" /> |
||||
|
<label>Data da última alteração de endereço</label> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
|
||||
|
<fieldset><legend>Contato Interlegis</legend> |
||||
|
<ul id="sortable" class="tabs-conteudo"> |
||||
|
<li><span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Nome contato" class="action-select" checked="checked" /> |
||||
|
<label>Nome</label> |
||||
|
</li> |
||||
|
<li><span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Cargo contato" class="action-select" checked="checked" /> |
||||
|
<label>Cargo</label> |
||||
|
</li> |
||||
|
<li><span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" |
||||
|
value="Email contato" class="action-select" checked="checked" /> |
||||
|
<label>Email</label> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
<ul class="botoes"> |
||||
|
<li><input type="submit" value="Exportar CSV" /></li> |
||||
|
</ul> |
||||
|
</form> |
||||
|
</div> |
||||
|
<div id="tabs-4"> |
||||
|
<form action="../labels_parlamentar/{{query_str}}" method="post"> |
||||
|
<fieldset><legend>Formato da Etiqueta</legend> |
||||
|
<ul class="formato_etiqueta"> |
||||
|
<li><input type="radio" name="tamanho_etiqueta" |
||||
|
value="2x5_etiqueta"><label>2x5</label></li> |
||||
|
<li><input type="radio" name="tamanho_etiqueta" |
||||
|
value="3x9_etiqueta" checked="checked"><label>3x9</label></li> |
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
<ul class="botoes"> |
||||
|
<li><input type="submit" value="Gerar Etiqueta" /></li> |
||||
|
</ul> |
||||
|
</form> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
{% endblock %} |
@ -0,0 +1,14 @@ |
|||||
|
{% extends "admin/change_form.html" %} |
||||
|
{% load i18n reporting_tags %} |
||||
|
|
||||
|
{% block object-tools %} |
||||
|
{% if change %}{% if not is_popup %} |
||||
|
<ul class="object-tools"> |
||||
|
<li><a href="report_complete/">Relatório</a></li> |
||||
|
<li><a href="labels/">Etiqueta</a></li> |
||||
|
<li><a href="labels_sem_presidente/">Etiqueta sem presidente</a></li> |
||||
|
<li><a href="history/" class="historylink">{% trans "History" %}</a></li> |
||||
|
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%} |
||||
|
</ul> |
||||
|
{% endif %}{% endif %} |
||||
|
{% endblock %} |
@ -0,0 +1,15 @@ |
|||||
|
{% extends "admin/change_list.html" %} |
||||
|
{% load admin_list i18n reporting_tags %} |
||||
|
|
||||
|
{% block object-tools %} |
||||
|
<ul class="object-tools"> |
||||
|
<li><a href="casas_sem_convenio_report/{{query_str}}">Casas sem Processo de Convênio</a></li> |
||||
|
<li><a onclick="return showRelatedObjectLookupPopup(this);" href="carrinho/{{query_str}}">Carrinho / Exportar</a></li> |
||||
|
<li> |
||||
|
<a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink"> |
||||
|
{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %} |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
|
||||
|
{% endblock %} |
@ -0,0 +1,377 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.http import HttpResponse, HttpResponseRedirect |
||||
|
from django.shortcuts import render_to_response |
||||
|
from geraldo.generators import PDFGenerator |
||||
|
|
||||
|
from sigi.apps.casas.models import CasaLegislativa, Funcionario |
||||
|
from sigi.apps.casas.reports import CasasLegislativasLabels |
||||
|
from sigi.apps.casas.reports import CasasLegislativasLabelsSemPresidente |
||||
|
from sigi.apps.casas.reports import CasasLegislativasReport |
||||
|
from sigi.apps.casas.reports import CasasSemConvenioReport |
||||
|
from sigi.apps.casas.reports import InfoCasaLegislativa |
||||
|
from sigi.apps.parlamentares.models import Parlamentar |
||||
|
from sigi.apps.parlamentares.reports import ParlamentaresLabels |
||||
|
|
||||
|
from django.core.paginator import Paginator, InvalidPage, EmptyPage |
||||
|
|
||||
|
from django.conf import settings |
||||
|
|
||||
|
import csv |
||||
|
|
||||
|
def query_ordena(qs,o,ot): |
||||
|
list_display = ('nome','municipio','logradouro') |
||||
|
|
||||
|
aux = list_display[(int(o)-1)] |
||||
|
if ot =='asc': |
||||
|
qs = qs.order_by(aux) |
||||
|
else: |
||||
|
qs = qs.order_by("-"+aux) |
||||
|
return qs |
||||
|
|
||||
|
def get_for_qs(get,qs): |
||||
|
""" |
||||
|
Verifica atributos do GET e retorna queryset correspondente |
||||
|
""" |
||||
|
kwargs = {} |
||||
|
for k,v in get.iteritems(): |
||||
|
if not (k == 'page' or k == 'pop' or k == 'q'): |
||||
|
if not k == 'o': |
||||
|
if k == "ot": |
||||
|
qs = query_ordena(qs,get["o"],get["ot"]) |
||||
|
else: |
||||
|
kwargs[str(k)] = v |
||||
|
qs = qs.filter(**kwargs) |
||||
|
return qs |
||||
|
|
||||
|
def carrinhoOrGet_for_qs(request): |
||||
|
""" |
||||
|
Verifica se existe casas na sessão se não verifica get e retorna qs correspondente. |
||||
|
""" |
||||
|
if request.session.has_key('carrinho_casas'): |
||||
|
ids = request.session['carrinho_casas'] |
||||
|
qs = CasaLegislativa.objects.filter(pk__in=ids) |
||||
|
else: |
||||
|
qs = CasaLegislativa.objects.all() |
||||
|
if request.GET: |
||||
|
qs = get_for_qs(request.GET,qs) |
||||
|
return qs |
||||
|
|
||||
|
def adicionar_casas_carrinho(request,queryset=None,id=None): |
||||
|
if request.method == 'POST': |
||||
|
ids_selecionados = request.POST.getlist('_selected_action') |
||||
|
if not request.session.has_key('carrinho_casas'): |
||||
|
request.session['carrinho_casas'] = ids_selecionados |
||||
|
else: |
||||
|
lista = request.session['carrinho_casas'] |
||||
|
# Verifica se id já não está adicionado |
||||
|
for id in ids_selecionados: |
||||
|
if not id in lista: |
||||
|
lista.append(id) |
||||
|
request.session['carrinho_casas'] = lista |
||||
|
|
||||
|
|
||||
|
|
||||
|
def visualizar_carrinho(request): |
||||
|
|
||||
|
qs = carrinhoOrGet_for_qs(request) |
||||
|
|
||||
|
paginator = Paginator(qs, 100) |
||||
|
|
||||
|
# Make sure page request is an int. If not, deliver first page. |
||||
|
# Esteja certo de que o `page request` é um inteiro. Se não, mostre a primeira página. |
||||
|
try: |
||||
|
page = int(request.GET.get('page', '1')) |
||||
|
except ValueError: |
||||
|
page = 1 |
||||
|
|
||||
|
# Se o page request (9999) está fora da lista, mostre a última página. |
||||
|
try: |
||||
|
paginas = paginator.page(page) |
||||
|
except (EmptyPage, InvalidPage): |
||||
|
paginas = paginator.page(paginator.num_pages) |
||||
|
|
||||
|
carrinhoIsEmpty = not(request.session.has_key('carrinho_casas')) |
||||
|
|
||||
|
return render_to_response( |
||||
|
'casas/carrinho.html', |
||||
|
{ |
||||
|
"ADMIN_MEDIA_PREFIX":settings.ADMIN_MEDIA_PREFIX, |
||||
|
'MEDIA_URL':settings.MEDIA_URL, |
||||
|
'carIsEmpty':carrinhoIsEmpty, |
||||
|
'paginas':paginas, |
||||
|
'query_str':'?'+request.META['QUERY_STRING'] |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
def excluir_carrinho(request): |
||||
|
if request.session.has_key('carrinho_casas'): |
||||
|
del request.session['carrinho_casas'] |
||||
|
return HttpResponseRedirect('.') |
||||
|
|
||||
|
def deleta_itens_carrinho(request): |
||||
|
if request.method == 'POST': |
||||
|
ids_selecionados = request.POST.getlist('_selected_action') |
||||
|
if request.session.has_key('carrinho_casas'): |
||||
|
lista = request.session['carrinho_casas'] |
||||
|
for item in ids_selecionados: |
||||
|
lista.remove(item) |
||||
|
if lista: |
||||
|
request.session['carrinho_casas'] = lista |
||||
|
else: |
||||
|
del lista; |
||||
|
del request.session['carrinho_casas'] |
||||
|
|
||||
|
return HttpResponseRedirect('.') |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
def labels_report(request, id=None, tipo=None, formato='3x9_etiqueta'): |
||||
|
""" TODO: adicionar suporte para resultado de pesquisa do admin. |
||||
|
""" |
||||
|
|
||||
|
if request.POST: |
||||
|
if request.POST.has_key('tipo_etiqueta'): |
||||
|
tipo = request.POST['tipo_etiqueta'] |
||||
|
if request.POST.has_key('tamanho_etiqueta'): |
||||
|
formato = request.POST['tamanho_etiqueta'] |
||||
|
|
||||
|
if tipo =='sem_presidente': |
||||
|
return labels_report_sem_presidente(request, id, formato) |
||||
|
|
||||
|
if id: |
||||
|
qs = CasaLegislativa.objects.filter(pk=id) |
||||
|
else: |
||||
|
qs = carrinhoOrGet_for_qs(request) |
||||
|
|
||||
|
if not qs: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
response['Content-Disposition'] = 'attachment; filename=casas.pdf' |
||||
|
report = CasasLegislativasLabels(queryset=qs, formato=formato) |
||||
|
report.generate_by(PDFGenerator, filename=response) |
||||
|
|
||||
|
return response |
||||
|
|
||||
|
def labels_report_parlamentar(request, id=None, formato='3x9_etiqueta'): |
||||
|
""" TODO: adicionar suporte para resultado de pesquisa do admin. |
||||
|
""" |
||||
|
|
||||
|
if request.POST: |
||||
|
if request.POST.has_key('tamanho_etiqueta'): |
||||
|
formato = request.POST['tamanho_etiqueta'] |
||||
|
|
||||
|
|
||||
|
if id: |
||||
|
legislaturas = [c.legislatura_set.latest('data_inicio') for c in CasaLegislativa.objects.filter(pk__in=id, legislatura__id__isnull=False).distinct()] |
||||
|
mandatos = reduce(lambda x, y: x | y, [l.mandato_set.all() for l in legislaturas]) |
||||
|
parlamentares = [m.parlamentar for m in mandatos] |
||||
|
qs = parlamentares |
||||
|
|
||||
|
else: |
||||
|
qs = carrinhoOrGet_for_parlamentar_qs(request) |
||||
|
|
||||
|
if not qs: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
response['Content-Disposition'] = 'attachment; filename=casas.pdf' |
||||
|
report = ParlamentaresLabels(queryset=qs, formato=formato) |
||||
|
report.generate_by(PDFGenerator, filename=response) |
||||
|
|
||||
|
return response |
||||
|
|
||||
|
def carrinhoOrGet_for_parlamentar_qs(request): |
||||
|
""" |
||||
|
Verifica se existe parlamentares na sessão se não verifica get e retorna qs correspondente. |
||||
|
""" |
||||
|
if request.session.has_key('carrinho_casas'): |
||||
|
ids = request.session['carrinho_casas'] |
||||
|
legislaturas = [c.legislatura_set.latest('data_inicio') for c in CasaLegislativa.objects.filter(pk__in=ids, legislatura__id__isnull=False).distinct()] |
||||
|
mandatos = reduce(lambda x, y: x | y, [l.mandato_set.all() for l in legislaturas]) |
||||
|
parlamentares = [m.parlamentar for m in mandatos] |
||||
|
qs = parlamentares |
||||
|
else: |
||||
|
legislaturas = [c.legislatura_set.latest('data_inicio') for c in CasaLegislativa.objects.all().distinct()] |
||||
|
mandatos = reduce(lambda x, y: x | y, [l.mandato_set.all() for l in legislaturas]) |
||||
|
parlamentares = [m.parlamentar for m in mandatos] |
||||
|
qs = parlamentares |
||||
|
if request.GET: |
||||
|
qs = get_for_qs(request.GET,qs) |
||||
|
return qs |
||||
|
|
||||
|
def labels_report_sem_presidente(request, id=None, formato='2x5_etiqueta'): |
||||
|
""" TODO: adicionar suporte para resultado de pesquisa do admin. |
||||
|
""" |
||||
|
|
||||
|
if id: |
||||
|
qs = CasaLegislativa.objects.filter(pk=id) |
||||
|
else: |
||||
|
qs = carrinhoOrGet_for_qs(request) |
||||
|
|
||||
|
if not qs: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
response['Content-Disposition'] = 'attachment; filename=casas.pdf' |
||||
|
report = CasasLegislativasLabelsSemPresidente(queryset=qs, formato=formato) |
||||
|
report.generate_by(PDFGenerator, filename=response) |
||||
|
|
||||
|
return response |
||||
|
|
||||
|
|
||||
|
def report(request, id=None,tipo=None): |
||||
|
|
||||
|
if request.POST: |
||||
|
if request.POST.has_key('tipo_relatorio'): |
||||
|
tipo = request.POST['tipo_relatorio'] |
||||
|
|
||||
|
if tipo =='completo': |
||||
|
return report_complete(request, id) |
||||
|
|
||||
|
|
||||
|
if id: |
||||
|
qs = CasaLegislativa.objects.filter(pk=id) |
||||
|
else: |
||||
|
qs = carrinhoOrGet_for_qs(request) |
||||
|
|
||||
|
if not qs: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
#qs.order_by('municipio__uf','nome') |
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
response['Content-Disposition'] = 'attachment; filename=casas.pdf' |
||||
|
report = CasasLegislativasReport(queryset=qs) |
||||
|
report.generate_by(PDFGenerator, filename=response) |
||||
|
return response |
||||
|
|
||||
|
def report_complete(request,id=None): |
||||
|
|
||||
|
if id: |
||||
|
qs = CasaLegislativa.objects.filter(pk=id) |
||||
|
else: |
||||
|
qs = carrinhoOrGet_for_qs(request) |
||||
|
|
||||
|
if not qs: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
response['Content-Disposition'] = 'attachment; filename=casas.pdf' |
||||
|
|
||||
|
# Gera um relatorio para cada casa e concatena os relatorios |
||||
|
cont = 0 |
||||
|
canvas = None |
||||
|
quant = qs.count() |
||||
|
if quant > 1: |
||||
|
for i in qs: |
||||
|
cont += 1 |
||||
|
#queryset deve ser uma lista |
||||
|
lista = (i,) |
||||
|
if cont == 1: |
||||
|
report = InfoCasaLegislativa(queryset=lista) |
||||
|
canvas = report.generate_by(PDFGenerator, return_canvas=True,filename=response,) |
||||
|
else: |
||||
|
report = InfoCasaLegislativa(queryset=lista) |
||||
|
if cont == quant: |
||||
|
report.generate_by(PDFGenerator, canvas=canvas) |
||||
|
else: |
||||
|
canvas = report.generate_by(PDFGenerator, canvas=canvas, return_canvas=True) |
||||
|
else: |
||||
|
report = InfoCasaLegislativa(queryset=qs) |
||||
|
report.generate_by(PDFGenerator,filename=response) |
||||
|
|
||||
|
return response |
||||
|
|
||||
|
def casas_sem_convenio_report(request): |
||||
|
qs = CasaLegislativa.objects.filter(convenio=None).order_by('municipio__uf','nome') |
||||
|
|
||||
|
if request.GET: |
||||
|
qs = get_for_qs(request.GET,qs) |
||||
|
if not qs: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
report = CasasSemConvenioReport(queryset=qs) |
||||
|
report.generate_by(PDFGenerator, filename=response) |
||||
|
return response |
||||
|
|
||||
|
|
||||
|
|
||||
|
def export_csv(request): |
||||
|
response = HttpResponse(mimetype='text/csv') |
||||
|
response['Content-Disposition'] = 'attachment; filename=casas.csv' |
||||
|
|
||||
|
writer = csv.writer(response) |
||||
|
|
||||
|
casas = carrinhoOrGet_for_qs(request) |
||||
|
if not casas or not request.POST: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
atributos = request.POST.getlist("itens_csv_selected") |
||||
|
atributos2 = [s.encode("utf-8") for s in atributos] |
||||
|
|
||||
|
try: |
||||
|
atributos2.insert(atributos2.index('Município'), u'UF') |
||||
|
except ValueError: |
||||
|
pass |
||||
|
|
||||
|
writer.writerow(atributos2) |
||||
|
|
||||
|
for casa in casas: |
||||
|
lista = [] |
||||
|
contatos = casa.funcionario_set.filter(setor="contato_interlegis") |
||||
|
for atributo in atributos: |
||||
|
if u"CNPJ" == atributo: |
||||
|
lista.append(casa.cnpj.encode("utf-8")) |
||||
|
elif u"Código IBGE" == atributo: |
||||
|
lista.append(str(casa.municipio.codigo_ibge).encode("utf-8")) |
||||
|
elif u"Código TSE" == atributo: |
||||
|
lista.append(str(casa.municipio.codigo_tse).encode("utf-8")) |
||||
|
elif u"Nome" == atributo: |
||||
|
lista.append(casa.nome.encode("utf-8")) |
||||
|
elif u"Município" == atributo: |
||||
|
lista.append(unicode(casa.municipio.uf.sigla).encode("utf-8")) |
||||
|
lista.append(unicode(casa.municipio.nome).encode("utf-8")) |
||||
|
elif u"Presidente" == atributo: |
||||
|
#TODO: Esse encode deu erro em 25/04/2012. Comentei para que o usuário pudesse continuar seu trabalho |
||||
|
# É preciso descobrir o porque do erro e fazer a correção definitiva. |
||||
|
# lista.append(str(casa.presidente or "").encode("utf-8")) |
||||
|
lista.append(str(casa.presidente or "")) |
||||
|
elif u"Logradouro" == atributo: |
||||
|
lista.append(casa.logradouro.encode("utf-8")) |
||||
|
elif u"Bairro" == atributo: |
||||
|
lista.append(casa.bairro.encode("utf-8")) |
||||
|
elif u"CEP" == atributo: |
||||
|
lista.append(casa.cep.encode("utf-8")) |
||||
|
elif u"Telefone" == atributo: |
||||
|
lista.append(str(casa.telefone or "")) |
||||
|
elif u"Página web" == atributo: |
||||
|
lista.append(casa.pagina_web.encode("utf-8")) |
||||
|
elif u"Email" == atributo: |
||||
|
lista.append(casa.email.encode("utf-8")) |
||||
|
elif u"Número de parlamentares" == atributo: |
||||
|
lista.append(casa.total_parlamentares) |
||||
|
elif u"Última alteração de endereco" == atributo: |
||||
|
lista.append(casa.ult_alt_endereco) |
||||
|
elif u"Nome contato" == atributo: |
||||
|
if contatos and contatos[0].nome: |
||||
|
lista.append(contatos[0].nome.encode("utf-8")) |
||||
|
else: |
||||
|
lista.append('') |
||||
|
elif u"Cargo contato" == atributo: |
||||
|
if contatos and contatos[0].cargo: |
||||
|
lista.append(contatos[0].cargo.encode("utf-8")) |
||||
|
else: |
||||
|
lista.append('') |
||||
|
elif u"Email contato" == atributo: |
||||
|
if contatos and contatos[0].email: |
||||
|
lista.append(contatos[0].email.encode("utf-8")) |
||||
|
else: |
||||
|
lista.append('') |
||||
|
else: |
||||
|
pass |
||||
|
|
||||
|
writer.writerow(lista) |
||||
|
|
||||
|
return response |
@ -0,0 +1,139 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.contrib import admin |
||||
|
from django.contrib.admin.views.main import ChangeList |
||||
|
from sigi.apps.convenios.models import Projeto, Convenio, EquipamentoPrevisto, Anexo, Tramitacao, UnidadeAdministrativa |
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
from sigi.apps.servicos.models import Servico |
||||
|
from django.http import HttpResponse, HttpResponseRedirect |
||||
|
from sigi.apps.convenios.reports import ConvenioReport |
||||
|
from sigi.apps.utils import queryset_ascii |
||||
|
from geraldo.generators import PDFGenerator |
||||
|
|
||||
|
from sigi.apps.convenios.views import adicionar_convenios_carrinho |
||||
|
|
||||
|
class TramitacaoInline(admin.TabularInline): |
||||
|
model = Tramitacao |
||||
|
extra = 1 |
||||
|
|
||||
|
class AnexosInline(admin.TabularInline): |
||||
|
model = Anexo |
||||
|
extra = 2 |
||||
|
exclude = ['data_pub',] |
||||
|
|
||||
|
class EquipamentoPrevistoInline(admin.TabularInline): |
||||
|
model = EquipamentoPrevisto |
||||
|
extra = 2 |
||||
|
raw_id_fields = ('equipamento',) |
||||
|
|
||||
|
class AnexoAdmin(admin.ModelAdmin): |
||||
|
date_hierarchy = 'data_pub' |
||||
|
exclude = ['data_pub',] |
||||
|
list_display = ('arquivo', 'descricao', 'data_pub', 'convenio') |
||||
|
raw_id_fields = ('convenio',) |
||||
|
search_fields = ('descricao', 'convenio__id', 'arquivo', |
||||
|
'convenio__casa_legislativa__nome') |
||||
|
|
||||
|
class ConvenioAdmin(admin.ModelAdmin): |
||||
|
change_list_template = 'convenios/change_list.html' |
||||
|
fieldsets = ( |
||||
|
(None, |
||||
|
{'fields': ('casa_legislativa', 'num_processo_sf','num_convenio','projeto','observacao')} |
||||
|
), |
||||
|
('Datas', |
||||
|
{'fields': ('data_adesao', 'data_retorno_assinatura', |
||||
|
'data_termo_aceite', 'data_pub_diario', |
||||
|
'data_devolucao_via', 'data_postagem_correio')} |
||||
|
), |
||||
|
('Datas - Convenio sem assinatura', |
||||
|
{'fields': ('data_devolucao_sem_assinatura','data_retorno_sem_assinatura',)} |
||||
|
), |
||||
|
) |
||||
|
actions = ['adicionar_convenios'] |
||||
|
inlines = (TramitacaoInline, AnexosInline, EquipamentoPrevistoInline) |
||||
|
list_display = ('num_convenio', 'casa_legislativa', 'get_uf', |
||||
|
'data_adesao','data_retorno_assinatura','data_pub_diario','data_termo_aceite', |
||||
|
'projeto', |
||||
|
) |
||||
|
list_display_links = ('num_convenio','casa_legislativa',) |
||||
|
list_filter = ('projeto','casa_legislativa','conveniada', 'equipada') |
||||
|
#date_hierarchy = 'data_adesao' |
||||
|
ordering = ('casa_legislativa__tipo__sigla','casa_legislativa__municipio__uf','casa_legislativa') |
||||
|
raw_id_fields = ('casa_legislativa',) |
||||
|
queryset = queryset_ascii |
||||
|
search_fields = ('id', 'search_text',#'casa_legislativa__nome', |
||||
|
'num_processo_sf','num_convenio') |
||||
|
|
||||
|
def get_uf(self, obj): |
||||
|
return obj.casa_legislativa.municipio.uf.sigla |
||||
|
get_uf.short_description = 'UF' |
||||
|
get_uf.admin_order_field = 'casa_legislativa__municipio__uf__sigla' |
||||
|
|
||||
|
def changelist_view(self, request, extra_context=None): |
||||
|
import re |
||||
|
request.GET._mutable=True |
||||
|
if 'data_retorno_assinatura__gte' in request.GET: |
||||
|
value = request.GET.get('data_retorno_assinatura__gte','') |
||||
|
if value == '': |
||||
|
del request.GET['data_retorno_assinatura__gte'] |
||||
|
elif re.match('^\d*$', value): # Year only |
||||
|
request.GET['data_retorno_assinatura__gte'] = "%s-01-01" % value #Complete with january 1st |
||||
|
elif re.match('^\d*\D\d*$', value): # Year and month |
||||
|
request.GET['data_retorno_assinatura__gte'] = '%s-01' % value #Complete with 1st day of month |
||||
|
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 |
||||
|
|
||||
|
return super(ConvenioAdmin, self).changelist_view( |
||||
|
request, |
||||
|
extra_context={'query_str': '?' + request.META['QUERY_STRING']} |
||||
|
) |
||||
|
def relatorio(self, request, queryset): |
||||
|
#queryset.order_by('casa_legislativa__municipio__uf') |
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
report = ConvenioReport(queryset=queryset) |
||||
|
report.generate_by(PDFGenerator, filename=response) |
||||
|
return response |
||||
|
relatorio.short_description = u'Exportar convênios selecionados para PDF' |
||||
|
|
||||
|
def adicionar_convenios(self, request, queryset): |
||||
|
if request.session.has_key('carrinho_convenios'): |
||||
|
q1 = len(request.session['carrinho_convenios']) |
||||
|
else: |
||||
|
q1 = 0 |
||||
|
adicionar_convenios_carrinho(request,queryset=queryset) |
||||
|
q2 = len(request.session['carrinho_convenios']) |
||||
|
quant = q2 - q1 |
||||
|
if quant: |
||||
|
self.message_user(request,str(q2-q1)+" Convênios adicionados no carrinho" ) |
||||
|
else: |
||||
|
self.message_user(request,"Os Convênios selecionados já foram adicionadas anteriormente" ) |
||||
|
return HttpResponseRedirect('.') |
||||
|
adicionar_convenios.short_description = u"Armazenar convênios no carrinho para exportar" |
||||
|
|
||||
|
def get_actions(self, request): |
||||
|
actions = super(ConvenioAdmin, self).get_actions(request) |
||||
|
del actions['delete_selected'] |
||||
|
return actions |
||||
|
|
||||
|
def lookup_allowed(self, lookup, value): |
||||
|
return super(ConvenioAdmin, self).lookup_allowed(lookup, value) or \ |
||||
|
lookup in ['casa_legislativa__municipio__uf__codigo_ibge__exact'] |
||||
|
|
||||
|
class EquipamentoPrevistoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('convenio', 'equipamento', 'quantidade') |
||||
|
list_display_links = ('convenio', 'equipamento') |
||||
|
ordering = ('convenio', 'equipamento') |
||||
|
raw_id_fields = ('convenio', 'equipamento') |
||||
|
search_fields = ('convenio__id', 'equipamento__fabricante__nome', |
||||
|
'equipamento__modelo__modelo', 'equipamento__modelo__tipo__tipo') |
||||
|
|
||||
|
#admin.site.register(Projeto) |
||||
|
admin.site.register(Convenio, ConvenioAdmin) |
||||
|
#admin.site.register(CasaLegislativa) |
||||
|
admin.site.register(EquipamentoPrevisto, EquipamentoPrevistoAdmin) |
@ -0,0 +1,188 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from datetime import datetime |
||||
|
from django.db import models |
||||
|
from django.contrib.contenttypes import generic |
||||
|
from sigi.apps.utils import SearchField |
||||
|
|
||||
|
class Projeto(models.Model): |
||||
|
""" Modelo para representar os projetos do programa |
||||
|
Interlegis |
||||
|
""" |
||||
|
nome = models.CharField(max_length=50) |
||||
|
sigla = models.CharField(max_length=10) |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.sigla |
||||
|
|
||||
|
class Convenio(models.Model): |
||||
|
""" Modelo que representa um convênio do Interlegis |
||||
|
com uma Casa Legislativa. |
||||
|
|
||||
|
Uma Casa Legislativa pode não ter um convênio e sim |
||||
|
apenas uma adesão com o Interlegis, isto é, |
||||
|
não tem compromissos direto com o Interlegis apenas |
||||
|
um pacto de colaboração entre as partes |
||||
|
""" |
||||
|
casa_legislativa = models.ForeignKey( |
||||
|
'casas.CasaLegislativa', |
||||
|
verbose_name='Casa Legislativa' |
||||
|
) |
||||
|
# campo de busca em caixa baixa e sem acentos |
||||
|
search_text = SearchField(field_names=['casa_legislativa']) |
||||
|
casa_legislativa.convenio_uf_filter = True |
||||
|
casa_legislativa.convenio_cl_tipo_filter = True |
||||
|
projeto = models.ForeignKey( |
||||
|
Projeto |
||||
|
) |
||||
|
# numero designado pelo Senado Federal para o convênio |
||||
|
num_processo_sf = models.CharField( |
||||
|
'número do processo SF (Senado Federal)', |
||||
|
max_length=20, |
||||
|
blank=True, |
||||
|
help_text='Formatos:<br/>Antigo: <em>XXXXXX/XX-X</em>.<br/><em>SIGAD: XXXXX.XXXXXX/XXXX-XX</em>' |
||||
|
) |
||||
|
num_convenio = models.CharField( |
||||
|
'número do convênio', |
||||
|
max_length=10, |
||||
|
blank=True |
||||
|
) |
||||
|
data_adesao = models.DateField( |
||||
|
'Aderidas', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
) |
||||
|
data_retorno_assinatura = models.DateField( |
||||
|
'Conveniadas', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
help_text='Convênio firmado.' |
||||
|
) |
||||
|
data_pub_diario = models.DateField( |
||||
|
'data da publicação no Diário Oficial', |
||||
|
null=True, |
||||
|
blank=True |
||||
|
) |
||||
|
data_termo_aceite = models.DateField( |
||||
|
'Equipadas', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
help_text='Equipamentos recebidos.' |
||||
|
) |
||||
|
data_devolucao_via = models.DateField( |
||||
|
'data de devolução da via', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
help_text=u'Data de devolução da via do convênio à Câmara Municipal.' |
||||
|
) |
||||
|
data_postagem_correio = models.DateField( |
||||
|
'data postagem correio', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
) |
||||
|
data_devolucao_sem_assinatura = models.DateField( |
||||
|
'data de devolução por falta de assinatura', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
help_text=u'Data de devolução por falta de assinatura', |
||||
|
) |
||||
|
data_retorno_sem_assinatura = models.DateField( |
||||
|
'data do retorno sem assinatura', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
help_text=u'Data do retorno do convênio sem assinatura', |
||||
|
) |
||||
|
observacao = models.CharField( |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
max_length=100, |
||||
|
) |
||||
|
conveniada = models.BooleanField() |
||||
|
equipada = models.BooleanField() |
||||
|
|
||||
|
def save(self, *args, **kwargs): |
||||
|
self.conveniada = self.data_retorno_assinatura!=None |
||||
|
self.equipada = self.data_termo_aceite!=None |
||||
|
super(Convenio, self).save(*args, **kwargs) |
||||
|
|
||||
|
|
||||
|
class Meta: |
||||
|
get_latest_by = 'id' |
||||
|
ordering = ('id',) |
||||
|
verbose_name = u'convênio' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
if self.data_retorno_assinatura != None: |
||||
|
return u"Convênio nº %s - projeto %s, em %s" % (self.num_convenio, self.projeto.sigla, self.data_retorno_assinatura) |
||||
|
else: |
||||
|
return u"Adesão ao projeto %s, em %s" % (self.projeto.sigla, self.data_adesao) |
||||
|
|
||||
|
class EquipamentoPrevisto(models.Model): |
||||
|
""" Modelo utilizado para registrar os equipamentos |
||||
|
disponibilizados para as Casas Legislativas |
||||
|
(foi usado na prmeira etapa do programa) |
||||
|
""" |
||||
|
convenio = models.ForeignKey(Convenio, verbose_name=u'convênio') |
||||
|
equipamento = models.ForeignKey('inventario.Equipamento') |
||||
|
quantidade = models.PositiveSmallIntegerField(default=1) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'equipamento previsto' |
||||
|
verbose_name_plural = 'equipamentos previstos' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return u'%s %s(s)' % (self.quantidade, self.equipamento) |
||||
|
|
||||
|
class Anexo(models.Model): |
||||
|
""" Modelo para giardar os documentos gerados |
||||
|
no processo de convênio |
||||
|
""" |
||||
|
convenio = models.ForeignKey(Convenio, verbose_name=u'convênio') |
||||
|
# caminho no sistema para o documento anexo |
||||
|
arquivo = models.FileField(upload_to='apps/convenios/anexo/arquivo',) |
||||
|
descricao = models.CharField('descrição', max_length='70') |
||||
|
data_pub = models.DateTimeField( |
||||
|
'data da publicação do anexo', |
||||
|
default=datetime.now |
||||
|
) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('-data_pub',) |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return unicode("%s publicado em %s" % (self.descricao, self.data_pub)) |
||||
|
|
||||
|
class UnidadeAdministrativa(models.Model): |
||||
|
""" Modelo para representar uma Unidade Administrativa |
||||
|
que pode ser um servivo do próprio Interlegis, assim como |
||||
|
uma unidade do Senado Federal |
||||
|
""" |
||||
|
sigla = models.CharField(max_length='10') |
||||
|
nome = models.CharField(max_length='100') |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return unicode(self.sigla) |
||||
|
|
||||
|
|
||||
|
class Tramitacao(models.Model): |
||||
|
""" 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) |
||||
|
""" |
||||
|
convenio = models.ForeignKey(Convenio, verbose_name=u'convênio') |
||||
|
unid_admin = models.ForeignKey(UnidadeAdministrativa, verbose_name=u'Unidade Administrativa') |
||||
|
data = models.DateField() |
||||
|
observacao = models.CharField( |
||||
|
'observação', |
||||
|
max_length='512', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name_plural = u'Tramitações' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
if self.observacao: |
||||
|
return unicode("%s em %s (%s)" % (self.unid_admin, self.data, self.observacao)) |
||||
|
else: |
||||
|
return unicode("%s em %s" % (self.unid_admin, self.data)) |
||||
|
|
@ -0,0 +1,316 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
import os |
||||
|
from ctypes import alignment |
||||
|
from operator import attrgetter |
||||
|
from geraldo import Report, ReportBand, ObjectValue, DetailBand, Label, \ |
||||
|
landscape,SystemField, BAND_WIDTH,ReportGroup, \ |
||||
|
FIELD_ACTION_SUM, FIELD_ACTION_COUNT, FIELD_ACTION_AVG |
||||
|
from geraldo.graphics import Image |
||||
|
|
||||
|
from reportlab.lib.units import cm |
||||
|
from reportlab.lib.pagesizes import A4 |
||||
|
from reportlab.lib.enums import TA_CENTER, TA_RIGHT |
||||
|
|
||||
|
from sigi.apps.relatorios.reports import ReportDefault |
||||
|
|
||||
|
#from abc import ABCMeta |
||||
|
|
||||
|
class CasasAderidasReport(object): |
||||
|
pass |
||||
|
|
||||
|
class CasasNaoAderidasReport(object): |
||||
|
pass |
||||
|
|
||||
|
class CasasComEquipamentosReport(object): |
||||
|
pass |
||||
|
|
||||
|
class SemEquipamentosReport(object): |
||||
|
pass |
||||
|
|
||||
|
class ConvenioReport(ReportDefault): |
||||
|
title = u'Relatório de Convênios' |
||||
|
|
||||
|
class band_page_header(ReportDefault.band_page_header): |
||||
|
|
||||
|
label_top = ReportDefault.band_page_header.label_top |
||||
|
label_left = [0,1.5,7,9,11,13,15,17] |
||||
|
elements = list(ReportDefault.band_page_header.elements) |
||||
|
height = 4.7*cm |
||||
|
|
||||
|
elements += [ |
||||
|
Label( |
||||
|
text="UF", |
||||
|
left=label_left[0]*cm, |
||||
|
top=label_top + 0.4*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Municipio", |
||||
|
left=label_left[1]*cm, |
||||
|
top=label_top + 0.4*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Data de Adesão", |
||||
|
left=label_left[2]*cm, |
||||
|
top=label_top, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Número do Convênio", |
||||
|
left=label_left[3]*cm, |
||||
|
top=label_top, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Data do Convênio", |
||||
|
left=label_left[4]*cm, |
||||
|
top=label_top, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Data de Publicação", |
||||
|
left=label_left[5]*cm, |
||||
|
top=label_top, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Data de Aceite", |
||||
|
left=label_left[6]*cm, |
||||
|
top=label_top, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Projeto", |
||||
|
left=label_left[7]*cm, |
||||
|
top=label_top + 0.4*cm, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
] |
||||
|
|
||||
|
|
||||
|
|
||||
|
class band_page_footer(ReportDefault.band_page_footer): |
||||
|
pass |
||||
|
|
||||
|
class band_detail(ReportDefault.band_detail): |
||||
|
|
||||
|
label_left = [0,1.5,7,9,11,13,15,17] |
||||
|
|
||||
|
elements=[ |
||||
|
ObjectValue( |
||||
|
attribute_name='casa_legislativa.municipio.uf.sigla', |
||||
|
left=label_left[0]*cm |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='casa_legislativa.municipio.nome', |
||||
|
left=label_left[1]*cm |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='data_adesao', |
||||
|
left=label_left[2]*cm, |
||||
|
get_value=lambda instance: |
||||
|
instance.data_adesao.strftime('%d/%m/%Y') if instance.data_adesao != None else '-' |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='num_convenio', |
||||
|
left=label_left[3]*cm |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='data_retorno_assinatura', |
||||
|
left=label_left[4]*cm, |
||||
|
get_value=lambda instance: |
||||
|
instance.data_retorno_assinatura.strftime('%d/%m/%Y') if instance.data_retorno_assinatura != None else '-' |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='data_pub_diario', |
||||
|
left=label_left[5]*cm, |
||||
|
get_value=lambda instance: |
||||
|
instance.data_pub_diario.strftime('%d/%m/%Y') if instance.data_pub_diario != None else '-' |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='data_termo_aceite', |
||||
|
left=label_left[6]*cm, |
||||
|
get_value=lambda instance: |
||||
|
instance.data_termo_aceite.strftime('%d/%m/%Y') if instance.data_termo_aceite != None else '-' |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='projeto.sigla', |
||||
|
left=label_left[7]*cm |
||||
|
), |
||||
|
] |
||||
|
|
||||
|
groups = [ |
||||
|
ReportGroup(attribute_name='casa_legislativa.municipio.uf', |
||||
|
band_header=ReportBand( |
||||
|
height=0.7*cm, |
||||
|
elements= [ |
||||
|
ObjectValue(attribute_name='casa_legislativa.municipio.uf', |
||||
|
get_Value= lambda instance: 'CasaLegislativa: '+ (instance.casa_legislativa.uf) |
||||
|
) |
||||
|
], |
||||
|
borders={'top': True}, |
||||
|
) |
||||
|
) |
||||
|
] |
||||
|
|
||||
|
class ConvenioReportSemAceite(ConvenioReport): |
||||
|
class band_page_header(ReportDefault.band_page_header): |
||||
|
|
||||
|
label_top = ReportDefault.band_page_header.label_top |
||||
|
label_left = [0,1.5,7,9,11,13,15,17] |
||||
|
elements = list(ReportDefault.band_page_header.elements) |
||||
|
height = 4.7*cm |
||||
|
|
||||
|
elements += [ |
||||
|
Label( |
||||
|
text="UF", |
||||
|
left=label_left[0]*cm, |
||||
|
top=label_top + 0.4*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Município", |
||||
|
left=label_left[1]*cm, |
||||
|
top=label_top + 0.4*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Data de Adesão", |
||||
|
left=label_left[3]*cm, |
||||
|
top=label_top, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Número do Convênio", |
||||
|
left=label_left[4]*cm, |
||||
|
top=label_top, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Data do Convênio", |
||||
|
left=label_left[5]*cm, |
||||
|
top=label_top, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Data de Publicação", |
||||
|
left=label_left[6]*cm, |
||||
|
top=label_top, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
Label( |
||||
|
text="Projeto", |
||||
|
left=label_left[7]*cm, |
||||
|
top=label_top + 0.4*cm, |
||||
|
width=2*cm, |
||||
|
), |
||||
|
] |
||||
|
|
||||
|
|
||||
|
class band_detail(ReportDefault.band_detail): |
||||
|
|
||||
|
label_left = [0,1.5,7,9,11,13,15,17] |
||||
|
|
||||
|
elements=[ |
||||
|
ObjectValue( |
||||
|
attribute_name='casa_legislativa.municipio.uf.sigla', |
||||
|
left=label_left[0]*cm |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='casa_legislativa.municipio.nome', |
||||
|
left=label_left[1]*cm |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='data_adesao', |
||||
|
left=label_left[3]*cm, |
||||
|
get_value=lambda instance: |
||||
|
instance.data_adesao.strftime('%d/%m/%Y') if instance.data_adesao != None else '-' |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='num_convenio', |
||||
|
left=label_left[4]*cm |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='data_retorno_assinatura', |
||||
|
left=label_left[5]*cm, |
||||
|
get_value=lambda instance: |
||||
|
instance.data_retorno_assinatura.strftime('%d/%m/%Y') if instance.data_retorno_assinatura != None else '-' |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='data_pub_diario', |
||||
|
left=label_left[6]*cm, |
||||
|
get_value=lambda instance: |
||||
|
instance.data_pub_diario.strftime('%d/%m/%Y') if instance.data_pub_diario != None else '-' |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='projeto.sigla', |
||||
|
left=label_left[7]*cm |
||||
|
), |
||||
|
] |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
float_duas_casas = lambda instance: '%.2f' % (instance) |
||||
|
class ConvenioReportRegiao(ReportDefault): |
||||
|
title = u'Relatório de Convênios por Região' |
||||
|
|
||||
|
class band_page_header(ReportDefault.band_page_header): |
||||
|
label_top = ReportDefault.band_page_header.label_top |
||||
|
label_left = [0.5,6,8,10,12,14] |
||||
|
map(lambda x:x-0.4,label_left) |
||||
|
|
||||
|
elements = list(ReportDefault.band_page_header.elements) |
||||
|
|
||||
|
elements += [ |
||||
|
Label(text="UF", left=label_left[0]*cm,top=label_top,), |
||||
|
Label(text="Total", left=label_left[1]*cm,top=label_top,), |
||||
|
Label(text="Aderidas", left=label_left[2]*cm,top=label_top,), |
||||
|
Label(text="%", left=label_left[3]*cm,top=label_top), |
||||
|
Label(text="Ñ Aderidas", left=label_left[4]*cm,top=label_top,), |
||||
|
Label(text="%", left=label_left[5]*cm,top=label_top), |
||||
|
] |
||||
|
class band_detail(ReportDefault.band_detail): |
||||
|
label_left = [0.5,6,8,10,12,14] |
||||
|
display_inline = True |
||||
|
float_duas_casas = lambda instance: '%.2f' % (instance.porc_casas_aderidas) |
||||
|
default_style = {'fontName': 'Helvetica', 'fontSize': 11} |
||||
|
|
||||
|
elements=[ |
||||
|
ObjectValue(attribute_name='estado', left=label_left[0]*cm, ), |
||||
|
ObjectValue(attribute_name='quant_casas', left=label_left[1]*cm,), |
||||
|
ObjectValue(attribute_name='quant_casas_aderidas', left=label_left[2]*cm), |
||||
|
ObjectValue(attribute_name='porc_casas_aderidas', left=label_left[3]*cm), |
||||
|
ObjectValue(attribute_name='quant_casas_nao_aderidas', left=label_left[4]*cm), |
||||
|
ObjectValue(attribute_name='porc_casas_nao_aderidas', left=label_left[5]*cm,), |
||||
|
] |
||||
|
|
||||
|
class band_summary(ReportBand): |
||||
|
label_left = [0.5,6,8,10,12,14] |
||||
|
elements = [ |
||||
|
Label(text="Total", top=0.1*cm, left=label_left[0]*cm), |
||||
|
ObjectValue(attribute_name='quant_casas', action=FIELD_ACTION_SUM, left=label_left[1]*cm, ), |
||||
|
ObjectValue(attribute_name='quant_casas_aderidas', action=FIELD_ACTION_SUM, left=label_left[2]*cm), |
||||
|
# ObjectValue(attribute_name='porc_casas_aderidas', action=FIELD_ACTION_AVG, left=label_left[3]*cm, |
||||
|
# #get_value= lambda instance : lambda instance: '%.2f' % (instance.porc_casas_aderidas), |
||||
|
# ), |
||||
|
ObjectValue(attribute_name='quant_casas_nao_aderidas', action=FIELD_ACTION_SUM, left=label_left[4]*cm), |
||||
|
# ObjectValue(attribute_name='porc_casas_nao_aderidas', left=label_left[5]*cm, |
||||
|
# get_value=lambda x: teste(), |
||||
|
# ), |
||||
|
] |
||||
|
borders = {'top':True} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
class ConvenioPorCMReport(ConvenioReport): |
||||
|
title = u'Relatório de Convênios por Câmara Municipal' |
||||
|
|
||||
|
class ConvenioPorALReport(ConvenioReport): |
||||
|
title = u'Relatório de Convênios por Assembléia Legislativa' |
||||
|
|
||||
|
class ConvenioReportSemAceiteCM(ConvenioReportSemAceite): |
||||
|
title = u'Relatório de Convênios por Câmara Municipal' |
||||
|
|
||||
|
class ConvenioReportSemAceiteAL(ConvenioReportSemAceite): |
||||
|
title = u'Relatório de Convênios por Assembléia Legislativa' |
@ -0,0 +1,158 @@ |
|||||
|
{% extends "admin/carrinho.html" %} |
||||
|
{% load adminmedia admin_list i18n %} |
||||
|
{% block extrastyle %} |
||||
|
{{ block.super }} |
||||
|
{% include "admin/tabs_style.html" %} |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block title %}Convênios no Carrinho | SIGI{% endblock %} |
||||
|
{% block content_title %}<h1>Convênios no Carrinho</h1>{% endblock %} |
||||
|
|
||||
|
{% block mensagem%} |
||||
|
<ul class="messagelist"> |
||||
|
{%if carIsEmpty%} |
||||
|
<li class="warning">O carrinho está vazio, sendo assim todos os convênios entram na lista para exportação de acordo com os filtros aplicados.</li> |
||||
|
{%else%} |
||||
|
<li>{{paginas.paginator.count}} Convênios no carrinho.</li> |
||||
|
{%endif%} |
||||
|
</ul> |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block action %}deleta_itens_carrinho{% endblock %} |
||||
|
|
||||
|
{% block tabela %} |
||||
|
<table> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
{%if not carIsEmpty%} |
||||
|
<th class="sorted ascending"><!-- <input type="checkbox" id="action-toggle" style="display: inline;">--> |
||||
|
</th> |
||||
|
{% endif %} |
||||
|
<th class="sorted ascending">Numero do convênio</th> |
||||
|
<th class="sorted ascending">Casa Legislativa</th> |
||||
|
<th class="sorted ascending">Aderidas</th> |
||||
|
<th class="sorted ascending">Convêniadas</th> |
||||
|
<th class="sorted ascending">Equipadas</th> |
||||
|
<th class="sorted ascending">Projeto</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
{% for convenio in paginas.object_list %} |
||||
|
<tr class="{% cycle 'row1' 'row2' %}"> |
||||
|
{%if not carIsEmpty%} |
||||
|
<th><input type="checkbox" name="_selected_action" |
||||
|
value="{{convenio.id}}" class="action-select" /></th> |
||||
|
{% endif %} |
||||
|
<td style="text-align: left;">{{convenio.num_convenio}}</td> |
||||
|
<td>{{convenio.casa_legislativa}}</td> |
||||
|
<td>{{convenio.data_adesao}}</td> |
||||
|
<td>{{convenio.data_retorno_assinatura}}</td> |
||||
|
<td>{{convenio.data_termo_aceite}}</td> |
||||
|
<td>{{convenio.projeto}}</td> |
||||
|
</tr> |
||||
|
{% endfor %} |
||||
|
</tbody> |
||||
|
</table> |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block botoes %} |
||||
|
<div id="tabs"> |
||||
|
|
||||
|
<ul> |
||||
|
<li><a href="#tabs-1">Relatório</a></li> |
||||
|
<li><a href="#tabs-2">Arquivo CSV (Excel, Calc)</a></li> |
||||
|
</ul> |
||||
|
<div id="tabs-1"> |
||||
|
<form action="../reports/{{ query_str }}" method="post"> |
||||
|
<fieldset> |
||||
|
<legend>Relatório por</legend> |
||||
|
<ul class="tabs-conteudo"> |
||||
|
<li> |
||||
|
<input type="radio" name="filtro_casa" value="cm" checked="checked"/> |
||||
|
<label>Câmara Municipal</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<input type="radio" name="filtro_casa" value="al" /> |
||||
|
<label>Assembléia Legislativa</label> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
<fieldset> |
||||
|
<legend>Com data de aceite? (Equipada)</legend> |
||||
|
<ul class="tabs-conteudo"> |
||||
|
<li> |
||||
|
<input type="radio" name="data_aceite" value="sim" checked="checked" /> |
||||
|
<label>Sim</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<input type="radio" name="data_aceite" value="nao" /> |
||||
|
<label>Não</label> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
<ul class="botoes"> |
||||
|
<li><input type="submit" value="Gerar Relatório"></li> |
||||
|
</ul> |
||||
|
</form> |
||||
|
</div> |
||||
|
<div id="tabs-2"> |
||||
|
<form action="../csv/{{query_str}}" method="post"> |
||||
|
<fieldset><legend>Escolha os atributos para exportar</legend> |
||||
|
<ul id="sortable" class="tabs-conteudo"> |
||||
|
<li> |
||||
|
<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" /> |
||||
|
<label>Nº Processo</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" value="No. Convênio" |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>Nº Convênio</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" value="Projeto" |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>Projeto</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" value="Casa Legislativa" |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>Casa Legislativa</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" value="Data de Adesão" |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>Data de Adesão</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" value="Data de Convênio" |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>Data de Convênio</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<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." |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>Data da Publicação no Diário Oficial</label> |
||||
|
</li> |
||||
|
<li> |
||||
|
<span class="ui-icon ui-icon-arrowthick-2-n-s"></span> |
||||
|
<input type="checkbox" name="itens_csv_selected" value="Data Equipada" |
||||
|
class="action-select" checked="checked" /> |
||||
|
<label>Data Equipada</label> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
<ul class="botoes"> |
||||
|
<li><input type="submit" value="Exportar CSV" /></li> |
||||
|
</ul> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
{% endblock %} |
@ -0,0 +1,40 @@ |
|||||
|
{% extends "admin/change_list.html" %} |
||||
|
{% load i18n reporting_tags admin_list %} |
||||
|
|
||||
|
{% block extrastyle %} |
||||
|
{{ block.super }} |
||||
|
{% include "admin/tabs_style.html" %} |
||||
|
|
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block object-tools %} |
||||
|
{% if has_add_permission %} |
||||
|
|
||||
|
<ul class="object-tools"> |
||||
|
<li><a onclick="return showRelatedObjectLookupPopup(this);" href="carrinho/{{query_str}}">Carrinho / Exportar</a></li> |
||||
|
<li> |
||||
|
<a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink"> |
||||
|
{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %} |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
|
||||
|
{% endif %} |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block search %} |
||||
|
<div id="toolbar"> |
||||
|
<form id="changelist-search" action="" method="get"> |
||||
|
<div><!-- DIV needed for valid HTML --> |
||||
|
<label for="searchbar"><img src="/sigi/admin_media/img/admin/icon_searchbox.png" alt="Search" /></label> |
||||
|
<input type="text" size="40" name="q" value="" id="searchbar" /> |
||||
|
<label for="data_retorno_assinatura__gte">Conveniadas a partir de:</label> |
||||
|
<input type="text" size="10" name="data_retorno_assinatura__gte" value="" id="data_retorno_assinatura__gte" class="vDateField"/> |
||||
|
<label for="data_retorno_assinatura__lte">até:</label> |
||||
|
<input type="text" size="10" name="data_retorno_assinatura__lte" value="" id="data_retorno_assinatura__lte" /> |
||||
|
<input type="submit" value="Pesquisar" /> |
||||
|
Datas podem ser: Um ano (aaaa), um mês (aaaa-mm) ou um dia (aaaa-mm-dd) |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
{% endblock %} |
@ -0,0 +1,145 @@ |
|||||
|
<html> |
||||
|
<head> |
||||
|
<title>Relatório por Região</title> |
||||
|
<style> |
||||
|
@page { |
||||
|
size: a4; |
||||
|
margin-top: 6.5cm; |
||||
|
margin-left: 1.5cm; |
||||
|
margin-right: 1cm; |
||||
|
margin-bottom: 3.5cm; |
||||
|
@frame top{ |
||||
|
-pdf-frame-content: cabecalho; |
||||
|
top: 2cm; |
||||
|
margin-left: 1cm; |
||||
|
margin-right: 1cm; |
||||
|
/*height: 1cm; */ |
||||
|
} |
||||
|
/* @frame midle{ |
||||
|
-pdf-frame-content: midle; |
||||
|
top: 6cm; |
||||
|
height: 1cm; |
||||
|
margin: 2cm; |
||||
|
}*/ |
||||
|
@frame footer { |
||||
|
-pdf-frame-content: footerContent; |
||||
|
bottom: 2cm; |
||||
|
margin-left: 1cm; |
||||
|
margin-right: 1cm; |
||||
|
height: 1cm; |
||||
|
} |
||||
|
} |
||||
|
body{ |
||||
|
font-family: 'Helvetica'; |
||||
|
font-size: 9pt; |
||||
|
} |
||||
|
#corpo h1{ |
||||
|
text-align: center; |
||||
|
} |
||||
|
#cabecalho { |
||||
|
text-align: center; |
||||
|
font-weight: bold; |
||||
|
font-size: 14pt; |
||||
|
} |
||||
|
#cabecalho .item2{ |
||||
|
font-size: 13pt; |
||||
|
} |
||||
|
#cabecalho .titulo{ |
||||
|
font-size: 14pt; |
||||
|
} |
||||
|
#footerContent { |
||||
|
border-top: black outset; |
||||
|
padding-top: 0.15cm; |
||||
|
} |
||||
|
#footerContent #esquerda{ |
||||
|
text-align: left; |
||||
|
} |
||||
|
#footerContent #direita{ |
||||
|
text-align: right; |
||||
|
background-image: url("/media/images/logo-senado.png"); |
||||
|
} |
||||
|
.tabela { |
||||
|
padding-top: 0.1cm; |
||||
|
padding-left: 0.1cm; |
||||
|
border: black solid; |
||||
|
width: 2cm; |
||||
|
background-color: #B5B5B5; |
||||
|
} |
||||
|
.tabela caption{ |
||||
|
text-align: center; |
||||
|
font-weight: bold; |
||||
|
font-size: 11pt; |
||||
|
} |
||||
|
.tabela th{ |
||||
|
background-color: #CFCFCF; |
||||
|
text-align: left; |
||||
|
} |
||||
|
.tabela .conteudo { |
||||
|
background-color: white;/*#E8E8E8;*/ |
||||
|
} |
||||
|
.tabela .sumario{ |
||||
|
font-weight: bold; |
||||
|
background-color: #CFCFCF; |
||||
|
} |
||||
|
.tabela .cabecalho_esquerda{ |
||||
|
background-color: #E8E8E8; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
</style> |
||||
|
|
||||
|
</head> |
||||
|
<body> |
||||
|
<div id="cabecalho"> |
||||
|
<table> |
||||
|
<tr> |
||||
|
<td id="imagem1"><img src="../media/images/logo-senado.png" width="80" height="80" alt="Logo Senado"/></td> |
||||
|
<td id="centro" colspan="3">SENADO FEDERAL<br/><span class="item2">SINTER - Secretaria Especial do Interlegis</span></td> |
||||
|
<td id="imagem2"><img src="../media/images/logo-interlegis.jpg" width="90" height="65" alt="Logo Interlegis"/></td> |
||||
|
</tr> |
||||
|
</table> |
||||
|
<h1 class="titulo">{{regiao}}</h1> |
||||
|
</div> |
||||
|
<div id="midle"> |
||||
|
{% for tabela in tabelas %} |
||||
|
<table class="tabela" repeat="1"> |
||||
|
<caption>{{tabela.projeto}} - {{regiao}}</caption> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
{%for item in tabela.cabecalho%} |
||||
|
<th>{{item}}</th> |
||||
|
{%endfor%} |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
{% for linha in tabela.linhas %} |
||||
|
<tr class="conteudo"> |
||||
|
<th class="cabecalho_esquerda">{{linha.estado}}</th> |
||||
|
{% for item in linha.lista %} |
||||
|
<td>{{item}}</td> |
||||
|
{% endfor %} |
||||
|
</tr> |
||||
|
{% endfor %} |
||||
|
<tr> |
||||
|
<th>Total</th> |
||||
|
{% for item in tabela.sumario %} |
||||
|
<th>{{item}}</th> |
||||
|
{% endfor %} |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
<br /> |
||||
|
{% endfor %} |
||||
|
</div> |
||||
|
<div id="footerContent"> |
||||
|
<table> |
||||
|
<tr> |
||||
|
<td id="esquerda">{{data}} às {{hora}}</td> |
||||
|
<td id="direita">Página <pdf:pagenumber /> </td> |
||||
|
</tr> |
||||
|
</table> |
||||
|
</div> |
||||
|
|
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,345 @@ |
|||||
|
#-*- coding:utf-8 -*- |
||||
|
from django.http import HttpResponse, HttpResponseRedirect |
||||
|
from django.shortcuts import render_to_response, get_list_or_404 |
||||
|
from geraldo.generators import PDFGenerator |
||||
|
from sigi.apps.convenios.models import Convenio, Projeto |
||||
|
from sigi.apps.convenios.reports import ConvenioReport \ |
||||
|
,ConvenioPorCMReport \ |
||||
|
,ConvenioPorALReport \ |
||||
|
,ConvenioReportSemAceiteAL \ |
||||
|
,ConvenioReportSemAceiteCM |
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
from sigi.apps.contatos.models import UnidadeFederativa |
||||
|
|
||||
|
import ho.pisa as pisa |
||||
|
from django.template import Context, loader |
||||
|
|
||||
|
from django.core.paginator import Paginator, InvalidPage, EmptyPage |
||||
|
|
||||
|
from django.conf import settings |
||||
|
|
||||
|
import datetime |
||||
|
|
||||
|
import csv |
||||
|
|
||||
|
def query_ordena(qs,o,ot): |
||||
|
list_display = ('num_convenio', 'casa_legislativa', |
||||
|
'data_adesao','data_retorno_assinatura','data_termo_aceite', |
||||
|
'projeto', |
||||
|
) |
||||
|
|
||||
|
aux = list_display[(int(o)-1)] |
||||
|
if ot =='asc': |
||||
|
qs = qs.order_by(aux) |
||||
|
else: |
||||
|
qs = qs.order_by("-"+aux) |
||||
|
return qs |
||||
|
|
||||
|
def get_for_qs(get,qs): |
||||
|
kwargs = {} |
||||
|
ids = 0 |
||||
|
for k,v in get.iteritems(): |
||||
|
if not (k == 'page' or k == 'pop' or k == 'q'): |
||||
|
if not k == 'o': |
||||
|
if k == "ot": |
||||
|
qs = query_ordena(qs,get["o"],get["ot"]) |
||||
|
else: |
||||
|
kwargs[str(k)] = v |
||||
|
if(str(k)=='ids'): |
||||
|
ids = 1 |
||||
|
break |
||||
|
qs = qs.filter(**kwargs) |
||||
|
|
||||
|
if ids: |
||||
|
query = 'id IN ('+ kwargs['ids'].__str__()+')' |
||||
|
qs = Convenio.objects.extra(where=[query]) |
||||
|
return qs |
||||
|
|
||||
|
def carrinhoOrGet_for_qs(request): |
||||
|
""" |
||||
|
Verifica se existe convênios na sessão se não verifica get e retorna qs correspondente. |
||||
|
""" |
||||
|
if request.session.has_key('carrinho_convenios'): |
||||
|
ids = request.session['carrinho_convenios'] |
||||
|
qs = Convenio.objects.filter(pk__in=ids) |
||||
|
else: |
||||
|
qs = Convenio.objects.all() |
||||
|
if request.GET: |
||||
|
qs = qs.order_by("casa_legislativa__municipio__uf","casa_legislativa__municipio") |
||||
|
qs = get_for_qs(request.GET,qs) |
||||
|
return qs |
||||
|
|
||||
|
def adicionar_convenios_carrinho(request,queryset=None,id=None): |
||||
|
if request.method == 'POST': |
||||
|
ids_selecionados = request.POST.getlist('_selected_action') |
||||
|
if not request.session.has_key('carrinho_convenios'): |
||||
|
request.session['carrinho_convenios'] = ids_selecionados |
||||
|
else: |
||||
|
lista = request.session['carrinho_convenios'] |
||||
|
# Verifica se id já não está adicionado |
||||
|
for id in ids_selecionados: |
||||
|
if not id in lista: |
||||
|
lista.append(id) |
||||
|
request.session['carrinho_convenios'] = lista |
||||
|
|
||||
|
def excluir_carrinho(request): |
||||
|
if request.session.has_key('carrinho_convenios'): |
||||
|
del request.session['carrinho_convenios'] |
||||
|
return HttpResponseRedirect('.') |
||||
|
|
||||
|
def deleta_itens_carrinho(request): |
||||
|
if request.method == 'POST': |
||||
|
ids_selecionados = request.POST.getlist('_selected_action') |
||||
|
if request.session.has_key('carrinho_convenios'): |
||||
|
lista = request.session['carrinho_convenios'] |
||||
|
for item in ids_selecionados: |
||||
|
lista.remove(item) |
||||
|
if lista: |
||||
|
request.session['carrinho_convenios'] = lista |
||||
|
else: |
||||
|
del lista; |
||||
|
del request.session['carrinho_convenios'] |
||||
|
|
||||
|
return HttpResponseRedirect('.') |
||||
|
|
||||
|
def visualizar_carrinho(request): |
||||
|
|
||||
|
qs = carrinhoOrGet_for_qs(request) |
||||
|
|
||||
|
paginator = Paginator(qs, 100) |
||||
|
|
||||
|
# Make sure page request is an int. If not, deliver first page. |
||||
|
# Esteja certo de que o `page request` é um inteiro. Se não, mostre a primeira página. |
||||
|
try: |
||||
|
page = int(request.GET.get('page', '1')) |
||||
|
except ValueError: |
||||
|
page = 1 |
||||
|
|
||||
|
# Se o page request (9999) está fora da lista, mostre a última página. |
||||
|
try: |
||||
|
paginas = paginator.page(page) |
||||
|
except (EmptyPage, InvalidPage): |
||||
|
paginas = paginator.page(paginator.num_pages) |
||||
|
|
||||
|
carrinhoIsEmpty = not(request.session.has_key('carrinho_convenios')) |
||||
|
|
||||
|
return render_to_response( |
||||
|
'convenios/carrinho.html', |
||||
|
{ |
||||
|
"ADMIN_MEDIA_PREFIX":settings.ADMIN_MEDIA_PREFIX, |
||||
|
'MEDIA_URL':settings.MEDIA_URL, |
||||
|
'carIsEmpty':carrinhoIsEmpty, |
||||
|
'paginas':paginas, |
||||
|
'query_str':'?'+request.META['QUERY_STRING'] |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
def report(request, id=None): |
||||
|
|
||||
|
if id: |
||||
|
qs = Convenio.objects.filter(pk=id) |
||||
|
else: |
||||
|
qs = carrinhoOrGet_for_qs(request) |
||||
|
|
||||
|
if not qs: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
tipo = '' |
||||
|
data_aceite_has = '' |
||||
|
report = None |
||||
|
if request.POST: |
||||
|
if request.POST.has_key('filtro_casa'): |
||||
|
tipo = request.POST['filtro_casa'] |
||||
|
if request.POST.has_key('data_aceite'): |
||||
|
data_aceite_has = request.POST['data_aceite'] |
||||
|
# Verifica filtro se é por Assembleia |
||||
|
if tipo == 'al': |
||||
|
qs = qs.filter(casa_legislativa__tipo__sigla='AL') |
||||
|
# Verifica se é com data de aceite |
||||
|
if data_aceite_has == 'nao': |
||||
|
report = ConvenioReportSemAceiteAL(queryset=qs) |
||||
|
else: |
||||
|
report = ConvenioPorALReport(queryset=qs) |
||||
|
else: |
||||
|
qs = qs.filter(casa_legislativa__tipo__sigla='CM') |
||||
|
if data_aceite_has == 'nao': |
||||
|
report = ConvenioReportSemAceiteCM(queryset=qs) |
||||
|
else: |
||||
|
report = ConvenioPorCMReport(queryset=qs) |
||||
|
|
||||
|
|
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
if report: |
||||
|
report.generate_by(PDFGenerator, filename=response) |
||||
|
else: |
||||
|
return HttpResponseRedirect('../') |
||||
|
return response |
||||
|
|
||||
|
def casas_estado_to_tabela(casas,convenios,regiao): |
||||
|
|
||||
|
|
||||
|
estados = get_list_or_404(UnidadeFederativa,regiao=regiao) |
||||
|
|
||||
|
class LinhaEstado(): |
||||
|
pass |
||||
|
|
||||
|
lista = [] |
||||
|
|
||||
|
for estado in estados: |
||||
|
linha = LinhaEstado() |
||||
|
|
||||
|
convenios_est = convenios.filter(casa_legislativa__municipio__uf=estado) |
||||
|
convenios_est_publicados = convenios_est.exclude(data_pub_diario=None) |
||||
|
convenios_est_equipados = convenios_est.exclude(data_termo_aceite=None) |
||||
|
|
||||
|
casas_est = casas.filter(municipio__uf=estado) |
||||
|
casas_est_nao_aderidas = casas_est.exclude(convenio__in=convenios_est).distinct() |
||||
|
casas_est_aderidas = casas_est.filter(convenio__in=convenios_est).distinct() |
||||
|
casas_est_conveniadas = casas_est.filter(convenio__in=convenios_est_publicados).distinct() |
||||
|
casas_est_equipadas = casas_est.filter(convenio__in=convenios_est_equipados).distinct() |
||||
|
|
||||
|
linha.lista = ( |
||||
|
casas_est.count(), |
||||
|
casas_est_nao_aderidas.count(), |
||||
|
casas_est_aderidas.count(), |
||||
|
casas_est_conveniadas.count(), |
||||
|
casas_est_equipadas.count(), |
||||
|
) |
||||
|
|
||||
|
linha.estado = estado |
||||
|
|
||||
|
lista.append(linha) |
||||
|
|
||||
|
casas_regiao = casas.filter(municipio__uf__regiao=regiao) |
||||
|
convenios_regiao = convenios.filter(casa_legislativa__municipio__uf__regiao=regiao) |
||||
|
convenios_regiao_publicados = convenios_regiao.exclude(data_pub_diario=None) |
||||
|
convenios_regiao_equipados = convenios_regiao.exclude(data_termo_aceite=None) |
||||
|
sumario = ( |
||||
|
casas_regiao.count(), |
||||
|
casas_regiao.exclude(convenio__in=convenios_regiao).distinct().count(), |
||||
|
casas_regiao.filter(convenio__in=convenios_regiao).distinct().count(), |
||||
|
casas_regiao.filter(convenio__in=convenios_regiao_publicados).distinct().count(), |
||||
|
casas_regiao.filter(convenio__in=convenios_regiao_equipados).distinct().count(), |
||||
|
) |
||||
|
|
||||
|
cabecalho_topo = ( |
||||
|
u'UF', |
||||
|
u'Câmaras municipais', |
||||
|
u'Não Aderidas', |
||||
|
u'Aderidas', |
||||
|
u'Conveniadas', |
||||
|
u'Equipadas' |
||||
|
) |
||||
|
|
||||
|
return { |
||||
|
"linhas":lista, |
||||
|
"cabecalho":cabecalho_topo, |
||||
|
"sumario":sumario, |
||||
|
} |
||||
|
|
||||
|
def report_regiao(request,regiao='NE'): |
||||
|
|
||||
|
if request.POST: |
||||
|
if request.POST.has_key('regiao'): |
||||
|
regiao = request.POST['regiao'] |
||||
|
|
||||
|
REGIAO_CHOICES = { |
||||
|
'SL': 'Sul', |
||||
|
'SD': 'Sudeste', |
||||
|
'CO': 'Centro-Oeste', |
||||
|
'NE': 'Nordeste', |
||||
|
'NO': 'Norte', |
||||
|
} |
||||
|
|
||||
|
projetos = Projeto.objects.all() |
||||
|
|
||||
|
camaras = CasaLegislativa.objects.filter(tipo__sigla='CM') |
||||
|
|
||||
|
tabelas = list() |
||||
|
# Geral |
||||
|
convenios = Convenio.objects.filter(casa_legislativa__tipo__sigla='CM') |
||||
|
tabela = casas_estado_to_tabela(camaras,convenios,regiao) |
||||
|
tabela["projeto"] = "Geral" |
||||
|
|
||||
|
tabelas.append(tabela) |
||||
|
|
||||
|
for projeto in projetos: |
||||
|
convenios_proj = convenios.filter(projeto=projeto) |
||||
|
tabela = casas_estado_to_tabela(camaras, convenios_proj,regiao) |
||||
|
tabela["projeto"] = projeto.nome |
||||
|
tabelas.append(tabela) |
||||
|
|
||||
|
data = datetime.datetime.now().strftime('%d/%m/%Y') |
||||
|
hora = datetime.datetime.now().strftime('%H:%M') |
||||
|
pisa.showLogging() |
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
response['Content-Disposition'] = 'attachment; filename=RelatorioRegiao_' + regiao + '.pdf' |
||||
|
#tabelas = ({'projeto':"PI"},{'projeto':"PML"},) |
||||
|
t = loader.get_template('convenios/tabela_regiao.html') |
||||
|
c = Context({'tabelas':tabelas,'regiao':REGIAO_CHOICES[regiao],'data':data,'hora':hora}) |
||||
|
pdf = pisa.CreatePDF(t.render(c),response) |
||||
|
if not pdf.err: |
||||
|
pisa.startViewer(response) |
||||
|
|
||||
|
return response |
||||
|
|
||||
|
def export_csv(request): |
||||
|
response = HttpResponse(mimetype='text/csv') |
||||
|
response['Content-Disposition'] = 'attachment; filename=convenios.csv' |
||||
|
|
||||
|
csv_writer = csv.writer(response) |
||||
|
convenios = carrinhoOrGet_for_qs(request) |
||||
|
if not convenios: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
atributos = [ u"No. Processo", u"No. Convênio", u"Projeto", u"Casa Legislativa", u"Data de Adesão", u"Data de Convênio", |
||||
|
u"Data da Publicacao no D.O.", u"Data Equipada", ] |
||||
|
|
||||
|
if request.POST: |
||||
|
atributos = request.POST.getlist("itens_csv_selected") |
||||
|
|
||||
|
col_titles = atributos |
||||
|
if u"Casa Legislativa" in col_titles: |
||||
|
pos = col_titles.index(u"Casa Legislativa") + 1 |
||||
|
col_titles.insert(pos, u"uf") |
||||
|
csv_writer.writerow([s.encode("utf-8") for s in col_titles]) |
||||
|
|
||||
|
for convenio in convenios: |
||||
|
lista = [] |
||||
|
for atributo in atributos: |
||||
|
if u"No. Processo" == atributo: |
||||
|
lista.append(convenio.num_processo_sf.encode("utf-8")) |
||||
|
elif u"No. Convênio" == atributo: |
||||
|
lista.append(convenio.num_convenio.encode("utf-8")) |
||||
|
elif u"Projeto" == atributo: |
||||
|
lista.append(convenio.projeto.nome.encode("utf-8")) |
||||
|
elif u"Casa Legislativa" == atributo: |
||||
|
lista.append(convenio.casa_legislativa.nome.encode("utf-8")) |
||||
|
lista.append(convenio.casa_legislativa.municipio.uf.sigla.encode("utf-8")) |
||||
|
elif u"Data de Adesão" == atributo: |
||||
|
data = '' |
||||
|
if convenio.data_adesao: |
||||
|
data = convenio.data_adesao.strftime("%d/%m/%Y") |
||||
|
lista.append(data.encode("utf-8")) |
||||
|
elif u"Data de Convênio" == atributo: |
||||
|
data = '' |
||||
|
if convenio.data_retorno_assinatura: |
||||
|
data = convenio.data_retorno_assinatura.strftime("%d/%m/%Y") |
||||
|
lista.append(data.encode("utf-8")) |
||||
|
elif u"Data da Publicacao no D.O." == atributo: |
||||
|
data = '' |
||||
|
if convenio.data_pub_diario: |
||||
|
data = convenio.data_pub_diario.strftime("%d/%m/%Y") |
||||
|
lista.append(data.encode("utf-8")) |
||||
|
data = '' |
||||
|
elif u"Data Equipada" == atributo: |
||||
|
if convenio.data_termo_aceite: |
||||
|
data = convenio.data_termo_aceite.strftime("%d/%m/%Y") |
||||
|
lista.append(data.encode("utf-8")) |
||||
|
else: |
||||
|
pass |
||||
|
|
||||
|
csv_writer.writerow(lista) |
||||
|
|
||||
|
return response |
||||
|
|
@ -0,0 +1,129 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from datetime import datetime |
||||
|
from django.contrib import admin |
||||
|
from eav.admin import BaseEntityAdmin, BaseSchemaAdmin |
||||
|
from sigi.apps.diagnosticos.models import Diagnostico, Pergunta, Escolha, Equipe, Anexo, Categoria |
||||
|
from sigi.apps.diagnosticos.forms import DiagnosticoForm |
||||
|
from sigi.apps.contatos.models import UnidadeFederativa |
||||
|
|
||||
|
def publicar_diagnostico(self, request, queryset): |
||||
|
for registro in queryset: |
||||
|
diagnostico = Diagnostico.objects.get(pk=registro.id) |
||||
|
diagnostico.publicado = True |
||||
|
diagnostico.data_publicacao= datetime.now() |
||||
|
diagnostico.save() |
||||
|
|
||||
|
# Enviando o email avisando que o diagnóstico foi publicado |
||||
|
email = diagnostico.responsavel.user.email |
||||
|
if email: |
||||
|
diagnostico.email_diagnostico_publicado(email, request.get_host()) |
||||
|
self.message_user(request, "Diagnóstico(s) publicado(s) com sucesso!") |
||||
|
publicar_diagnostico.short_description = u""" |
||||
|
Definir diagnósticos como publicado""" |
||||
|
|
||||
|
|
||||
|
def despublicar_diagnostico(self, request, queryset): |
||||
|
queryset.update(publicado=False) |
||||
|
despublicar_diagnostico.short_description = u""" |
||||
|
Definir diagnósticos como não publicado""" |
||||
|
|
||||
|
class EquipeInline(admin.TabularInline): |
||||
|
model = Equipe |
||||
|
|
||||
|
class AnexosInline(admin.TabularInline): |
||||
|
model = Anexo |
||||
|
extra = 2 |
||||
|
exclude = ['data_pub', ] |
||||
|
|
||||
|
class AnexoAdmin(admin.ModelAdmin): |
||||
|
date_hierarchy = 'data_pub' |
||||
|
exclude = ['data_pub', ] |
||||
|
list_display = ('arquivo', 'descricao', 'data_pub', 'diagnostico') |
||||
|
raw_id_fields = ('diagnostico',) |
||||
|
search_fields = ('descricao', 'diagnostico__id', 'arquivo', |
||||
|
'diagnostico__casa_legislativa__nome') |
||||
|
|
||||
|
class DiagnosticoAdmin(BaseEntityAdmin): |
||||
|
form = DiagnosticoForm |
||||
|
actions = [publicar_diagnostico, despublicar_diagnostico] |
||||
|
inlines = (EquipeInline, AnexosInline) |
||||
|
search_fields = ('casa_legislativa__nome',) |
||||
|
list_display = ('casa_legislativa','get_uf', 'data_visita_inicio', 'data_visita_fim', 'responsavel', 'publicado') |
||||
|
list_filter = ('publicado', 'casa_legislativa', 'data_publicacao', 'data_visita_inicio', 'data_visita_fim') |
||||
|
raw_id_fields = ('casa_legislativa',) |
||||
|
ordering = ('casa_legislativa',) |
||||
|
|
||||
|
eav_fieldsets = [ |
||||
|
(u'00. Identificação do Diagnóstico', {'fields': ('responsavel', 'data_visita_inicio', 'data_visita_fim',)}), |
||||
|
(u'01. Identificação da Casa Legislativa', {'fields': ('casa_legislativa',)}), |
||||
|
(u'02. Identificação de Competências da Casa Legislativa', {'fields': ()}) |
||||
|
] |
||||
|
|
||||
|
# popula o eav fieldsets ordenando as categorias e as perguntas |
||||
|
# para serem exibidas no admin |
||||
|
for categoria in Categoria.objects.all(): |
||||
|
# ordena as perguntas pelo title e utiliza o name no fieldset |
||||
|
perguntas_by_title = [(p.title, p.name) for p in categoria.perguntas.all()] |
||||
|
perguntas = [pergunta[1] for pergunta in sorted(perguntas_by_title)] |
||||
|
|
||||
|
eav_fieldsets.append((categoria, { |
||||
|
'fields': tuple(perguntas), |
||||
|
'classes': ['collapse'] |
||||
|
})) |
||||
|
|
||||
|
def get_uf(self, obj): |
||||
|
return '%s' % (obj.casa_legislativa.municipio.uf) |
||||
|
get_uf.short_description = 'UF' |
||||
|
get_uf.admin_order_field = 'casa_legislativa__municipio__uf__nome' |
||||
|
|
||||
|
def lookup_allowed(self, lookup, value): |
||||
|
return super(DiagnosticoAdmin, self).lookup_allowed(lookup, value) or \ |
||||
|
lookup in ['casa_legislativa__municipio__uf__codigo_ibge__exact'] |
||||
|
|
||||
|
def changelist_view(self, request, extra_context=None): |
||||
|
import re |
||||
|
request.GET._mutable=True |
||||
|
if 'data_visita_inicio__gte' in request.GET: |
||||
|
value = request.GET.get('data_visita_inicio__gte','') |
||||
|
if value == '': |
||||
|
del request.GET['data_visita_inicio__gte'] |
||||
|
elif re.match('^\d*$', value): # Year only |
||||
|
request.GET['data_visita_inicio__gte'] = "%s-01-01" % value #Complete with january 1st |
||||
|
elif re.match('^\d*\D\d*$', value): # Year and month |
||||
|
request.GET['data_visita_inicio__gte'] = '%s-01' % value #Complete with 1st day of month |
||||
|
if 'data_visita_inicio__lte' in request.GET: |
||||
|
value = request.GET.get('data_visita_inicio__lte','') |
||||
|
if value == '': |
||||
|
del request.GET['data_visita_inicio__lte'] |
||||
|
elif re.match('^\d*$', value): # Year only |
||||
|
request.GET['data_visita_inicio__lte'] = "%s-01-01" % value #Complete with january 1st |
||||
|
elif re.match('^\d*\D\d*$', value): # Year and month |
||||
|
request.GET['data_visita_inicio__lte'] = '%s-01' % value #Complete with 1st day of month |
||||
|
request.GET._mutable=False |
||||
|
|
||||
|
return super(DiagnosticoAdmin, self).changelist_view(request, extra_context) |
||||
|
|
||||
|
class EscolhaAdmin(admin.ModelAdmin): |
||||
|
search_fields = ('title',) |
||||
|
list_display = ('title', 'schema', 'schema_to_open') |
||||
|
raw_id_fields = ('schema', 'schema_to_open') |
||||
|
ordering = ('schema', 'title') |
||||
|
|
||||
|
class EscolhaInline(admin.TabularInline): |
||||
|
model = Escolha |
||||
|
fk_name = 'schema' |
||||
|
raw_id_fields = ('schema_to_open',) |
||||
|
verbose_name = 'Escolhas (apenas para choices ou multiple choices)' |
||||
|
extra = 0 |
||||
|
|
||||
|
class PerguntaAdmin (BaseSchemaAdmin): |
||||
|
search_fields = ('title', 'help_text', 'name',) |
||||
|
list_display = ('title', 'categoria', 'datatype', 'help_text', 'required') |
||||
|
list_filter = ('datatype', 'categoria', 'required') |
||||
|
inlines = (EscolhaInline,) |
||||
|
|
||||
|
admin.site.register(Diagnostico, DiagnosticoAdmin) |
||||
|
admin.site.register(Pergunta, PerguntaAdmin) |
||||
|
admin.site.register(Escolha, EscolhaAdmin) |
||||
|
admin.site.register(Anexo, AnexoAdmin) |
||||
|
admin.site.register(Categoria) |
@ -0,0 +1,23 @@ |
|||||
|
# -*- coding: utf8 -*- |
||||
|
|
||||
|
from django.template import RequestContext |
||||
|
from django.shortcuts import render_to_response |
||||
|
from sigi.apps.diagnosticos.models import Diagnostico |
||||
|
|
||||
|
def validate_diagnostico(func): |
||||
|
def decorator(request, id_diagnostico, *args, **kwargs): |
||||
|
""" Retorna 404 caso o diagnostico esteja publicado |
||||
|
ou o usuario nao seja um membro da equipe |
||||
|
""" |
||||
|
try: |
||||
|
diagnostico = Diagnostico.objects.filter(publicado=False).get(pk=id_diagnostico) |
||||
|
if (request.user.servidor in diagnostico.membros): |
||||
|
# continua o processamento normal da view |
||||
|
return func(request, id_diagnostico, *args, **kwargs) |
||||
|
except Diagnostico.DoesNotExist: |
||||
|
pass |
||||
|
|
||||
|
# renderiza a pagina de 404 |
||||
|
context = RequestContext(request, {}) |
||||
|
return render_to_response('mobile/404.html', context) |
||||
|
return decorator |
File diff suppressed because it is too large
@ -0,0 +1,171 @@ |
|||||
|
# -*- coding: utf8 -*- |
||||
|
|
||||
|
from copy import deepcopy |
||||
|
from django import forms |
||||
|
from django.forms.forms import BoundField |
||||
|
from django.forms import (BooleanField, CharField, DateField, |
||||
|
FloatField, ModelChoiceField, Textarea, |
||||
|
ModelMultipleChoiceField) |
||||
|
from django.contrib.contenttypes.generic import generic_inlineformset_factory |
||||
|
from sigi.apps.casas.models import CasaLegislativa, Funcionario |
||||
|
from sigi.apps.contatos.models import Telefone |
||||
|
from sigi.apps.diagnosticos.models import Diagnostico |
||||
|
from sigi.apps.diagnosticos.widgets import EavCheckboxSelectMultiple, EavRadioSelect |
||||
|
from eav.forms import BaseDynamicEntityForm |
||||
|
from eav.fields import RangeField |
||||
|
|
||||
|
class DiagnosticoForm(BaseDynamicEntityForm): |
||||
|
"""Classe responsável por contruir o formulário, |
||||
|
vinculando ao modelo Diagnostico |
||||
|
""" |
||||
|
model = Diagnostico |
||||
|
|
||||
|
def __init__(self, *args, **kwargs): |
||||
|
super(DiagnosticoForm, self).__init__(*args, **kwargs) |
||||
|
|
||||
|
for k, f in self.fields.iteritems(): |
||||
|
if isinstance(f, CharField): |
||||
|
f.widget = forms.widgets.Textarea(attrs={'cols':'80'}) |
||||
|
|
||||
|
class DiagnosticoMobileForm(BaseDynamicEntityForm): |
||||
|
"""Classe responsável por construir o formulário |
||||
|
para ser usado no ambiente mobile, a partir do |
||||
|
do modelo Diagnostico, como também organizar sua |
||||
|
estrutura via categorias. |
||||
|
""" |
||||
|
|
||||
|
FIELD_CLASSES = { |
||||
|
'text': CharField, |
||||
|
'float': FloatField, |
||||
|
'date': DateField, |
||||
|
'bool': BooleanField, |
||||
|
'one': ModelChoiceField, |
||||
|
'many': ModelMultipleChoiceField, |
||||
|
'range': RangeField, |
||||
|
} |
||||
|
|
||||
|
FIELD_EXTRA = { |
||||
|
'one': {'widget': EavRadioSelect}, |
||||
|
'many': {'widget': EavCheckboxSelectMultiple}, |
||||
|
} |
||||
|
|
||||
|
FIELD_WIDGET = { |
||||
|
'consideracoes_gerais' : {'widget': Textarea}, |
||||
|
'descreva_5_cursos_prioritarios_para_treinamento_de_parlamentares_da_camara_municipal' : {'widget': Textarea}, |
||||
|
'descreva_5_cursos_prioritarios_para_treinamento_de_servidores_da_camara_municipal' : {'widget': Textarea}, |
||||
|
'sugestoes_para_a_area_de_capacitacao' : {'widget': Textarea}, |
||||
|
'sugestoes_para_a_area_de_comunicacao' : {'widget': Textarea}, |
||||
|
'sugestoes_para_a_area_de_informacao' : {'widget': Textarea}, |
||||
|
'sugestoes_para_a_area_de_ti' : {'widget': Textarea}, |
||||
|
'inscricoes_para_lista_gitec' : {'widget': Textarea}, |
||||
|
'inscricoes_para_lista_gial' : {'widget': Textarea}, |
||||
|
'inscricoes_para_lista_gicom' : {'widget': Textarea}, |
||||
|
} |
||||
|
class Meta: |
||||
|
model = Diagnostico |
||||
|
|
||||
|
def __init__(self, data=None, category=None, *args, **kwargs): |
||||
|
super(BaseDynamicEntityForm, self).__init__(data, *args, **kwargs) |
||||
|
self._build_dynamics_fields(category) |
||||
|
|
||||
|
def __iter__(self): |
||||
|
# ordena os campos do formulario usando o atributo label |
||||
|
fields_by_label = [(field.label, name, field) for name, field in self.fields.items()] |
||||
|
for label, name, field in sorted(fields_by_label): |
||||
|
yield BoundField(self, field, name) |
||||
|
|
||||
|
def _build_dynamics_fields(self, category): |
||||
|
"""Método da classe ``BaseDynamicEntityForm`` sobrescrita, |
||||
|
para que as perguntas sejam agrupadas dentro das suas |
||||
|
categorias. |
||||
|
* category = ID da Categoria |
||||
|
""" |
||||
|
# Caso seja as duas primeiras categorias, utilize |
||||
|
# os campos do modelo |
||||
|
if int(category) in (0, 1, ): |
||||
|
self.fields = deepcopy(self.base_fields) |
||||
|
else: |
||||
|
self.fields = dict() |
||||
|
|
||||
|
# Se determinada pergunta é da categoria pesquisada, |
||||
|
# então, gere o campo no formulário. |
||||
|
for schema in self.instance.get_schemata(int(category)): |
||||
|
|
||||
|
defaults = { |
||||
|
'label': schema.title, |
||||
|
'required': schema.required, |
||||
|
'help_text': schema.help_text, |
||||
|
} |
||||
|
|
||||
|
datatype = schema.datatype |
||||
|
if datatype == schema.TYPE_MANY: |
||||
|
choices = getattr(self.instance, schema.name) |
||||
|
defaults.update({'queryset': schema.get_choices(), |
||||
|
'initial': [x.pk for x in choices]}) |
||||
|
elif datatype == schema.TYPE_ONE: |
||||
|
choice = getattr(self.instance, schema.name) |
||||
|
defaults.update({'queryset': schema.get_choices(), |
||||
|
'initial': choice.pk if choice else None, |
||||
|
# if schema is required remove --------- from ui |
||||
|
'empty_label': None if schema.required else u"---------"}) |
||||
|
|
||||
|
extra = self.FIELD_EXTRA.get(datatype, {}) |
||||
|
extra.update(self.FIELD_WIDGET.get(schema.name, {})) |
||||
|
if hasattr(extra, '__call__'): |
||||
|
extra = extra(schema) |
||||
|
defaults.update(extra) |
||||
|
|
||||
|
MappedField = self.FIELD_CLASSES[datatype] |
||||
|
self.fields[schema.name] = MappedField(**defaults) |
||||
|
|
||||
|
# fill initial data (if attribute was already defined) |
||||
|
value = getattr(self.instance, schema.name) |
||||
|
if value and not datatype in (schema.TYPE_ONE, schema.TYPE_MANY): # choices are already done above |
||||
|
self.initial[schema.name] = value |
||||
|
|
||||
|
|
||||
|
class CasaLegislativaMobileForm(forms.ModelForm): |
||||
|
data_instalacao = forms.DateField(label = u'Data de instalação da Casa Legislativa', required=False) |
||||
|
|
||||
|
class Meta: |
||||
|
model = CasaLegislativa |
||||
|
fields = ('cnpj', 'data_criacao', 'data_instalacao', 'logradouro', 'bairro', 'cep', 'email', 'pagina_web') |
||||
|
|
||||
|
def __init__(self, *args, **kwargs): |
||||
|
super(CasaLegislativaMobileForm, self).__init__(*args, **kwargs) |
||||
|
self.fields['data_criacao'] = forms.DateField( |
||||
|
label = u'Data de criação do Município', |
||||
|
initial = self.instance.municipio.data_criacao, |
||||
|
required=False |
||||
|
) |
||||
|
|
||||
|
def save(self, commit=True): |
||||
|
super(CasaLegislativaMobileForm, self).save(commit=True) |
||||
|
self.instance.municipio.data_criacao = self.cleaned_data['data_criacao'] |
||||
|
if commit: |
||||
|
self.instance.municipio.save() |
||||
|
return self.instance |
||||
|
|
||||
|
class TelefoneMobileForm(forms.ModelForm): |
||||
|
pass |
||||
|
class Meta: |
||||
|
model = Telefone |
||||
|
fields = ('numero', 'tipo') |
||||
|
|
||||
|
class FuncionariosMobileForm(forms.ModelForm): |
||||
|
TelefoneFormSet = generic_inlineformset_factory(Telefone, TelefoneMobileForm, extra=1, can_delete=False) |
||||
|
|
||||
|
def __init__(self, data=None, prefix=None, instance=None, *args, **kwargs): |
||||
|
super(FuncionariosMobileForm, self).__init__(data, prefix=prefix, instance=instance, *args, **kwargs) |
||||
|
self.telefones = self.TelefoneFormSet(data, prefix=prefix, instance=instance) |
||||
|
|
||||
|
def is_valid(self): |
||||
|
return self.telefones.is_valid() and super(FuncionariosMobileForm, self).is_valid() |
||||
|
|
||||
|
def save(self, commit=True): |
||||
|
self.telefones.save(commit) |
||||
|
return super(FuncionariosMobileForm, self).save(commit) |
||||
|
|
||||
|
class Meta: |
||||
|
model = Funcionario |
||||
|
fields = ('nome', 'email', 'cargo', 'funcao', 'tempo_de_servico', 'sexo') |
@ -0,0 +1,247 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from datetime import datetime |
||||
|
from django.db import models |
||||
|
|
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
from sigi.apps.utils import SearchField |
||||
|
from sigi.apps.utils.email import enviar_email |
||||
|
from eav.models import BaseChoice, BaseEntity, BaseSchema, BaseAttribute |
||||
|
|
||||
|
|
||||
|
class Diagnostico(BaseEntity): |
||||
|
""" Modelo para representar unm diagnostico realizado |
||||
|
em uma Casa Legislativa |
||||
|
""" |
||||
|
casa_legislativa = models.ForeignKey( |
||||
|
'casas.CasaLegislativa', |
||||
|
verbose_name='Casa Legislativa') |
||||
|
|
||||
|
# campo de busca em caixa baixa e sem acento |
||||
|
search_text = SearchField(field_names=['casa_legislativa']) |
||||
|
casa_legislativa.casa_uf_filter = True |
||||
|
# casa_legislativa.casa_tipo_filter = True |
||||
|
data_visita_inicio = models.DateField( |
||||
|
u'data inicial da visita', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
) |
||||
|
data_visita_fim = models.DateField( |
||||
|
u'data final da visita', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
) |
||||
|
publicado = models.BooleanField(default=False) |
||||
|
data_publicacao = models.DateField( |
||||
|
u'data de publicação do diagnóstico', |
||||
|
null=True, |
||||
|
blank=True, |
||||
|
) |
||||
|
|
||||
|
responsavel = models.ForeignKey('servidores.Servidor', |
||||
|
verbose_name=u'responsável') |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name, verbose_name_plural = u'diagnóstico', u'diagnósticos' |
||||
|
|
||||
|
@property |
||||
|
def membros(self): |
||||
|
""" Retorna a lista de membros do diagnostico, |
||||
|
isto é responsavel + equipe |
||||
|
""" |
||||
|
membros = set([self.responsavel]) |
||||
|
for equipe in self.equipe_set.all(): |
||||
|
membros.add(equipe.membro) |
||||
|
return list(membros) |
||||
|
|
||||
|
@property |
||||
|
def contatos_respondidos(self): |
||||
|
"""Retorna uma lista de contatos que foram |
||||
|
respondidos |
||||
|
""" |
||||
|
return list(self.casa_legislativa.funcionario_set.all()) |
||||
|
|
||||
|
@property |
||||
|
def categorias_respondidas(self): |
||||
|
""" Retorna uma listas das categorias dinamicas que tem |
||||
|
ao menos uma resposta |
||||
|
""" |
||||
|
# unifica as categorias das perguntas dessas respostas |
||||
|
categoria_com_respostas = set([r.schema.categoria for r in self._get_respostas()]) |
||||
|
|
||||
|
return list(categoria_com_respostas) |
||||
|
|
||||
|
def _get_respostas(self): |
||||
|
# obtem todas as respostas dinamicas desse diagnostico |
||||
|
respostas = Resposta.objects.filter(entity_id=self.id).all() |
||||
|
|
||||
|
# remove as respostas nulas ou em branco |
||||
|
return [r for r in respostas if r._get_value()] |
||||
|
|
||||
|
def email_diagnostico_publicado(self, from_email, host): |
||||
|
"""Enviando email quando o diagnóstico for publicado. Os |
||||
|
argumentos acima são: |
||||
|
* from_email - Email de remetente |
||||
|
* host - O Host do sistema, para ser usado na |
||||
|
construção do endereço do diagnóstico |
||||
|
""" |
||||
|
enviar_email(from_email, u"Diagnóstico publicado", |
||||
|
'diagnosticos/email_diagnostico_publicado.txt', |
||||
|
{ |
||||
|
'responsavel': self.responsavel.nome_completo, |
||||
|
'casa_legislativa': self.casa_legislativa, |
||||
|
'data_diagnostico': self.data_visita_inicio, |
||||
|
'host': host, |
||||
|
'url_diagnostico': self.get_absolute_url(), |
||||
|
'status': u"Publicado", |
||||
|
}) |
||||
|
|
||||
|
def email_diagnostico_alterado(self, from_email, host): |
||||
|
"""Enviando email quando o status do diagnóstico |
||||
|
for alterado. Os argumentos acima são: |
||||
|
* from_email - Email do destinatário |
||||
|
* host - O Host do sistema, para ser usado na |
||||
|
construção do endereço do diagnóstico |
||||
|
""" |
||||
|
enviar_email(from_email, u"Diagnóstico alterado", |
||||
|
'diagnosticos/email_diagnostico_alterado.txt', |
||||
|
{ |
||||
|
'servidor': self.responsavel.nome_completo, |
||||
|
'casa_legislativa': self.casa_legislativa, |
||||
|
'data_diagnostico': self.data_visita_inicio, |
||||
|
'host': host, |
||||
|
'url_diagnostico': self.get_absolute_url(), |
||||
|
'status': "Alterado", |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
def get_schemata(self, category=None, *args, **kwargs): |
||||
|
""" Se existir uma categoria retorna apenas as questões dessa. |
||||
|
""" |
||||
|
schemas = super(Diagnostico,self).get_schemata(*args, **kwargs) |
||||
|
if category: |
||||
|
schemas = [s for s in schemas if s.categoria_id == category] |
||||
|
schemas= sorted(schemas, lambda x,y: cmp(x.title, y.title)) |
||||
|
|
||||
|
return schemas |
||||
|
|
||||
|
@classmethod |
||||
|
def get_schemata_for_model(self): |
||||
|
return Pergunta.objects.all() |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return str(self.casa_legislativa).decode('utf8') |
||||
|
|
||||
|
def get_absolute_url(self): |
||||
|
return "/sigi/diagnosticos/diagnostico/%i.pdf" % (self.id, ) |
||||
|
|
||||
|
|
||||
|
class Categoria(models.Model): |
||||
|
""" Modelo para representar a categoria de uma pergunta |
||||
|
e sua ordem na hora de exibir no formulário |
||||
|
""" |
||||
|
nome = models.CharField(max_length=255) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('nome',) |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.nome |
||||
|
|
||||
|
|
||||
|
class Pergunta(BaseSchema): |
||||
|
""" Modelo que representa uma pergunta no questionário |
||||
|
e sua ordem dentro da categoria |
||||
|
|
||||
|
Uma pergunta tem o nome e o tipo da resposta |
||||
|
""" |
||||
|
categoria = models.ForeignKey(Categoria, related_name='perguntas') |
||||
|
|
||||
|
def group_choices(self): |
||||
|
from django.db import connection, transaction |
||||
|
cursor = connection.cursor() |
||||
|
|
||||
|
cursor.execute(""" |
||||
|
SELECT choice_id, sum(1) |
||||
|
FROM diagnosticos_resposta |
||||
|
WHERE schema_id=%s and choice_id is not null |
||||
|
GROUP BY choice_id; |
||||
|
""", [self.id]) |
||||
|
|
||||
|
return [ |
||||
|
(Escolha.objects.get(id=int(row[0])), row[1]) |
||||
|
for row in cursor.fetchall() |
||||
|
] |
||||
|
|
||||
|
def total_anwsers(self): |
||||
|
from django.db import connection, transaction |
||||
|
cursor = connection.cursor() |
||||
|
|
||||
|
cursor.execute(""" |
||||
|
SELECT sum(1) |
||||
|
FROM diagnosticos_resposta |
||||
|
WHERE schema_id=%s |
||||
|
""", [self.id]) |
||||
|
|
||||
|
return cursor.fetchone() |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('title',) |
||||
|
verbose_name, verbose_name_plural = 'pergunta', 'perguntas' |
||||
|
|
||||
|
|
||||
|
class Escolha(BaseChoice): |
||||
|
""" Perguntas de multiplas escolhas tem as opções |
||||
|
cadastradas neste modelo |
||||
|
""" |
||||
|
schema = models.ForeignKey(Pergunta, |
||||
|
related_name='choices', verbose_name='pergunta') |
||||
|
schema_to_open = models.ForeignKey(Pergunta, related_name='', |
||||
|
verbose_name='pergunta para abrir', blank=True, null=True) |
||||
|
ordem = models.PositiveIntegerField(blank=True, null=True) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('schema','ordem') |
||||
|
verbose_name, verbose_name_plural = 'escolha', 'escolhas' |
||||
|
|
||||
|
|
||||
|
class Resposta(BaseAttribute): |
||||
|
""" Modelo para guardar as respostas das perguntas |
||||
|
de um diagnosico |
||||
|
""" |
||||
|
schema = models.ForeignKey(Pergunta, related_name='attrs', |
||||
|
verbose_name='pergunta') |
||||
|
choice = models.ForeignKey(Escolha, verbose_name='escolha', |
||||
|
blank=True, null=True) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name, verbose_name_plural = 'resposta', 'respostas' |
||||
|
|
||||
|
|
||||
|
class Equipe(models.Model): |
||||
|
""" Modelo que representa a equipe de um diagnóstico |
||||
|
""" |
||||
|
diagnostico = models.ForeignKey(Diagnostico) |
||||
|
membro = models.ForeignKey('servidores.Servidor') |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name, verbose_name_plural = u'equipe', u'equipe' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.membro.__unicode__() |
||||
|
|
||||
|
|
||||
|
class Anexo(models.Model): |
||||
|
""" Modelo para representar os documentos levantados |
||||
|
no processo de diagnóstico. Podem ser fotos, contratos, etc. |
||||
|
""" |
||||
|
diagnostico = models.ForeignKey(Diagnostico, verbose_name=u'diagnóstico') |
||||
|
arquivo = models.FileField(upload_to='apps/diagnostico/anexo/arquivo',) |
||||
|
descricao = models.CharField('descrição', max_length='70') |
||||
|
data_pub = models.DateTimeField('data da publicação do anexo', |
||||
|
default=datetime.now) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('-data_pub',) |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return unicode(self.arquivo.name) |
@ -0,0 +1,401 @@ |
|||||
|
""" |
||||
|
A smarter {% if %} tag for django templates. |
||||
|
|
||||
|
While retaining current Django functionality, it also handles equality, |
||||
|
greater than and less than operators. Some common case examples:: |
||||
|
|
||||
|
{% if articles|length >= 5 %}...{% endif %} |
||||
|
{% if "ifnotequal tag" != "beautiful" %}...{% endif %} |
||||
|
""" |
||||
|
import unittest |
||||
|
from django import template |
||||
|
|
||||
|
|
||||
|
register = template.Library() |
||||
|
|
||||
|
|
||||
|
#============================================================================== |
||||
|
# Calculation objects |
||||
|
#============================================================================== |
||||
|
|
||||
|
class BaseCalc(object): |
||||
|
def __init__(self, var1, var2=None, negate=False): |
||||
|
self.var1 = var1 |
||||
|
self.var2 = var2 |
||||
|
self.negate = negate |
||||
|
|
||||
|
def resolve(self, context): |
||||
|
try: |
||||
|
var1, var2 = self.resolve_vars(context) |
||||
|
outcome = self.calculate(var1, var2) |
||||
|
except: |
||||
|
outcome = False |
||||
|
if self.negate: |
||||
|
return not outcome |
||||
|
return outcome |
||||
|
|
||||
|
def resolve_vars(self, context): |
||||
|
var2 = self.var2 and self.var2.resolve(context) |
||||
|
return self.var1.resolve(context), var2 |
||||
|
|
||||
|
def calculate(self, var1, var2): |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
|
||||
|
class Or(BaseCalc): |
||||
|
def calculate(self, var1, var2): |
||||
|
return var1 or var2 |
||||
|
|
||||
|
|
||||
|
class And(BaseCalc): |
||||
|
def calculate(self, var1, var2): |
||||
|
return var1 and var2 |
||||
|
|
||||
|
|
||||
|
class Equals(BaseCalc): |
||||
|
def calculate(self, var1, var2): |
||||
|
return var1 == var2 |
||||
|
|
||||
|
|
||||
|
class Greater(BaseCalc): |
||||
|
def calculate(self, var1, var2): |
||||
|
return var1 > var2 |
||||
|
|
||||
|
|
||||
|
class GreaterOrEqual(BaseCalc): |
||||
|
def calculate(self, var1, var2): |
||||
|
return var1 >= var2 |
||||
|
|
||||
|
|
||||
|
class In(BaseCalc): |
||||
|
def calculate(self, var1, var2): |
||||
|
return var1 in var2 |
||||
|
|
||||
|
|
||||
|
#============================================================================== |
||||
|
# Tests |
||||
|
#============================================================================== |
||||
|
|
||||
|
class TestVar(object): |
||||
|
""" |
||||
|
A basic self-resolvable object similar to a Django template variable. Used |
||||
|
to assist with tests. |
||||
|
""" |
||||
|
def __init__(self, value): |
||||
|
self.value = value |
||||
|
|
||||
|
def resolve(self, context): |
||||
|
return self.value |
||||
|
|
||||
|
|
||||
|
class SmartIfTests(unittest.TestCase): |
||||
|
def setUp(self): |
||||
|
self.true = TestVar(True) |
||||
|
self.false = TestVar(False) |
||||
|
self.high = TestVar(9000) |
||||
|
self.low = TestVar(1) |
||||
|
|
||||
|
def assertCalc(self, calc, context=None): |
||||
|
""" |
||||
|
Test a calculation is True, also checking the inverse "negate" case. |
||||
|
""" |
||||
|
context = context or {} |
||||
|
self.assert_(calc.resolve(context)) |
||||
|
calc.negate = not calc.negate |
||||
|
self.assertFalse(calc.resolve(context)) |
||||
|
|
||||
|
def assertCalcFalse(self, calc, context=None): |
||||
|
""" |
||||
|
Test a calculation is False, also checking the inverse "negate" case. |
||||
|
""" |
||||
|
context = context or {} |
||||
|
self.assertFalse(calc.resolve(context)) |
||||
|
calc.negate = not calc.negate |
||||
|
self.assert_(calc.resolve(context)) |
||||
|
|
||||
|
def test_or(self): |
||||
|
self.assertCalc(Or(self.true)) |
||||
|
self.assertCalcFalse(Or(self.false)) |
||||
|
self.assertCalc(Or(self.true, self.true)) |
||||
|
self.assertCalc(Or(self.true, self.false)) |
||||
|
self.assertCalc(Or(self.false, self.true)) |
||||
|
self.assertCalcFalse(Or(self.false, self.false)) |
||||
|
|
||||
|
def test_and(self): |
||||
|
self.assertCalc(And(self.true, self.true)) |
||||
|
self.assertCalcFalse(And(self.true, self.false)) |
||||
|
self.assertCalcFalse(And(self.false, self.true)) |
||||
|
self.assertCalcFalse(And(self.false, self.false)) |
||||
|
|
||||
|
def test_equals(self): |
||||
|
self.assertCalc(Equals(self.low, self.low)) |
||||
|
self.assertCalcFalse(Equals(self.low, self.high)) |
||||
|
|
||||
|
def test_greater(self): |
||||
|
self.assertCalc(Greater(self.high, self.low)) |
||||
|
self.assertCalcFalse(Greater(self.low, self.low)) |
||||
|
self.assertCalcFalse(Greater(self.low, self.high)) |
||||
|
|
||||
|
def test_greater_or_equal(self): |
||||
|
self.assertCalc(GreaterOrEqual(self.high, self.low)) |
||||
|
self.assertCalc(GreaterOrEqual(self.low, self.low)) |
||||
|
self.assertCalcFalse(GreaterOrEqual(self.low, self.high)) |
||||
|
|
||||
|
def test_in(self): |
||||
|
list_ = TestVar([1,2,3]) |
||||
|
invalid_list = TestVar(None) |
||||
|
self.assertCalc(In(self.low, list_)) |
||||
|
self.assertCalcFalse(In(self.low, invalid_list)) |
||||
|
|
||||
|
def test_parse_bits(self): |
||||
|
var = IfParser([True]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
var = IfParser([False]).parse() |
||||
|
self.assertFalse(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([False, 'or', True]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([False, 'and', True]).parse() |
||||
|
self.assertFalse(var.resolve({})) |
||||
|
|
||||
|
var = IfParser(['not', False, 'and', 'not', False]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
|
||||
|
var = IfParser(['not', 'not', True]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([1, '=', 1]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([1, 'not', '=', 1]).parse() |
||||
|
self.assertFalse(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([1, 'not', 'not', '=', 1]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([1, '!=', 1]).parse() |
||||
|
self.assertFalse(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([3, '>', 2]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([1, '<', 2]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([2, 'not', 'in', [2, 3]]).parse() |
||||
|
self.assertFalse(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([1, 'or', 1, '=', 2]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
|
||||
|
def test_boolean(self): |
||||
|
var = IfParser([True, 'and', True, 'and', True]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
var = IfParser([False, 'or', False, 'or', True]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
var = IfParser([True, 'and', False, 'or', True]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
var = IfParser([False, 'or', True, 'and', True]).parse() |
||||
|
self.assert_(var.resolve({})) |
||||
|
|
||||
|
var = IfParser([True, 'and', True, 'and', False]).parse() |
||||
|
self.assertFalse(var.resolve({})) |
||||
|
var = IfParser([False, 'or', False, 'or', False]).parse() |
||||
|
self.assertFalse(var.resolve({})) |
||||
|
var = IfParser([False, 'or', True, 'and', False]).parse() |
||||
|
self.assertFalse(var.resolve({})) |
||||
|
var = IfParser([False, 'and', True, 'or', False]).parse() |
||||
|
self.assertFalse(var.resolve({})) |
||||
|
|
||||
|
def test_invalid(self): |
||||
|
self.assertRaises(ValueError, IfParser(['not']).parse) |
||||
|
self.assertRaises(ValueError, IfParser(['==']).parse) |
||||
|
self.assertRaises(ValueError, IfParser([1, 'in']).parse) |
||||
|
self.assertRaises(ValueError, IfParser([1, '>', 'in']).parse) |
||||
|
self.assertRaises(ValueError, IfParser([1, '==', 'not', 'not']).parse) |
||||
|
self.assertRaises(ValueError, IfParser([1, 2]).parse) |
||||
|
|
||||
|
|
||||
|
OPERATORS = { |
||||
|
'=': (Equals, True), |
||||
|
'==': (Equals, True), |
||||
|
'!=': (Equals, False), |
||||
|
'>': (Greater, True), |
||||
|
'>=': (GreaterOrEqual, True), |
||||
|
'<=': (Greater, False), |
||||
|
'<': (GreaterOrEqual, False), |
||||
|
'or': (Or, True), |
||||
|
'and': (And, True), |
||||
|
'in': (In, True), |
||||
|
} |
||||
|
BOOL_OPERATORS = ('or', 'and') |
||||
|
|
||||
|
|
||||
|
class IfParser(object): |
||||
|
error_class = ValueError |
||||
|
|
||||
|
def __init__(self, tokens): |
||||
|
self.tokens = tokens |
||||
|
|
||||
|
def _get_tokens(self): |
||||
|
return self._tokens |
||||
|
|
||||
|
def _set_tokens(self, tokens): |
||||
|
self._tokens = tokens |
||||
|
self.len = len(tokens) |
||||
|
self.pos = 0 |
||||
|
|
||||
|
tokens = property(_get_tokens, _set_tokens) |
||||
|
|
||||
|
def parse(self): |
||||
|
if self.at_end(): |
||||
|
raise self.error_class('No variables provided.') |
||||
|
var1 = self.get_bool_var() |
||||
|
while not self.at_end(): |
||||
|
op, negate = self.get_operator() |
||||
|
var2 = self.get_bool_var() |
||||
|
var1 = op(var1, var2, negate=negate) |
||||
|
return var1 |
||||
|
|
||||
|
def get_token(self, eof_message=None, lookahead=False): |
||||
|
negate = True |
||||
|
token = None |
||||
|
pos = self.pos |
||||
|
while token is None or token == 'not': |
||||
|
if pos >= self.len: |
||||
|
if eof_message is None: |
||||
|
raise self.error_class() |
||||
|
raise self.error_class(eof_message) |
||||
|
token = self.tokens[pos] |
||||
|
negate = not negate |
||||
|
pos += 1 |
||||
|
if not lookahead: |
||||
|
self.pos = pos |
||||
|
return token, negate |
||||
|
|
||||
|
def at_end(self): |
||||
|
return self.pos >= self.len |
||||
|
|
||||
|
def create_var(self, value): |
||||
|
return TestVar(value) |
||||
|
|
||||
|
def get_bool_var(self): |
||||
|
""" |
||||
|
Returns either a variable by itself or a non-boolean operation (such as |
||||
|
``x == 0`` or ``x < 0``). |
||||
|
|
||||
|
This is needed to keep correct precedence for boolean operations (i.e. |
||||
|
``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``). |
||||
|
""" |
||||
|
var = self.get_var() |
||||
|
if not self.at_end(): |
||||
|
op_token = self.get_token(lookahead=True)[0] |
||||
|
if isinstance(op_token, basestring) and (op_token not in |
||||
|
BOOL_OPERATORS): |
||||
|
op, negate = self.get_operator() |
||||
|
return op(var, self.get_var(), negate=negate) |
||||
|
return var |
||||
|
|
||||
|
def get_var(self): |
||||
|
token, negate = self.get_token('Reached end of statement, still ' |
||||
|
'expecting a variable.') |
||||
|
if isinstance(token, basestring) and token in OPERATORS: |
||||
|
raise self.error_class('Expected variable, got operator (%s).' % |
||||
|
token) |
||||
|
var = self.create_var(token) |
||||
|
if negate: |
||||
|
return Or(var, negate=True) |
||||
|
return var |
||||
|
|
||||
|
def get_operator(self): |
||||
|
token, negate = self.get_token('Reached end of statement, still ' |
||||
|
'expecting an operator.') |
||||
|
if not isinstance(token, basestring) or token not in OPERATORS: |
||||
|
raise self.error_class('%s is not a valid operator.' % token) |
||||
|
if self.at_end(): |
||||
|
raise self.error_class('No variable provided after "%s".' % token) |
||||
|
op, true = OPERATORS[token] |
||||
|
if not true: |
||||
|
negate = not negate |
||||
|
return op, negate |
||||
|
|
||||
|
|
||||
|
#============================================================================== |
||||
|
# Actual templatetag code. |
||||
|
#============================================================================== |
||||
|
|
||||
|
class TemplateIfParser(IfParser): |
||||
|
error_class = template.TemplateSyntaxError |
||||
|
|
||||
|
def __init__(self, parser, *args, **kwargs): |
||||
|
self.template_parser = parser |
||||
|
return super(TemplateIfParser, self).__init__(*args, **kwargs) |
||||
|
|
||||
|
def create_var(self, value): |
||||
|
return self.template_parser.compile_filter(value) |
||||
|
|
||||
|
|
||||
|
class SmartIfNode(template.Node): |
||||
|
def __init__(self, var, nodelist_true, nodelist_false=None): |
||||
|
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false |
||||
|
self.var = var |
||||
|
|
||||
|
def render(self, context): |
||||
|
if self.var.resolve(context): |
||||
|
return self.nodelist_true.render(context) |
||||
|
if self.nodelist_false: |
||||
|
return self.nodelist_false.render(context) |
||||
|
return '' |
||||
|
|
||||
|
def __repr__(self): |
||||
|
return "<Smart If node>" |
||||
|
|
||||
|
def __iter__(self): |
||||
|
for node in self.nodelist_true: |
||||
|
yield node |
||||
|
if self.nodelist_false: |
||||
|
for node in self.nodelist_false: |
||||
|
yield node |
||||
|
|
||||
|
def get_nodes_by_type(self, nodetype): |
||||
|
nodes = [] |
||||
|
if isinstance(self, nodetype): |
||||
|
nodes.append(self) |
||||
|
nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype)) |
||||
|
if self.nodelist_false: |
||||
|
nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype)) |
||||
|
return nodes |
||||
|
|
||||
|
|
||||
|
@register.tag('if') |
||||
|
def smart_if(parser, token): |
||||
|
""" |
||||
|
A smarter {% if %} tag for django templates. |
||||
|
|
||||
|
While retaining current Django functionality, it also handles equality, |
||||
|
greater than and less than operators. Some common case examples:: |
||||
|
|
||||
|
{% if articles|length >= 5 %}...{% endif %} |
||||
|
{% if "ifnotequal tag" != "beautiful" %}...{% endif %} |
||||
|
|
||||
|
Arguments and operators _must_ have a space between them, so |
||||
|
``{% if 1>2 %}`` is not a valid smart if tag. |
||||
|
|
||||
|
All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``), |
||||
|
``!=``, ``>``, ``>=``, ``<`` and ``<=``. |
||||
|
""" |
||||
|
bits = token.split_contents()[1:] |
||||
|
var = TemplateIfParser(parser, bits).parse() |
||||
|
nodelist_true = parser.parse(('else', 'endif')) |
||||
|
token = parser.next_token() |
||||
|
if token.contents == 'else': |
||||
|
nodelist_false = parser.parse(('endif',)) |
||||
|
parser.delete_first_token() |
||||
|
else: |
||||
|
nodelist_false = None |
||||
|
return SmartIfNode(var, nodelist_true, nodelist_false) |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
unittest.main() |
@ -0,0 +1,15 @@ |
|||||
|
# -*- coding: utf8 -*- |
||||
|
|
||||
|
from django.test import TestCase |
||||
|
|
||||
|
|
||||
|
class DiagnosticosViewsTest(TestCase): |
||||
|
"""Testes feitos para verificar o funcionamento |
||||
|
do view de diagnósticos. |
||||
|
""" |
||||
|
|
||||
|
def test_diagnostico_list_success(self): |
||||
|
|
||||
|
response = self.client.get('/sigi/mobile/diagnosticos') |
||||
|
self.assertEquals(200, response.status_code) |
||||
|
self.assertTemplateUsed(response, 'diagnosticos/diagnosticos_list.html') |
@ -0,0 +1,35 @@ |
|||||
|
# -*- coding: utf8 -*- |
||||
|
from django.conf.urls.defaults import patterns, url |
||||
|
|
||||
|
LOGIN_REDIRECT_URL = '/sigi/mobile/diagnosticos/login' |
||||
|
|
||||
|
urlpatterns = patterns('', |
||||
|
# Lista de Diagnósticos |
||||
|
url(r'^$', 'sigi.apps.diagnosticos.views.lista', name='lista_diagnosticos'), |
||||
|
|
||||
|
# Login do Diagnóstico |
||||
|
url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': |
||||
|
'diagnosticos/diagnosticos_login.html'}, name='login'), |
||||
|
|
||||
|
# Logout do Diagnóstico |
||||
|
url(r'^logout/$', 'django.contrib.auth.views.logout', |
||||
|
{'next_page': LOGIN_REDIRECT_URL}, name='logout'), |
||||
|
|
||||
|
# Lista de Categorias |
||||
|
url(r'^(?P<id_diagnostico>\d+)/categorias/$', 'sigi.apps.diagnosticos.views.categorias', name='lista_categorias'), |
||||
|
|
||||
|
# Detalhes da Categoria da Casa Legislativa |
||||
|
url(r'^(?P<id_diagnostico>\d+)/categorias/1/$', |
||||
|
'sigi.apps.diagnosticos.views.categoria_casa_legislativa', |
||||
|
name='detalhes_categoria_casa_legislativa'), |
||||
|
|
||||
|
# Detalhes da Categoria de Contatos |
||||
|
url(r'^(?P<id_diagnostico>\d+)/categorias/2/$', |
||||
|
'sigi.apps.diagnosticos.views.categoria_contatos', |
||||
|
name='detalhes_categoria_contatos'), |
||||
|
|
||||
|
# Detalhes de Categorias Dinamicas |
||||
|
url(r'^(?P<id_diagnostico>\d+)/categorias/(?P<id_categoria>\d+)/$', |
||||
|
'sigi.apps.diagnosticos.views.categoria_detalhes', |
||||
|
name='detalhes_categoria'), |
||||
|
) |
@ -0,0 +1,351 @@ |
|||||
|
# -*- coding: utf8 -*- |
||||
|
|
||||
|
import new |
||||
|
from django.http import HttpResponse, QueryDict |
||||
|
from django.utils import simplejson |
||||
|
from django.shortcuts import render_to_response, get_object_or_404, redirect |
||||
|
from django.template import RequestContext |
||||
|
from django.views.decorators.cache import never_cache |
||||
|
from geraldo.generators import PDFGenerator |
||||
|
|
||||
|
from sigi.apps.diagnosticos.urls import LOGIN_REDIRECT_URL |
||||
|
from sigi.apps.utils.decorators import login_required |
||||
|
from sigi.apps.diagnosticos.decorators import validate_diagnostico |
||||
|
from sigi.apps.diagnosticos.models import Diagnostico, Categoria, Pergunta |
||||
|
from sigi.apps.casas.models import Funcionario |
||||
|
from sigi.apps.diagnosticos.forms import (DiagnosticoMobileForm, |
||||
|
CasaLegislativaMobileForm, FuncionariosMobileForm) |
||||
|
from sigi.apps.contatos.models import Telefone |
||||
|
from sigi.shortcuts import render_to_pdf |
||||
|
|
||||
|
|
||||
|
@never_cache |
||||
|
@login_required(login_url=LOGIN_REDIRECT_URL) |
||||
|
def lista(request): |
||||
|
"""Consulta os diagnosticos do servidor logado, |
||||
|
que contenham o status de não publicado. |
||||
|
""" |
||||
|
servidor = request.user.servidor |
||||
|
diagnosticos = servidor.diagnosticos |
||||
|
context = RequestContext(request, {'diagnosticos': diagnosticos}) |
||||
|
return render_to_response('diagnosticos/diagnosticos_list.html', context) |
||||
|
|
||||
|
|
||||
|
@never_cache |
||||
|
@login_required(login_url=LOGIN_REDIRECT_URL) |
||||
|
@validate_diagnostico |
||||
|
def categorias(request, id_diagnostico): |
||||
|
"""Consulta as categorias do diagnostico selecionado |
||||
|
a partir da sua identificação |
||||
|
""" |
||||
|
categorias = Categoria.objects.all() |
||||
|
diagnostico = Diagnostico.objects.get(pk=id_diagnostico) |
||||
|
|
||||
|
# Estilizando a lista de categorias para que ajude a identificar |
||||
|
# qual categoria foi a ultima a ser usada, como também as outras |
||||
|
# que ainda não foram acessadas |
||||
|
ultima_categoria = request.session.get('ultima_categoria', 0) |
||||
|
|
||||
|
context = RequestContext(request, {'categorias': categorias, |
||||
|
'diagnostico': diagnostico, 'ultima_categoria': ultima_categoria}) |
||||
|
return render_to_response('diagnosticos/diagnosticos_categorias_list.html', |
||||
|
context) |
||||
|
|
||||
|
|
||||
|
@never_cache |
||||
|
@login_required(login_url=LOGIN_REDIRECT_URL) |
||||
|
@validate_diagnostico |
||||
|
def categoria_detalhes(request, id_diagnostico, id_categoria): |
||||
|
"""Captura as perguntas da categoria |
||||
|
selecionada. Durante o preenchimento das perguntas, o camada |
||||
|
template do projeto, vai requisitar a inserção dos campos via |
||||
|
AJAX a cada mudança de pergunta |
||||
|
|
||||
|
Caso alguma inserção não passe na validação do formulário em |
||||
|
questão, será enviado as mensagens de erro no formato JSON, |
||||
|
para que a camada de template do projeto trate-as de forma adequada. |
||||
|
""" |
||||
|
|
||||
|
# Grava na sessão a categoria atual, para destacar que |
||||
|
# era foi a última visitada. |
||||
|
request.session['ultima_categoria'] = int(id_categoria) |
||||
|
|
||||
|
try: |
||||
|
categoria = Categoria.objects.get(pk=id_categoria) |
||||
|
except Categoria.DoesNotExist: |
||||
|
context = RequestContext(request) |
||||
|
return render_to_response('mobile/404.html', context) |
||||
|
|
||||
|
diagnostico = Diagnostico.objects.filter(publicado=False).get(pk=id_diagnostico) |
||||
|
|
||||
|
if request.method == "POST": |
||||
|
form = DiagnosticoMobileForm(request.POST, |
||||
|
instance=diagnostico, category=id_categoria) |
||||
|
if form.is_valid(): |
||||
|
form.save() |
||||
|
resposta = { |
||||
|
'mensagem': 'sucesso' |
||||
|
} |
||||
|
else: |
||||
|
# Montando a estrutura das mensagens de erro no formato JSON |
||||
|
resposta = { |
||||
|
'mensagem': 'erro', |
||||
|
'erros': form.errors |
||||
|
} |
||||
|
json = simplejson.dumps(resposta) |
||||
|
return HttpResponse(json, mimetype="application/json") |
||||
|
else: |
||||
|
form = DiagnosticoMobileForm(instance=diagnostico, |
||||
|
category=id_categoria) |
||||
|
|
||||
|
context = RequestContext(request, {'form': form, 'categoria': categoria, |
||||
|
'diagnostico': diagnostico}) |
||||
|
return render_to_response('diagnosticos/diagnosticos_categorias_form.html', |
||||
|
context) |
||||
|
|
||||
|
|
||||
|
@never_cache |
||||
|
@login_required(login_url=LOGIN_REDIRECT_URL) |
||||
|
@validate_diagnostico |
||||
|
def categoria_casa_legislativa(request, id_diagnostico): |
||||
|
|
||||
|
# Grava na sessão a categoria atual, para destacar que |
||||
|
# era foi a última visitada. |
||||
|
request.session['ultima_categoria'] = 1 |
||||
|
|
||||
|
diagnostico = Diagnostico.objects.get(pk=id_diagnostico) |
||||
|
casa_legislativa = diagnostico.casa_legislativa |
||||
|
|
||||
|
if request.method == "POST": |
||||
|
form = CasaLegislativaMobileForm(request.POST, |
||||
|
instance=casa_legislativa) |
||||
|
if form.is_valid(): |
||||
|
form.save() |
||||
|
resposta = { |
||||
|
'mensagem': 'sucesso' |
||||
|
} |
||||
|
else: |
||||
|
# Montando a estrutura das mensagens de erro no formato JSON |
||||
|
resposta = { |
||||
|
'mensagem': 'erro', |
||||
|
'erros': form.errors |
||||
|
} |
||||
|
json = simplejson.dumps(resposta) |
||||
|
return HttpResponse(json, mimetype="application/json") |
||||
|
else: |
||||
|
form = CasaLegislativaMobileForm(instance=casa_legislativa) |
||||
|
|
||||
|
context = RequestContext(request, {'form': form, |
||||
|
'diagnostico': diagnostico, 'casa_legislativa': casa_legislativa}) |
||||
|
return render_to_response( |
||||
|
'diagnosticos/diagnosticos_categoria_casa_legislativa_form.html', |
||||
|
context) |
||||
|
|
||||
|
|
||||
|
@never_cache |
||||
|
@login_required(login_url=LOGIN_REDIRECT_URL) |
||||
|
@validate_diagnostico |
||||
|
def categoria_contatos(request, id_diagnostico): |
||||
|
|
||||
|
# Grava na sessão a categoria atual, para destacar que |
||||
|
# era foi a última visitada. |
||||
|
request.session['ultima_categoria'] = 2 |
||||
|
|
||||
|
diagnostico = Diagnostico.objects.get(pk=id_diagnostico) |
||||
|
casa_legislativa = diagnostico.casa_legislativa |
||||
|
|
||||
|
funcionarios = [] |
||||
|
|
||||
|
for n, l in Funcionario.SETOR_CHOICES: |
||||
|
if casa_legislativa.funcionario_set.filter(setor=n).count() <= 1: |
||||
|
funcionarios.append(casa_legislativa.funcionario_set.get_or_create(setor=n)) |
||||
|
else: |
||||
|
for f in casa_legislativa.funcionario_set.filter(setor=n): |
||||
|
funcionarios.append((f, False)) |
||||
|
|
||||
|
if request.method == "POST": |
||||
|
forms = [] |
||||
|
for f, c in funcionarios: |
||||
|
try: |
||||
|
forms.append(FuncionariosMobileForm(request.POST, prefix=f.setor, instance=f)) |
||||
|
except: |
||||
|
pass |
||||
|
|
||||
|
resposta = { |
||||
|
'mensagem': 'sucesso', |
||||
|
'erros' : {}, |
||||
|
'fones' : {}, |
||||
|
'clean' : (), |
||||
|
} |
||||
|
|
||||
|
# valida e salva um formulario por vez |
||||
|
for form in forms: |
||||
|
if form.is_valid(): |
||||
|
form.save() |
||||
|
s = '' |
||||
|
for form_telefones in form.telefones.forms: |
||||
|
tel = form_telefones.instance |
||||
|
if tel._state.adding and tel.numero != '': |
||||
|
s += '<p>Novo telefone %s: %s</p>' % (form_telefones.instance.get_tipo_display(), form_telefones.instance.numero) |
||||
|
resposta['clean'] += ('id_' + form_telefones.prefix + '-numero',) |
||||
|
if s != '': |
||||
|
resposta['fones'][form.prefix] = s |
||||
|
else: |
||||
|
# Montando a estrutura das mensagens de erro no formato JSON |
||||
|
resposta['mensagem'] = 'erro' |
||||
|
for key, value in form.errors.iteritems(): |
||||
|
resposta['erros'][form.prefix + '-' + key + '-errors'] = value |
||||
|
|
||||
|
for form_telefones in form.telefones.forms: |
||||
|
if not form_telefones.is_valid(): |
||||
|
if (form_telefones.fields['id'].initial is not None |
||||
|
and form_telefones.fields['tipo'].initial == 'I' |
||||
|
and form_telefones.fields['numero'].initial is None): |
||||
|
if Telefone.objects.filter(pk=form_telefones.fields['id'].initial).exists(): |
||||
|
Telefone.objects.get(pk=form_telefones.fields['id'].initial).delete() |
||||
|
if not resposta['fones'].has_key(form.prefix): |
||||
|
resposta['fones'][form.prefix] = '' |
||||
|
resposta['fones'][form.prefix] += u'<p>O telefone %s %s foi excluído da base de dados</p>' % ( |
||||
|
form_telefones.instance.get_tipo_display(), form_telefones.instance.numero) |
||||
|
else: |
||||
|
for key, value in form_telefones.errors.iteritems(): |
||||
|
key = form_telefones.prefix + "-id-errors" |
||||
|
resposta['erros'][key] = value |
||||
|
|
||||
|
json = simplejson.dumps(resposta) |
||||
|
return HttpResponse(json, mimetype="application/json") |
||||
|
else: |
||||
|
forms = [FuncionariosMobileForm(prefix=f.setor, instance=f) |
||||
|
for f, c in funcionarios] |
||||
|
|
||||
|
context = RequestContext(request, {'forms': forms, |
||||
|
'diagnostico': diagnostico, 'casa_legislativa': casa_legislativa}) |
||||
|
return render_to_response('diagnosticos/diagnosticos_categoria_contatos_form.html', |
||||
|
context) |
||||
|
|
||||
|
def diagnostico_pdf(request, id_diagnostico): |
||||
|
diagnostico = Diagnostico.objects.get(pk=id_diagnostico) |
||||
|
categorias = Categoria.objects.all() |
||||
|
|
||||
|
casa_legislativa = diagnostico.casa_legislativa |
||||
|
funcionarios = [] |
||||
|
for n, l in Funcionario.SETOR_CHOICES: |
||||
|
if casa_legislativa.funcionario_set.filter(setor=n).count() <= 1: |
||||
|
funcionarios.append(casa_legislativa.funcionario_set.get_or_create(setor=n)) |
||||
|
else: |
||||
|
for f in casa_legislativa.funcionario_set.filter(setor=n): |
||||
|
funcionarios.append(f) |
||||
|
|
||||
|
schemas_by_categoria = [] |
||||
|
for categoria in categorias: |
||||
|
schemas = [] |
||||
|
for schema in diagnostico.get_schemata(categoria.id): |
||||
|
datatype = schema.datatype |
||||
|
data = getattr(diagnostico, schema.name) |
||||
|
if datatype == schema.TYPE_MANY: |
||||
|
schema.value = [x.pk for x in data] |
||||
|
elif datatype == schema.TYPE_ONE: |
||||
|
schema.value = data.pk if data else None, |
||||
|
else: |
||||
|
schema.value = data |
||||
|
schemas.append(schema) |
||||
|
|
||||
|
schemas_by_categoria.append((categoria,schemas)) |
||||
|
|
||||
|
context = RequestContext(request, { |
||||
|
'pagesize':'A4', |
||||
|
'casa_legislativa': casa_legislativa, |
||||
|
'funcionarios': funcionarios, |
||||
|
'diagnostico': diagnostico, |
||||
|
'schemas_by_categoria': schemas_by_categoria, |
||||
|
}) |
||||
|
|
||||
|
return render_to_pdf('diagnosticos/diagnostico_pdf.html', context) |
||||
|
#return render_to_response('diagnosticos/diagnostico_pdf.html', context) |
||||
|
|
||||
|
def graficos(request): |
||||
|
categorias = Categoria.objects.all() |
||||
|
|
||||
|
sel_categoria = int(request.REQUEST.get("categoria","3")) |
||||
|
perguntas = Pergunta.objects.filter(categoria=sel_categoria).all() |
||||
|
|
||||
|
context = RequestContext(request, { |
||||
|
'categorias': categorias, |
||||
|
'sel_categoria': sel_categoria, |
||||
|
'perguntas': perguntas, |
||||
|
}) |
||||
|
return render_to_response('diagnosticos/graficos.html', |
||||
|
context) |
||||
|
|
||||
|
def percentage(fraction, population): |
||||
|
try: |
||||
|
return "%.0f%%" % ((float(fraction) / float(population)) * 100) |
||||
|
except ValueError: |
||||
|
return '' |
||||
|
|
||||
|
def grafico_api(request): |
||||
|
colors = ['ffff00', 'cc7900', 'ff0000', '92d050', '006600', '0097cc', '002776', 'ae78d6', 'ff00ff', '430080', |
||||
|
'28d75c', '0000ff', 'fff200'] |
||||
|
graph_url = "http://chart.apis.google.com/chart" |
||||
|
#graph_params = QueryDict("chxt=y&chbh=a&chco=A2C180,3D7930") |
||||
|
graph_params = QueryDict("") |
||||
|
graph_params = graph_params.copy() # to make it mutable |
||||
|
|
||||
|
width = request.REQUEST.get('width', '800') |
||||
|
height = request.REQUEST.get('height', '300') |
||||
|
graph_params.update({'chs': width + 'x' + height}) |
||||
|
|
||||
|
pergunta_slug = request.REQUEST.get('id', None) |
||||
|
pergunta = get_object_or_404(Pergunta, name=pergunta_slug) |
||||
|
|
||||
|
if pergunta.datatype == 'one': |
||||
|
total = sum([r[1] for r in pergunta.group_choices()]) |
||||
|
choices = [str(r[1]) for r in pergunta.group_choices()] |
||||
|
legend = [percentage(r[1],total) + " " + str(r[0]) for r in pergunta.group_choices()] |
||||
|
colors = ['ff0000', 'fff200', '0000ff', '28d75c'] + ["%0.6x" % (0x48d1 + (0xda74 * c)) |
||||
|
for c in range(0,len(pergunta.group_choices()))] |
||||
|
graph_params.update({ |
||||
|
'cht': 'p', |
||||
|
'chd': 't:' + ",".join(choices), |
||||
|
'chdl': '' + "|".join(legend), |
||||
|
'chco': '' + '|'.join(colors[:len(pergunta.group_choices())]) |
||||
|
}) |
||||
|
elif pergunta.datatype == 'many': |
||||
|
total = sum([r[1] for r in pergunta.group_choices()]) |
||||
|
percent = [str(float(r[1])*100/total) for r in pergunta.group_choices()] |
||||
|
choices = [str(r[1]) for r in pergunta.group_choices()] |
||||
|
legend = [str(r[0]) for r in pergunta.group_choices()] |
||||
|
colors = ['ffff00', 'cc7900', 'ff0000', '92d050', '006600', '0097cc', '002776', 'ae78d6', 'ff00ff', '430080'] + \ |
||||
|
["%0.6x" % (0x48d1 + (0xda74 * c)) for c in range(0,len(pergunta.group_choices()))] |
||||
|
graph_params.update({ |
||||
|
'cht': 'bvg', |
||||
|
'chxt': 'y', |
||||
|
'chd': 't:' + ",".join(percent), |
||||
|
'chdl': '' + "|".join(legend), |
||||
|
'chl': '' + "|".join(choices), |
||||
|
'chco': '' + '|'.join(colors[:len(pergunta.group_choices())]) |
||||
|
}) |
||||
|
|
||||
|
response = { |
||||
|
"type": "photo", |
||||
|
"width": width, |
||||
|
"height": height, |
||||
|
"title": pergunta.title, |
||||
|
"url": graph_url + "?" + graph_params.urlencode(), |
||||
|
"provider_name": "SIGI", |
||||
|
"provider_url": "https://intranet.interlegis.gov.br/sigi/" |
||||
|
} |
||||
|
|
||||
|
json = simplejson.dumps(response) |
||||
|
return HttpResponse(json, mimetype="application/json") |
||||
|
|
||||
|
def municipios_diagnosticados(self): |
||||
|
municipios = [] |
||||
|
|
||||
|
for d in Diagnostico.objects.all(): |
||||
|
m = d.casa_legislativa.municipio |
||||
|
municipio = {'nome': d.casa_legislativa.nome + ', ' + m.uf.sigla, 'lat': str(m.latitude), 'lng': str(m.longitude), 'inicio': d.data_visita_inicio.strftime('%d/%m/%Y'), |
||||
|
'fim': d.data_visita_fim.strftime('%d/%m/%Y'), 'equipe': "<ul><li>" + "</li><li>".join([m.user.get_full_name() for m in d.membros]) + "</li></ul>",} |
||||
|
municipios.append(municipio) |
||||
|
|
||||
|
return HttpResponse(simplejson.dumps(municipios), mimetype="application/json") |
@ -0,0 +1,61 @@ |
|||||
|
from itertools import chain |
||||
|
from django.forms.widgets import CheckboxInput, CheckboxSelectMultiple, RadioSelect, RadioFieldRenderer, RadioInput |
||||
|
from django.utils.html import conditional_escape |
||||
|
from django.utils.encoding import force_unicode |
||||
|
from django.utils.safestring import mark_safe |
||||
|
from sigi.apps.diagnosticos.models import Escolha |
||||
|
|
||||
|
class EavCheckboxSelectMultiple(CheckboxSelectMultiple): |
||||
|
def render(self, name, value, attrs=None, choices=()): |
||||
|
if value is None: value = [] |
||||
|
final_attrs = self.build_attrs(attrs, name=name) |
||||
|
output = [u'<ul>'] |
||||
|
str_values = set([force_unicode(v) for v in value]) |
||||
|
for i, (option_value, option_label) in enumerate(chain(self.choices, choices)): |
||||
|
final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i)) |
||||
|
label_for = u' for="%s"' % final_attrs['id'] |
||||
|
|
||||
|
# Caso exista uma pergunta para abrir |
||||
|
# adiciona um atripbuto no checkbox |
||||
|
schema_to_open = Escolha.objects.get(pk=option_value).schema_to_open |
||||
|
if schema_to_open: |
||||
|
final_attrs['schema_to_open'] = schema_to_open.name |
||||
|
|
||||
|
cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values) |
||||
|
option_value = force_unicode(option_value) |
||||
|
rendered_cb = cb.render(name, option_value) |
||||
|
option_label = conditional_escape(force_unicode(option_label)) |
||||
|
output.append(u'<li><label%s>%s %s</label></li>' % (label_for, rendered_cb, option_label)) |
||||
|
output.append(u'</ul>') |
||||
|
return mark_safe(u'\n'.join(output)) |
||||
|
|
||||
|
class EavRadioFieldRenderer(RadioFieldRenderer): |
||||
|
def __iter__(self): |
||||
|
for i, choice in enumerate(self.choices): |
||||
|
final_attrs = self.attrs.copy() |
||||
|
|
||||
|
# Caso exista uma pergunta para abrir |
||||
|
# adiciona um atripbuto no checkbox |
||||
|
if choice[0]: |
||||
|
schema_to_open = Escolha.objects.get(pk=choice[0]).schema_to_open |
||||
|
if schema_to_open: |
||||
|
final_attrs['schema_to_open'] = schema_to_open.name |
||||
|
|
||||
|
yield RadioInput(self.name, self.value, final_attrs, choice, i) |
||||
|
|
||||
|
def __getitem__(self, idx): |
||||
|
choice = self.choices[idx] |
||||
|
|
||||
|
final_attrs = self.attrs.copy() |
||||
|
|
||||
|
# Caso exista uma pergunta para abrir |
||||
|
# adiciona um atripbuto no checkbox |
||||
|
schema_to_open = Escolha.objects.get(pk=self.value).schema_to_open |
||||
|
if schema_to_open: |
||||
|
final_attrs['schema_to_open'] = schema_to_open.name |
||||
|
|
||||
|
return RadioInput(self.name, self.value,final_attrs, choice, idx) |
||||
|
|
||||
|
class EavRadioSelect(RadioSelect): |
||||
|
renderer = EavRadioFieldRenderer |
||||
|
|
@ -0,0 +1,9 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.contrib import admin |
||||
|
from sigi.apps.financeiro.models import Desembolso |
||||
|
|
||||
|
class DesembolsoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('projeto', 'descricao', 'data', 'valor_reais', 'valor_dolar',) |
||||
|
fields = ('projeto', 'descricao', 'data', 'valor_reais', 'valor_dolar', ) |
||||
|
list_filter = ('projeto',) |
||||
|
date_hierarchy = 'data' |
@ -0,0 +1,3 @@ |
|||||
|
from django import forms |
||||
|
|
||||
|
# place form definition here |
@ -0,0 +1,18 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.db import models |
||||
|
from sigi.apps.convenios.models import Projeto |
||||
|
|
||||
|
class Desembolso(models.Model): |
||||
|
projeto = models.ForeignKey(Projeto, verbose_name=u'Projeto') |
||||
|
descricao = models.CharField(u'Descrição da despesa', max_length=100) |
||||
|
data = models.DateField(u'Data do desembolso') |
||||
|
valor_reais = models.DecimalField(u'Valor em R$', max_digits=18, decimal_places=2) |
||||
|
valor_dolar = models.DecimalField(u'Valor em US$', max_digits=18, decimal_places=2) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'Desembolso' |
||||
|
verbose_name_plural = 'Desembolsos' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return u"%s (US$ %s)" % (self.descricao, self.valor_dolar) |
||||
|
|
@ -0,0 +1,3 @@ |
|||||
|
from django.conf.urls.defaults import * |
||||
|
|
||||
|
# place app url patterns here |
@ -0,0 +1 @@ |
|||||
|
# Create your views here. |
@ -0,0 +1,71 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.contrib import admin |
||||
|
from django.contrib.contenttypes import generic |
||||
|
from sigi.apps.contatos.models import Contato, Telefone |
||||
|
from sigi.apps.inventario.models import (Fornecedor, Fabricante, Equipamento, |
||||
|
TipoEquipamento, ModeloEquipamento, |
||||
|
Bem) |
||||
|
|
||||
|
class ContatosInline(generic.GenericTabularInline): |
||||
|
model = Contato |
||||
|
extra = 2 |
||||
|
raw_id_fields = ('municipio',) |
||||
|
|
||||
|
class TelefonesInline(generic.GenericTabularInline): |
||||
|
model = Telefone |
||||
|
extra = 2 |
||||
|
|
||||
|
class FornecedorAdmin(admin.ModelAdmin): |
||||
|
inlines = (TelefonesInline, ContatosInline) |
||||
|
list_display = ('id', 'nome', 'email', 'pagina_web') |
||||
|
list_display_links = ('id', 'nome') |
||||
|
list_filter = ('nome',) |
||||
|
search_fields = ('id', 'nome', 'email', 'pagina_web') |
||||
|
|
||||
|
class FabricanteAdmin(admin.ModelAdmin): |
||||
|
list_display = ('id', 'nome') |
||||
|
list_display_links = list_display |
||||
|
list_filter = ('nome',) |
||||
|
search_fields = ('id', 'nome') |
||||
|
|
||||
|
class TipoEquipamentoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('id', 'tipo') |
||||
|
list_display_links = list_display |
||||
|
list_filter = ('tipo',) |
||||
|
search_fields = ('id', 'tipo') |
||||
|
|
||||
|
class ModeloEquipamentoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('id', 'tipo', 'modelo') |
||||
|
list_filter = ('tipo', 'modelo') |
||||
|
ordering = ('tipo', 'modelo') |
||||
|
search_fields = ('id', 'tipo', 'modelo') |
||||
|
raw_id_fields = ('tipo',) |
||||
|
|
||||
|
class EquipamentoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('id', 'fabricante', 'modelo', 'get_tipo') |
||||
|
list_display_links = ('id',) |
||||
|
list_filter = ('fabricante',) |
||||
|
ordering = ('fabricante', 'modelo') |
||||
|
raw_id_fields = ('fabricante', 'modelo') |
||||
|
search_fields = ('id', 'modelo', 'fabricante') |
||||
|
|
||||
|
def get_tipo(self, obj): |
||||
|
return obj.modelo.tipo.tipo |
||||
|
get_tipo.short_description = 'tipo' |
||||
|
|
||||
|
class BemAdmin(admin.ModelAdmin): |
||||
|
list_display = ('equipamento', 'fornecedor', 'num_serie', |
||||
|
'casa_legislativa') |
||||
|
list_filter = ('fornecedor',) |
||||
|
ordering = ('casa_legislativa', 'fornecedor', 'equipamento') |
||||
|
raw_id_fields = ('casa_legislativa', 'equipamento', 'fornecedor') |
||||
|
search_fields = ('fornecedor__nome', 'equipamento__fabricante__nome', |
||||
|
'equipamento__modelo__modelo', 'num_serie', |
||||
|
'num_tombamento', 'casa_legislativa__nome') |
||||
|
|
||||
|
admin.site.register(Fornecedor, FornecedorAdmin) |
||||
|
admin.site.register(Fabricante, FabricanteAdmin) |
||||
|
admin.site.register(TipoEquipamento, TipoEquipamentoAdmin) |
||||
|
admin.site.register(ModeloEquipamento,ModeloEquipamentoAdmin) |
||||
|
admin.site.register(Equipamento, EquipamentoAdmin) |
||||
|
admin.site.register(Bem, BemAdmin) |
@ -0,0 +1,280 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"pk": 3, |
||||
|
"model": "inventario.fornecedor", |
||||
|
"fields": { |
||||
|
"pagina_web": "http://www.dell.com.br/", |
||||
|
"email": "", |
||||
|
"nome": "Dell" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 1, |
||||
|
"model": "inventario.fornecedor", |
||||
|
"fields": { |
||||
|
"pagina_web": "", |
||||
|
"email": "", |
||||
|
"nome": "Desconhecido" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 2, |
||||
|
"model": "inventario.fornecedor", |
||||
|
"fields": { |
||||
|
"pagina_web": "http://www.submarino.com.br/", |
||||
|
"email": "", |
||||
|
"nome": "Submarino" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 2, |
||||
|
"model": "inventario.fabricante", |
||||
|
"fields": { |
||||
|
"nome": "Dell" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 1, |
||||
|
"model": "inventario.fabricante", |
||||
|
"fields": { |
||||
|
"nome": "Desconhecido" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 4, |
||||
|
"model": "inventario.fabricante", |
||||
|
"fields": { |
||||
|
"nome": "HP" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 3, |
||||
|
"model": "inventario.fabricante", |
||||
|
"fields": { |
||||
|
"nome": "Microsoft" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 2, |
||||
|
"model": "inventario.tipoequipamento", |
||||
|
"fields": { |
||||
|
"tipo": "Computador Desktop" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 1, |
||||
|
"model": "inventario.tipoequipamento", |
||||
|
"fields": { |
||||
|
"tipo": "Desconhecido" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 8, |
||||
|
"model": "inventario.tipoequipamento", |
||||
|
"fields": { |
||||
|
"tipo": "Estabilizador" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 3, |
||||
|
"model": "inventario.tipoequipamento", |
||||
|
"fields": { |
||||
|
"tipo": "Impressora" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 5, |
||||
|
"model": "inventario.tipoequipamento", |
||||
|
"fields": { |
||||
|
"tipo": "Modem" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 4, |
||||
|
"model": "inventario.tipoequipamento", |
||||
|
"fields": { |
||||
|
"tipo": "Monitor" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 9, |
||||
|
"model": "inventario.tipoequipamento", |
||||
|
"fields": { |
||||
|
"tipo": "Notebook/Laptop" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 6, |
||||
|
"model": "inventario.tipoequipamento", |
||||
|
"fields": { |
||||
|
"tipo": "Roteador" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 7, |
||||
|
"model": "inventario.tipoequipamento", |
||||
|
"fields": { |
||||
|
"tipo": "Webcam" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 1, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Desconhecido", |
||||
|
"tipo": 1 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 2, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Desconhecido", |
||||
|
"tipo": 3 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 3, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Desconhecido", |
||||
|
"tipo": 2 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 4, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Desconhecido", |
||||
|
"tipo": 8 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 5, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Desconhecido", |
||||
|
"tipo": 5 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 6, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Desconhecido", |
||||
|
"tipo": 4 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 7, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Desconhecido", |
||||
|
"tipo": 9 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 8, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Desconhecido", |
||||
|
"tipo": 6 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 9, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Desconhecido", |
||||
|
"tipo": 7 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 10, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "PSC 500", |
||||
|
"tipo": 3 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 11, |
||||
|
"model": "inventario.modeloequipamento", |
||||
|
"fields": { |
||||
|
"modelo": "Vostro 1310", |
||||
|
"tipo": 9 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 1, |
||||
|
"model": "inventario.equipamento", |
||||
|
"fields": { |
||||
|
"modelo": 1, |
||||
|
"fabricante": 1 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 2, |
||||
|
"model": "inventario.equipamento", |
||||
|
"fields": { |
||||
|
"modelo": 2, |
||||
|
"fabricante": 1 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 3, |
||||
|
"model": "inventario.equipamento", |
||||
|
"fields": { |
||||
|
"modelo": 3, |
||||
|
"fabricante": 1 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 4, |
||||
|
"model": "inventario.equipamento", |
||||
|
"fields": { |
||||
|
"modelo": 4, |
||||
|
"fabricante": 1 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 5, |
||||
|
"model": "inventario.equipamento", |
||||
|
"fields": { |
||||
|
"modelo": 5, |
||||
|
"fabricante": 1 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 6, |
||||
|
"model": "inventario.equipamento", |
||||
|
"fields": { |
||||
|
"modelo": 6, |
||||
|
"fabricante": 1 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 7, |
||||
|
"model": "inventario.equipamento", |
||||
|
"fields": { |
||||
|
"modelo": 7, |
||||
|
"fabricante": 1 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 8, |
||||
|
"model": "inventario.equipamento", |
||||
|
"fields": { |
||||
|
"modelo": 8, |
||||
|
"fabricante": 1 |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 9, |
||||
|
"model": "inventario.equipamento", |
||||
|
"fields": { |
||||
|
"modelo": 9, |
||||
|
"fabricante": 1 |
||||
|
} |
||||
|
} |
||||
|
] |
@ -0,0 +1,90 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.db import models |
||||
|
from django.contrib.contenttypes import generic |
||||
|
|
||||
|
class Fornecedor(models.Model): |
||||
|
nome = models.CharField(max_length=40) |
||||
|
nome.alphabetic_filter = True |
||||
|
email = models.EmailField('e-mail', blank=True) |
||||
|
pagina_web = models.URLField('página web', blank=True) |
||||
|
telefones = generic.GenericRelation('contatos.Telefone') |
||||
|
contatos = generic.GenericRelation('contatos.Contato') |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('nome',) |
||||
|
verbose_name_plural = 'fornecedores' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.nome |
||||
|
|
||||
|
class Fabricante(models.Model): |
||||
|
nome = models.CharField(max_length=40, unique=True) |
||||
|
nome.alphabetic_filter = True |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('nome',) |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.nome |
||||
|
|
||||
|
class TipoEquipamento(models.Model): |
||||
|
tipo = models.CharField(max_length=40) |
||||
|
tipo.alphabetic_filter = True |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('tipo',) |
||||
|
verbose_name = 'tipo de equipamento' |
||||
|
verbose_name_plural = 'tipos de equipamentos' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.tipo |
||||
|
|
||||
|
class ModeloEquipamento(models.Model): |
||||
|
tipo = models.ForeignKey( |
||||
|
TipoEquipamento, |
||||
|
verbose_name='tipo de equipamento' |
||||
|
) |
||||
|
modelo = models.CharField(max_length=30) |
||||
|
modelo.alphabetic_filter = True |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('modelo',) |
||||
|
verbose_name = 'modelo de equipamento' |
||||
|
verbose_name_plural = 'modelos de equipamentos' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.modelo |
||||
|
|
||||
|
class Equipamento(models.Model): |
||||
|
fabricante = models.ForeignKey(Fabricante) |
||||
|
modelo = models.ForeignKey(ModeloEquipamento) |
||||
|
|
||||
|
class Meta: |
||||
|
unique_together = (('fabricante', 'modelo'),) |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return unicode('%s %s %s' % (self.modelo.tipo, self.fabricante.nome, |
||||
|
self.modelo.modelo)) |
||||
|
|
||||
|
class Bem(models.Model): |
||||
|
casa_legislativa = models.ForeignKey('casas.CasaLegislativa') |
||||
|
equipamento = models.ForeignKey(Equipamento) |
||||
|
fornecedor = models.ForeignKey(Fornecedor) |
||||
|
num_serie = models.CharField( |
||||
|
'número de série', |
||||
|
max_length=64, |
||||
|
help_text='Número fornecido pelo fabricante.', |
||||
|
unique=True |
||||
|
) |
||||
|
recebido_por = models.CharField( |
||||
|
max_length=64, |
||||
|
blank=True, |
||||
|
help_text='Nome de quem recebeu o equipamento.' |
||||
|
) |
||||
|
observacoes = models.TextField('observações', blank=True) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name_plural = 'bens' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return unicode('%s (%s)') % (self.equipamento, self.casa_legislativa) |
@ -0,0 +1,102 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.contrib import admin |
||||
|
from django.http import HttpResponse |
||||
|
from django.utils.html import escape |
||||
|
from sigi.apps.mesas.models import (Legislatura, Coligacao, ComposicaoColigacao, |
||||
|
SessaoLegislativa, MesaDiretora, Cargo, |
||||
|
MembroMesaDiretora) |
||||
|
from sigi.apps.parlamentares.models import Mandato |
||||
|
|
||||
|
class MandatoInline(admin.TabularInline): |
||||
|
model = Mandato |
||||
|
raw_id_fields = ['parlamentar',] |
||||
|
|
||||
|
class LegislaturaAdmin(admin.ModelAdmin): |
||||
|
date_hierarchy = 'data_inicio' |
||||
|
list_display = ('numero', 'casa_legislativa', 'uf', 'data_inicio', 'data_fim', 'data_eleicao', 'total_parlamentares') |
||||
|
raw_id_fields = ('casa_legislativa',) |
||||
|
list_display_links = ('numero',) |
||||
|
list_filter = ('casa_legislativa', ) |
||||
|
search_fields = ('casa_legislativa__nome', 'casa_legislativa__municipio__nome' ) |
||||
|
inlines = (MandatoInline,) |
||||
|
|
||||
|
def uf(self, obj): |
||||
|
return obj.casa_legislativa.municipio.uf.sigla |
||||
|
uf.short_description = 'UF' |
||||
|
uf.admin_order_field = 'casa_legislativa__municipio__uf' |
||||
|
|
||||
|
def lookup_allowed(self, lookup, value): |
||||
|
return super(LegislaturaAdmin, self).lookup_allowed(lookup, value) or \ |
||||
|
lookup in ['casa_legislativa__municipio__uf__codigo_ibge__exact'] |
||||
|
|
||||
|
def response_change(self, request, obj): |
||||
|
response = super(LegislaturaAdmin, self).response_change(request, obj) |
||||
|
if request.POST.has_key("_popup"): |
||||
|
response = HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \ |
||||
|
# escape() calls force_unicode. |
||||
|
(escape(obj.pk), escapejs(obj))) |
||||
|
return response |
||||
|
|
||||
|
class ColigacaoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('nome', 'legislatura', 'numero_votos') |
||||
|
list_display_links = ('nome',) |
||||
|
raw_id_fields = ('legislatura',) |
||||
|
search_fields = ('nome', 'legislatura__numero') |
||||
|
|
||||
|
class ComposicaoColigacaoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('coligacao', 'partido') |
||||
|
list_display_links = ('coligacao', 'partido') |
||||
|
list_filter = ('partido',) |
||||
|
raw_id_fields = ('coligacao', 'partido') |
||||
|
search_fields = ('coligacao__nome', 'partido__nome', 'partido__sigla') |
||||
|
|
||||
|
class SessaoLegislativaAdmin(admin.ModelAdmin): |
||||
|
list_display = ('numero', 'mesa_diretora', 'legislatura', 'tipo', |
||||
|
'data_inicio', 'data_fim') |
||||
|
list_display_links = ('numero',) |
||||
|
list_filter = ('tipo',) |
||||
|
fieldsets = ( |
||||
|
(None, { |
||||
|
'fields': ('numero', 'mesa_diretora', 'legislatura', 'tipo') |
||||
|
}), |
||||
|
(None, { |
||||
|
'fields': (('data_inicio', 'data_fim'), |
||||
|
('data_inicio_intervalo', 'data_fim_intervalo')) |
||||
|
}), |
||||
|
) |
||||
|
radio_fields = {'tipo': admin.VERTICAL} |
||||
|
raw_id_fields = ('mesa_diretora', 'legislatura') |
||||
|
search_fields = ('numero', 'mesa_diretora__casa_legislativa__nome') |
||||
|
|
||||
|
class CargoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('descricao',) |
||||
|
search_fields = ('descricao',) |
||||
|
|
||||
|
class MembroMesaDiretoraInline(admin.TabularInline): |
||||
|
model = MembroMesaDiretora |
||||
|
max_num = 11 |
||||
|
extra = 4 |
||||
|
raw_id_fields = ('parlamentar', 'cargo') |
||||
|
|
||||
|
class MembroMesaDiretoraAdmin(admin.ModelAdmin): |
||||
|
list_display = ('parlamentar', 'cargo', 'mesa_diretora') |
||||
|
list_display_links = ('parlamentar',) |
||||
|
list_filter = ('cargo',) |
||||
|
raw_id_fields = ('parlamentar', 'cargo', 'mesa_diretora') |
||||
|
search_fields = ('cargo__descricao', 'parlamentar__nome_completo', |
||||
|
'parlamentar__nome_parlamentar', |
||||
|
'mesa_diretora__casa_legislativa__nome') |
||||
|
|
||||
|
class MesaDiretoraAdmin(admin.ModelAdmin): |
||||
|
inlines = (MembroMesaDiretoraInline,) |
||||
|
raw_id_fields = ('casa_legislativa',) |
||||
|
list_display = ('id', 'casa_legislativa') |
||||
|
search_fields = ('casa_legislativa__nome',) |
||||
|
|
||||
|
admin.site.register(Legislatura, LegislaturaAdmin) |
||||
|
admin.site.register(Coligacao, ColigacaoAdmin) |
||||
|
admin.site.register(ComposicaoColigacao, ComposicaoColigacaoAdmin) |
||||
|
admin.site.register(SessaoLegislativa, SessaoLegislativaAdmin) |
||||
|
admin.site.register(MesaDiretora, MesaDiretoraAdmin) |
||||
|
admin.site.register(Cargo, CargoAdmin) |
||||
|
admin.site.register(MembroMesaDiretora, MembroMesaDiretoraAdmin) |
@ -0,0 +1,44 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"pk": 4, |
||||
|
"model": "mesas.cargo", |
||||
|
"fields": { |
||||
|
"descricao": "1\u00ba Secret\u00e1rio" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 2, |
||||
|
"model": "mesas.cargo", |
||||
|
"fields": { |
||||
|
"descricao": "1\u00ba Vice-Presidente" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 5, |
||||
|
"model": "mesas.cargo", |
||||
|
"fields": { |
||||
|
"descricao": "2\u00ba Secret\u00e1rio" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 3, |
||||
|
"model": "mesas.cargo", |
||||
|
"fields": { |
||||
|
"descricao": "2\u00ba Vice-Presidente" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 6, |
||||
|
"model": "mesas.cargo", |
||||
|
"fields": { |
||||
|
"descricao": "Corregedor" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 1, |
||||
|
"model": "mesas.cargo", |
||||
|
"fields": { |
||||
|
"descricao": "Presidente" |
||||
|
} |
||||
|
} |
||||
|
] |
@ -0,0 +1,122 @@ |
|||||
|
# coding: utf-8 |
||||
|
from django.db import models |
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
|
||||
|
class Legislatura(models.Model): |
||||
|
casa_legislativa = models.ForeignKey(CasaLegislativa) |
||||
|
numero = models.PositiveSmallIntegerField(u'número legislatura') |
||||
|
data_inicio = models.DateField(u'início') |
||||
|
data_fim = models.DateField(u'fim') |
||||
|
data_eleicao = models.DateField(u'data da eleição') |
||||
|
total_parlamentares = models.PositiveIntegerField(u"Total de parlamentares") |
||||
|
|
||||
|
casa_legislativa.convenio_uf_filter = True |
||||
|
casa_legislativa.convenio_cl_tipo_filter = True |
||||
|
|
||||
|
def meta(self): |
||||
|
unique_together = (('casa_legislativa', 'numero')) |
||||
|
ordering = ['casa_legislativa__municipio__uf__sigla', '-data_inicio'] |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return u"%sª legislatura da %s (%s-%s)" % (self.numero, self.casa_legislativa.__unicode__(), self.data_inicio.year, self.data_fim.year) |
||||
|
|
||||
|
class Coligacao(models.Model): |
||||
|
nome = models.CharField(max_length=50) |
||||
|
legislatura = models.ForeignKey(Legislatura) |
||||
|
numero_votos = models.PositiveIntegerField( |
||||
|
u'número de votos', |
||||
|
blank=True, |
||||
|
null=True, |
||||
|
) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('legislatura', 'nome') |
||||
|
verbose_name = 'coligação' |
||||
|
verbose_name_plural = 'coligações' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.nome |
||||
|
|
||||
|
class ComposicaoColigacao(models.Model): |
||||
|
coligacao = models.ForeignKey(Coligacao, verbose_name='coligação') |
||||
|
partido = models.ForeignKey('parlamentares.Partido') |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'composição da coligação' |
||||
|
verbose_name_plural = 'composições das coligações' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return str(self.id) |
||||
|
|
||||
|
class SessaoLegislativa(models.Model): |
||||
|
SESSAO_CHOICES = ( |
||||
|
('O', 'Ordinária'), |
||||
|
('E', 'Extraordinária'), |
||||
|
) |
||||
|
numero = models.PositiveSmallIntegerField(u'número da sessão', unique=True) |
||||
|
mesa_diretora = models.ForeignKey( |
||||
|
'MesaDiretora', |
||||
|
verbose_name='Mesa Diretora' |
||||
|
) |
||||
|
legislatura = models.ForeignKey(Legislatura) |
||||
|
tipo = models.CharField( |
||||
|
max_length=1, |
||||
|
choices=SESSAO_CHOICES, |
||||
|
default='O' |
||||
|
) |
||||
|
data_inicio = models.DateField(u'início') |
||||
|
data_fim = models.DateField('fim') |
||||
|
data_inicio_intervalo = models.DateField( |
||||
|
u'início de intervalo', |
||||
|
blank=True, |
||||
|
null=True |
||||
|
) |
||||
|
data_fim_intervalo = models.DateField( |
||||
|
'fim de intervalo', |
||||
|
blank=True, |
||||
|
null=True |
||||
|
) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('legislatura', 'numero') |
||||
|
verbose_name = 'Sessão Legislativa' |
||||
|
verbose_name_plural = 'Sessões Legislativas' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return str(self.numero) |
||||
|
|
||||
|
class MesaDiretora(models.Model): |
||||
|
casa_legislativa = models.ForeignKey( |
||||
|
'casas.CasaLegislativa', |
||||
|
verbose_name='Casa Legislativa' |
||||
|
) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'Mesa Diretora' |
||||
|
verbose_name_plural = 'Mesas Diretoras' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return 'Mesa Diretora da %s' % unicode(self.casa_legislativa) |
||||
|
|
||||
|
class Cargo(models.Model): |
||||
|
descricao = models.CharField(u'descrição', max_length=30) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('descricao',) |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.descricao |
||||
|
|
||||
|
class MembroMesaDiretora(models.Model): |
||||
|
parlamentar = models.ForeignKey('parlamentares.Parlamentar') |
||||
|
cargo = models.ForeignKey(Cargo) |
||||
|
mesa_diretora = models.ForeignKey(MesaDiretora) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('parlamentar',) |
||||
|
unique_together = ('cargo', 'mesa_diretora') |
||||
|
verbose_name = 'membro de Mesa Diretora' |
||||
|
verbose_name_plural = 'membros de Mesas Diretora' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return '%s (%s)' % (unicode(self.parlamentar), unicode(self.cargo)) |
@ -0,0 +1,46 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.contrib import admin |
||||
|
from sigi.apps.metas.models import Meta, PlanoDiretor |
||||
|
|
||||
|
class MetaAdmin(admin.ModelAdmin): |
||||
|
list_display = ('projeto', 'titulo', 'data_inicio', 'data_fim', 'valor_meta', 'valor_executado', 'percentual_concluido',) |
||||
|
fields = ('projeto', 'titulo', 'descricao', 'data_inicio', 'data_fim', 'algoritmo', 'valor_meta',) |
||||
|
list_filter = ('projeto',) |
||||
|
|
||||
|
class PlanoDiretorAdmin(admin.ModelAdmin): |
||||
|
list_display = ('projeto', 'casa_legislativa', 'get_uf', 'status', 'data_entrega', 'data_implantacao',) |
||||
|
fields = ('projeto', 'casa_legislativa', 'status', 'data_entrega', 'data_implantacao',) |
||||
|
raw_id_fields = ('casa_legislativa',) |
||||
|
list_filter = ('projeto', 'status', 'casa_legislativa', ) |
||||
|
|
||||
|
def get_uf(self, obj): |
||||
|
return obj.casa_legislativa.municipio.uf.nome |
||||
|
get_uf.short_description = u"UF" |
||||
|
get_uf.admin_order_field = 'casa_legislativa__municipio__uf__nome' |
||||
|
|
||||
|
def lookup_allowed(self, lookup, value): |
||||
|
return super(PlanoDiretorAdmin, self).lookup_allowed(lookup, value) or \ |
||||
|
lookup in ['casa_legislativa__municipio__uf__codigo_ibge__exact'] |
||||
|
|
||||
|
def changelist_view(self, request, extra_context=None): |
||||
|
import re |
||||
|
request.GET._mutable=True |
||||
|
if 'data_entrega__gte' in request.GET: |
||||
|
value = request.GET.get('data_entrega__gte','') |
||||
|
if value == '': |
||||
|
del request.GET['data_entrega__gte'] |
||||
|
elif re.match('^\d*$', value): # Year only |
||||
|
request.GET['data_entrega__gte'] = "%s-01-01" % value #Complete with january 1st |
||||
|
elif re.match('^\d*\D\d*$', value): # Year and month |
||||
|
request.GET['data_entrega__gte'] = '%s-01' % value #Complete with 1st day of month |
||||
|
if 'data_entrega__lte' in request.GET: |
||||
|
value = request.GET.get('data_entrega__lte','') |
||||
|
if value == '': |
||||
|
del request.GET['data_entrega__lte'] |
||||
|
elif re.match('^\d*$', value): # Year only |
||||
|
request.GET['data_entrega__lte'] = "%s-01-01" % value #Complete with january 1st |
||||
|
elif re.match('^\d*\D\d*$', value): # Year and month |
||||
|
request.GET['data_entrega__lte'] = '%s-01' % value #Complete with 1st day of month |
||||
|
request.GET._mutable=False |
||||
|
|
||||
|
return super(PlanoDiretorAdmin, self).changelist_view(request, extra_context) |
@ -0,0 +1,3 @@ |
|||||
|
from django import forms |
||||
|
|
||||
|
# place form definition here |
@ -0,0 +1,31 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# |
||||
|
# sigi.apps.servicos.management.commands.atualiza_uso_servico |
||||
|
# |
||||
|
# Copyright (c) 2012 by Interlegis |
||||
|
# |
||||
|
# GNU General Public License (GPL) |
||||
|
# |
||||
|
# This program is free software; you can redistribute it and/or |
||||
|
# modify it under the terms of the GNU General Public License |
||||
|
# as published by the Free Software Foundation; either version 2 |
||||
|
# of the License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU General Public License |
||||
|
# along with this program; if not, write to the Free Software |
||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
||||
|
# 02110-1301, USA. |
||||
|
# |
||||
|
from django.core.management.base import BaseCommand |
||||
|
from sigi.apps.metas.views import gera_map_data_file |
||||
|
|
||||
|
class Command(BaseCommand): |
||||
|
help = u'Gera arquivo de dados de plotagem do mapa de atuação do Interlegis.' |
||||
|
def handle(self, *args, **options): |
||||
|
result = gera_map_data_file(cronjob=True) |
||||
|
self.stdout.write(result+"\n") |
@ -0,0 +1,128 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from datetime import date, datetime |
||||
|
from django.db import models |
||||
|
from sigi.apps.convenios.models import Projeto, Convenio |
||||
|
from sigi.apps.diagnosticos.models import Diagnostico |
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
from sigi.apps.financeiro.models import Desembolso |
||||
|
|
||||
|
class Meta(models.Model): |
||||
|
ALGORITMO_CHOICES = ( |
||||
|
('SUM_GASTOS', u'Soma dos desembolsos'), |
||||
|
('COUNT_EQUI', u'Quantidade de casas equipadas'), |
||||
|
('COUNT_ADER', u'Quantidade de casas aderidas'), |
||||
|
('COUNT_DIAG', u'Quantidade de casas diagnosticadas'), |
||||
|
('COUNT_PDIR', u'Quantidade de planos diretores'), |
||||
|
('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') |
||||
|
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') |
||||
|
data_inicio = models.DateField(u'Data inicial', help_text=u'Início do período de cômputo da meta') |
||||
|
data_fim = models.DateField(u'Data final', help_text=u'Prazo final para cumprimento da meta') |
||||
|
algoritmo = models.CharField(u'Algoritmo de cálculo', max_length=10, choices=ALGORITMO_CHOICES) |
||||
|
valor_meta = models.FloatField(u'Valor da meta', help_text=u'Valor que deve ser atingido até o prazo final da meta') |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'Meta BID' |
||||
|
verbose_name_plural = 'Metas BID' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.titulo; |
||||
|
|
||||
|
@property |
||||
|
def valor_executado(self): |
||||
|
""" |
||||
|
Calcula o valor executado da meta |
||||
|
""" |
||||
|
algoritmo = self.algoritmo.lower() |
||||
|
valor = getattr(self, algoritmo)() |
||||
|
try: |
||||
|
valor = float(valor) |
||||
|
except: |
||||
|
valor = 0.0 |
||||
|
return valor |
||||
|
|
||||
|
@property |
||||
|
def percentual_concluido(self): |
||||
|
return round(float(self.valor_executado) / float(self.valor_meta) * 100.0, 2) |
||||
|
|
||||
|
@property |
||||
|
def valor_desejado(self): |
||||
|
total_dias = (self.data_fim - self.data_inicio).days + 1 |
||||
|
dias_gastos = (date.today() - self.data_inicio).days + 1 |
||||
|
meta_dia = self.valor_meta / total_dias |
||||
|
return meta_dia * dias_gastos |
||||
|
|
||||
|
@property |
||||
|
def percentual_desejado_low(self): |
||||
|
return (self.valor_desejado / self.valor_meta) - 0.05 # 5% abaixo do desejado |
||||
|
|
||||
|
@property |
||||
|
def percentual_desejado_high(self): |
||||
|
return (self.valor_desejado / self.valor_meta) + 0.05 # 5% acima do desejado |
||||
|
|
||||
|
@property |
||||
|
def saude(self): |
||||
|
percentual_concluido = self.percentual_concluido / 100.0 |
||||
|
if percentual_concluido >= 1: |
||||
|
return 'A2BBED' # Blue |
||||
|
|
||||
|
if percentual_concluido > self.percentual_desejado_high: |
||||
|
return '89D7AF' # Green |
||||
|
|
||||
|
if percentual_concluido > self.percentual_desejado_low: |
||||
|
return 'FFDB6E' # Orange |
||||
|
|
||||
|
return 'E74A69' # Red |
||||
|
|
||||
|
def sum_gastos(self): |
||||
|
valor = Desembolso.objects.filter(projeto=self.projeto, data__gte=self.data_inicio, data__lte=self.data_fim) \ |
||||
|
.aggregate(total_dolar=models.Sum('valor_dolar')) |
||||
|
valor = valor['total_dolar'] |
||||
|
return valor |
||||
|
|
||||
|
def count_equi(self): |
||||
|
valor = Convenio.objects.filter(casa_legislativa__tipo__sigla='CM', equipada=True, projeto__pk=3, data_termo_aceite__gte= |
||||
|
self.data_inicio, data_termo_aceite__lte=self.data_fim).exclude(data_termo_aceite=None).count() |
||||
|
return valor |
||||
|
|
||||
|
def count_ader(self): |
||||
|
valor = Convenio.objects.filter(casa_legislativa__tipo__sigla='CM', projeto=self.projeto, data_adesao__gte=self.data_inicio, |
||||
|
data_adesao__lte=self.data_fim).exclude(data_adesao=None).count() |
||||
|
return valor |
||||
|
|
||||
|
def count_diag(self): |
||||
|
valor = Diagnostico.objects.filter(data_visita_inicio__gte=self.data_inicio, data_visita_inicio__lte=self.data_fim, |
||||
|
publicado=True).count() |
||||
|
return valor |
||||
|
|
||||
|
def count_pdir(self): |
||||
|
valor = PlanoDiretor.objects.filter(projeto=self.projeto, data_entrega__gte=self.data_inicio, |
||||
|
data_entrega__lte=self.data_fim).count() |
||||
|
return valor |
||||
|
|
||||
|
def count_conv(self): |
||||
|
valor = Convenio.objects.filter(casa_legislativa__tipo__sigla='CM', projeto=self.projeto, data_retorno_assinatura__gte= |
||||
|
self.data_inicio, data_retorno_assinatura__lte=self.data_fim).exclude(data_retorno_assinatura=None).count() |
||||
|
return valor |
||||
|
|
||||
|
class PlanoDiretor(models.Model): |
||||
|
STATUS_CHOICE = ( |
||||
|
('E', u'Entregue'), |
||||
|
('I', u'Implantado'), |
||||
|
) |
||||
|
projeto = models.ForeignKey(Projeto, verbose_name=u'Projeto') |
||||
|
casa_legislativa = models.ForeignKey(CasaLegislativa, verbose_name=u'Casa legislativa') |
||||
|
casa_legislativa.casa_uf_filter = True |
||||
|
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_implantacao = models.DateField(u'Data de implantação', blank=True, null=True) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'Plano Diretor' |
||||
|
verbose_name_plural = 'Planos Diretores' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.casa_legislativa.nome ; |
||||
|
|
@ -0,0 +1,35 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from django import template |
||||
|
from django.utils.safestring import mark_safe |
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
|
||||
|
register = template.Library() |
||||
|
|
||||
|
@register.filter(name='map_desc_serv') |
||||
|
def descricao_servicos(value): |
||||
|
if not isinstance(value, CasaLegislativa): |
||||
|
return "" |
||||
|
|
||||
|
result = "" |
||||
|
|
||||
|
for sv in value.servico_set.all(): |
||||
|
result += u'<li>%s ativado em %s</li>' % (sv.tipo_servico.nome, sv.data_ativacao.strftime('%d/%m/%Y')) |
||||
|
|
||||
|
for cv in value.convenio_set.all(): |
||||
|
if (cv.data_retorno_assinatura is None) and (cv.equipada and cv.data_termo_aceite is not None): |
||||
|
result += u"<li>Equipada em %s pelo %s</li>" % (cv.data_termo_aceite.strftime('%d/%m/%Y'), cv.projeto.sigla) |
||||
|
if (cv.data_retorno_assinatura is not None) and not (cv.equipada and cv.data_termo_aceite is not None): |
||||
|
result += u"<li>Conveniada ao %s em %s</li>" % (cv.projeto.sigla, cv.data_retorno_assinatura.strftime('%d/%m/%Y')) |
||||
|
if (cv.data_retorno_assinatura is not None) and (cv.equipada and cv.data_termo_aceite is not None): |
||||
|
result += u"<li>Conveniada ao %s em %s e equipada em %s</li>" % (cv.projeto.sigla, cv.data_retorno_assinatura.strftime('%d/%m/%Y'), cv.data_termo_aceite.strftime('%d/%m/%Y')) |
||||
|
|
||||
|
for dg in value.diagnostico_set.all(): |
||||
|
result += u'<li>Diagnosticada no período de %s a %s</li>' % (dg.data_visita_inicio.strftime('%d/%m/%Y') if dg.data_visita_inicio |
||||
|
else u"<< sem data inicial >>", |
||||
|
dg.data_visita_fim.strftime('%d/%m/%Y') if dg.data_visita_fim |
||||
|
else u"<< sem data final >>") |
||||
|
|
||||
|
return mark_safe(result) |
||||
|
descricao_servicos.is_safe = True |
||||
|
|
@ -0,0 +1,3 @@ |
|||||
|
from django.conf.urls.defaults import * |
||||
|
|
||||
|
# place app url patterns here |
@ -0,0 +1,345 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
import csv |
||||
|
from django.http import HttpResponse |
||||
|
from django.core.exceptions import PermissionDenied |
||||
|
from django.utils import simplejson |
||||
|
from django.utils.datastructures import SortedDict |
||||
|
from django.shortcuts import render_to_response |
||||
|
from django.template import RequestContext |
||||
|
from django.db.models import Q |
||||
|
from django.views.decorators.cache import cache_page |
||||
|
from django.db.models.aggregates import Sum |
||||
|
from django.contrib.auth.decorators import user_passes_test, login_required |
||||
|
from sigi.settings import MEDIA_ROOT |
||||
|
from sigi.shortcuts import render_to_pdf |
||||
|
from sigi.apps.servicos.models import TipoServico, Servico |
||||
|
from sigi.apps.convenios.models import Projeto, Convenio |
||||
|
from sigi.apps.contatos.models import UnidadeFederativa |
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
from sigi.apps.utils import to_ascii |
||||
|
from sigi.apps.financeiro.models import Desembolso |
||||
|
from sigi.apps.metas.templatetags.mapa_tags import descricao_servicos |
||||
|
|
||||
|
JSON_FILE_NAME = MEDIA_ROOT + 'apps/metas/map_data.json' |
||||
|
|
||||
|
@login_required |
||||
|
|
||||
|
def dashboard(request): |
||||
|
if request.user.groups.filter(name__in=['SPDT-Servidores', 'SSPLF']).count() <= 0: |
||||
|
raise PermissionDenied |
||||
|
|
||||
|
desembolsos_max = 0 |
||||
|
matriz = SortedDict() |
||||
|
dados = SortedDict() |
||||
|
projetos = Projeto.objects.all() |
||||
|
meses = Desembolso.objects.dates('data', 'month', 'DESC')[:6] |
||||
|
colors = ['ffff00', 'cc7900', 'ff0000', '92d050', '006600', '0097cc', '002776', 'ae78d6', 'ff00ff', '430080', |
||||
|
'28d75c', '0000ff', 'fff200'] |
||||
|
|
||||
|
for date in reversed(meses): |
||||
|
mes_ano = '%s/%s' % (date.month, date.year) |
||||
|
dados[mes_ano] = 0 |
||||
|
|
||||
|
for p in projetos: |
||||
|
matriz[p.id] = (p.sigla, dados.copy()) |
||||
|
|
||||
|
for date in meses: |
||||
|
mes_ano = '%s/%s' % (date.month, date.year) |
||||
|
for d in Desembolso.objects.filter(data__year=date.year, data__month=date.month).values('projeto').annotate(total_dolar=Sum('valor_dolar')): |
||||
|
if int(d['total_dolar']) > desembolsos_max: |
||||
|
desembolsos_max = int(d['total_dolar']) |
||||
|
matriz[d['projeto']][1][mes_ano] += int(d['total_dolar']) |
||||
|
|
||||
|
meses = ["%s/%s" % (m.month, m.year) for m in reversed(meses)] |
||||
|
extra_context = {'desembolsos': matriz, 'desembolsos_max': desembolsos_max, 'meses': meses, 'colors': ','.join(colors[:len(matriz)])} |
||||
|
return render_to_response('metas/dashboard.html', extra_context, context_instance=RequestContext(request)) |
||||
|
|
||||
|
def mapa(request): |
||||
|
""" |
||||
|
Mostra o mapa com filtros carregados com valores default |
||||
|
""" |
||||
|
|
||||
|
regiao_choices = UnidadeFederativa.REGIAO_CHOICES |
||||
|
estado_choices = UnidadeFederativa.objects.all() |
||||
|
servico_choices = TipoServico.objects.all() |
||||
|
projeto_choices = Projeto.objects.all() |
||||
|
|
||||
|
seit = [ ts.sigla for ts in servico_choices] |
||||
|
convenios = ['PML'] # Apenas o ultimo #hardcoded #fixme |
||||
|
equipadas = [] #[p.sigla for p in projeto_choices] |
||||
|
diagnosticos = ['P'] # choices: ["A", "P"] |
||||
|
regioes = [r[0] for r in regiao_choices] |
||||
|
estados = [] |
||||
|
|
||||
|
extra_context = { |
||||
|
'seit': seit, |
||||
|
'convenios': convenios, |
||||
|
'equipadas': equipadas, |
||||
|
'diagnosticos': diagnosticos, |
||||
|
'regioes': regioes, |
||||
|
'estados': estados, |
||||
|
'regiao_choices': regiao_choices, |
||||
|
'estado_choices': estado_choices, |
||||
|
'servico_choices': servico_choices, |
||||
|
'projeto_choices': projeto_choices, |
||||
|
} |
||||
|
|
||||
|
return render_to_response('metas/mapa.html', extra_context, context_instance=RequestContext(request)) |
||||
|
|
||||
|
|
||||
|
@cache_page(1800) # Cache de 30min |
||||
|
def map_data(request): |
||||
|
""" |
||||
|
Retorna json com todos os dados dos municípios que têm relação com o Interlegis |
||||
|
Tenta ler esse json do arquivo JSON_FILE_NAME. Se não encontrar, chama a rotina |
||||
|
gera_map_data_file(). |
||||
|
""" |
||||
|
|
||||
|
try: |
||||
|
file = open(JSON_FILE_NAME, 'r') |
||||
|
json = file.read() |
||||
|
except: |
||||
|
json = gera_map_data_file() |
||||
|
|
||||
|
return HttpResponse(json, mimetype="application/json") |
||||
|
|
||||
|
def map_search(request): |
||||
|
response = {'result': 'NOT_FOUND'} |
||||
|
if 'q' in request.GET: |
||||
|
q = request.GET.get('q') |
||||
|
if len(q.split(',')) > 1: |
||||
|
municipio, uf = [s.strip() for s in q.split(',')] |
||||
|
casas = CasaLegislativa.objects.filter(search_text__icontains=to_ascii(municipio), municipio__uf__sigla__iexact=uf) |
||||
|
else: |
||||
|
casas = CasaLegislativa.objects.filter(search_text__icontains=to_ascii(q)) |
||||
|
if casas.count() > 0: |
||||
|
response = {'result': 'FOUND', 'ids': [c.pk for c in casas]} |
||||
|
|
||||
|
return HttpResponse(simplejson.dumps(response), mimetype="application/json") |
||||
|
|
||||
|
@cache_page(86400) # Cache de um dia (24 horas = 86400 segundos) |
||||
|
def map_sum(request): |
||||
|
# Filtrar Casas de acordo com os parâmetros |
||||
|
param = get_params(request) |
||||
|
casas = filtrar_casas(**param) |
||||
|
|
||||
|
# Montar registros de totalização |
||||
|
tot_servicos = SortedDict() |
||||
|
tot_projetos = SortedDict() |
||||
|
tot_diagnosticos = SortedDict() |
||||
|
|
||||
|
for ts in TipoServico.objects.all(): |
||||
|
tot_servicos[ts.sigla] = 0 |
||||
|
|
||||
|
for pr in Projeto.objects.all(): |
||||
|
tot_projetos[pr.sigla] = 0 |
||||
|
|
||||
|
tot_convenios = tot_projetos.copy() |
||||
|
tot_equipadas = tot_projetos.copy() |
||||
|
|
||||
|
tot_diagnosticos['A'] = 0 |
||||
|
tot_diagnosticos['P'] = 0 |
||||
|
|
||||
|
# Montar as linhas do array de resultados com as regiões e os estados |
||||
|
result = {} |
||||
|
|
||||
|
for uf in UnidadeFederativa.objects.filter(Q(regiao__in=param['regioes']) | Q(sigla__in=param['estados'])).order_by('regiao', 'nome'): |
||||
|
if not result.has_key(uf.regiao): |
||||
|
result[uf.regiao] = {'nome': uf.get_regiao_display(), 'ufs': {}, 'servicos': tot_servicos.copy(), |
||||
|
'convenios': tot_projetos.copy(), 'equipadas': tot_projetos.copy(), |
||||
|
'diagnosticos': tot_diagnosticos.copy()} |
||||
|
result[uf.regiao]['ufs'][uf.codigo_ibge] = {'nome': uf.nome, 'servicos': tot_servicos.copy(), |
||||
|
'convenios': tot_projetos.copy(), 'equipadas': tot_projetos.copy(), |
||||
|
'diagnosticos': tot_diagnosticos.copy()} |
||||
|
|
||||
|
|
||||
|
# Processar as casas filtradas |
||||
|
for casa in casas.distinct(): |
||||
|
uf = casa.municipio.uf |
||||
|
for s in casa.servico_set.all(): |
||||
|
tot_servicos[s.tipo_servico.sigla] += 1 |
||||
|
result[uf.regiao]['servicos'][s.tipo_servico.sigla] += 1 |
||||
|
result[uf.regiao]['ufs'][uf.codigo_ibge]['servicos'][s.tipo_servico.sigla] += 1 |
||||
|
for c in casa.convenio_set.all(): |
||||
|
tot_convenios[c.projeto.sigla] += 1 |
||||
|
result[uf.regiao]['convenios'][c.projeto.sigla] += 1 |
||||
|
result[uf.regiao]['ufs'][uf.codigo_ibge]['convenios'][c.projeto.sigla] += 1 |
||||
|
if (c.equipada and c.data_termo_aceite is not None): |
||||
|
tot_equipadas[c.projeto.sigla] += 1 |
||||
|
result[uf.regiao]['equipadas'][c.projeto.sigla] += 1 |
||||
|
result[uf.regiao]['ufs'][uf.codigo_ibge]['equipadas'][c.projeto.sigla] += 1 |
||||
|
for d in casa.diagnostico_set.all(): |
||||
|
if d.publicado: |
||||
|
tot_diagnosticos['P'] += 1 |
||||
|
result[uf.regiao]['diagnosticos']['P'] += 1 |
||||
|
result[uf.regiao]['ufs'][uf.codigo_ibge]['diagnosticos']['P'] += 1 |
||||
|
else: |
||||
|
tot_diagnosticos['A'] += 1 |
||||
|
result[uf.regiao]['diagnosticos']['A'] += 1 |
||||
|
result[uf.regiao]['ufs'][uf.codigo_ibge]['diagnosticos']['A'] += 1 |
||||
|
|
||||
|
extra_context = { |
||||
|
'pagesize': 'a4 landscape', |
||||
|
'servicos': TipoServico.objects.all(), |
||||
|
'projetos': Projeto.objects.all(), |
||||
|
'result': result, |
||||
|
'tot_servicos': tot_servicos, |
||||
|
'tot_convenios': tot_convenios, |
||||
|
'tot_equipadas': tot_equipadas, |
||||
|
'tot_diagnosticos': tot_diagnosticos, |
||||
|
} |
||||
|
return render_to_pdf('metas/map_sum.html', extra_context) |
||||
|
|
||||
|
@cache_page(86400) # Cache de um dia (24 horas = 86400 segundos) |
||||
|
def map_list(request): |
||||
|
# Filtrar Casas de acordo com os parâmetros |
||||
|
param = get_params(request) |
||||
|
formato = request.GET.get('fmt', 'pdf') |
||||
|
casas = filtrar_casas(**param) |
||||
|
casas = casas.order_by('municipio__uf__regiao', 'municipio__uf__nome', 'nome').distinct() |
||||
|
|
||||
|
if formato == 'csv': |
||||
|
response = HttpResponse(content_type='text/csv') |
||||
|
response['Content-Disposition'] = 'attachment; filename="maplist.csv"' |
||||
|
writer = csv.writer(response) |
||||
|
|
||||
|
srv = {} |
||||
|
for ts in TipoServico.objects.all(): |
||||
|
srv[ts.pk] = ts.nome |
||||
|
|
||||
|
cnv = {} |
||||
|
for pr in Projeto.objects.all(): |
||||
|
cnv[pr.id] = pr.sigla |
||||
|
|
||||
|
writer.writerow([u'codigo_ibge', u'nome_casa', u'municipio', u'uf', u'regiao',] + [x for x in srv.values()] + |
||||
|
reduce(lambda x,y: x+y, [['conveniada ao %s' % x, 'equipada por %s' % x] for x in cnv.values()])) |
||||
|
|
||||
|
for casa in casas: |
||||
|
row = [casa.municipio.codigo_ibge, casa.nome, casa.municipio.nome, casa.municipio.uf.sigla, |
||||
|
casa.municipio.uf.get_regiao_display(),] |
||||
|
for id in srv.keys(): |
||||
|
try: |
||||
|
sv = casa.servico_set.get(tipo_servico__id=id) |
||||
|
row += [sv.data_ativacao,] |
||||
|
except: |
||||
|
row += [None,] |
||||
|
for id in cnv.keys(): |
||||
|
try: |
||||
|
cv = casa.convenio_set.get(projeto__id=id) |
||||
|
row += [cv.data_retorno_assinatura, cv.data_termo_aceite if cv.equipada else None,] |
||||
|
except: |
||||
|
row += [None, None,] |
||||
|
|
||||
|
writer.writerow(row) |
||||
|
return response |
||||
|
|
||||
|
return render_to_pdf('metas/map_list.html', {'casas': casas}) |
||||
|
|
||||
|
|
||||
|
#---------------------------------------------------------------------------------------------------- |
||||
|
# Funções auxiliares - não são views |
||||
|
#---------------------------------------------------------------------------------------------------- |
||||
|
|
||||
|
def get_params(request): |
||||
|
''' Pegar parâmetros da pesquisa ''' |
||||
|
return { |
||||
|
'seit' : request.GET.getlist('seit'), |
||||
|
'convenios' : request.GET.getlist('convenios'), |
||||
|
'equipadas' : request.GET.getlist('equipadas'), |
||||
|
'diagnosticos' : request.GET.getlist('diagnosticos'), |
||||
|
'regioes' : request.GET.getlist('regioes'), |
||||
|
'estados' : request.GET.getlist('estados'), |
||||
|
} |
||||
|
|
||||
|
def filtrar_casas(seit, convenios, equipadas, regioes, estados, diagnosticos): |
||||
|
''' Filtrar Casas que atendem aos parâmetros de pesquisa ''' |
||||
|
qServico = Q(servico__tipo_servico__sigla__in=seit) |
||||
|
qConvenio = Q(convenio__projeto__sigla__in=convenios) |
||||
|
qEquipada = Q(convenio__projeto__sigla__in=equipadas, convenio__equipada=True) |
||||
|
qRegiao = Q(municipio__uf__regiao__in=regioes) |
||||
|
qEstado = Q(municipio__uf__sigla__in=estados) |
||||
|
|
||||
|
if diagnosticos: |
||||
|
qDiagnostico = Q(diagnostico__publicado__in=[p == 'P' for p in diagnosticos]) |
||||
|
else: |
||||
|
qDiagnostico = Q() |
||||
|
|
||||
|
casas = CasaLegislativa.objects.filter(qServico | qConvenio | qEquipada | qDiagnostico).filter(qRegiao | qEstado) |
||||
|
|
||||
|
return casas |
||||
|
|
||||
|
def gera_map_data_file(cronjob=False): |
||||
|
''' Criar um arquivo json em {settings.MEDIA_ROOT}/apps/metas/ com o nome de map_data.json |
||||
|
Este arquivo será consumido pela view de dados de mapa. |
||||
|
Retorna os dados json caso cronjob seja falso. |
||||
|
Caso cronjob seja True, retorna log de tempo gasto na geração ou a mensagem do erro |
||||
|
que impediu a gravação do arquivo. |
||||
|
''' |
||||
|
import time |
||||
|
start = time.time() |
||||
|
|
||||
|
casas = {} |
||||
|
|
||||
|
for c in CasaLegislativa.objects.select_related('servico', 'convenio', 'diagnostico').all().distinct(): |
||||
|
if c.servico_set.count() == 0 and c.convenio_set.count() == 0 and c.diagnostico_set.count() == 0: |
||||
|
continue; # Salta essa casa, pois ela não tem nada com o Interlegis |
||||
|
|
||||
|
if not casas.has_key(c.pk): |
||||
|
casa = { |
||||
|
'nome': c.nome + ', ' + c.municipio.uf.sigla, |
||||
|
'icone': 'mapmarker', |
||||
|
'lat': str(c.municipio.latitude), |
||||
|
'lng': str(c.municipio.longitude), |
||||
|
'estado': c.municipio.uf.sigla, |
||||
|
'regiao': c.municipio.uf.regiao, |
||||
|
'diagnosticos': [], |
||||
|
'seit': [], |
||||
|
'convenios': [], |
||||
|
'equipadas': [], |
||||
|
'info': [] |
||||
|
} |
||||
|
|
||||
|
for sv in c.servico_set.all(): |
||||
|
casa['info'].append(u"%s ativado em %s <a href='%s' target='_blank'><img src='/sigi/media/images/link.gif' alt='link'></a>" % ( |
||||
|
sv.tipo_servico.nome, sv.data_ativacao.strftime('%d/%m/%Y') if sv.data_ativacao else |
||||
|
u'<sem data de ativação>', sv.url)) |
||||
|
casa['seit'].append(sv.tipo_servico.sigla) |
||||
|
|
||||
|
for cv in c.convenio_set.all(): |
||||
|
if (cv.data_retorno_assinatura is None) and (cv.equipada and cv.data_termo_aceite is not None): |
||||
|
casa['info'].append(u"Equipada em %s pelo %s" % (cv.data_termo_aceite.strftime('%d/%m/%Y'), cv.projeto.sigla)) |
||||
|
casa['equipadas'].append(cv.projeto.sigla) |
||||
|
if (cv.data_retorno_assinatura is not None) and not (cv.equipada and cv.data_termo_aceite is not None): |
||||
|
casa['info'].append(u"Conveniada ao %s em %s" % (cv.projeto.sigla, cv.data_retorno_assinatura.strftime('%d/%m/%Y'))) |
||||
|
casa['convenios'].append(cv.projeto.sigla) |
||||
|
if (cv.data_retorno_assinatura is not None) and (cv.equipada and cv.data_termo_aceite is not None): |
||||
|
casa['info'].append(u"Conveniada ao %s em %s e equipada em %s" % (cv.projeto.sigla, cv.data_retorno_assinatura.strftime('%d/%m/%Y'), cv.data_termo_aceite.strftime('%d/%m/%Y'))) |
||||
|
casa['equipadas'].append(cv.projeto.sigla) |
||||
|
casa['convenios'].append(cv.projeto.sigla) |
||||
|
|
||||
|
for dg in c.diagnostico_set.all(): |
||||
|
casa['diagnosticos'].append('P' if dg.publicado else 'A') |
||||
|
casa['info'].append(u'Diagnosticada no período de %s a %s' % (dg.data_visita_inicio.strftime('%d/%m/%Y') if |
||||
|
dg.data_visita_inicio is not None else u"<sem data de início>", |
||||
|
dg.data_visita_fim.strftime('%d/%m/%Y') if dg.data_visita_fim else u"<sem data de término>")) |
||||
|
|
||||
|
casa['info'] = "<br/>".join(casa['info']) |
||||
|
|
||||
|
casas[c.pk] = casa |
||||
|
|
||||
|
json_data = simplejson.dumps(casas) |
||||
|
|
||||
|
try: |
||||
|
file = open(JSON_FILE_NAME, 'w') |
||||
|
file.write(json_data) |
||||
|
file.close() |
||||
|
except Exception as e: # A gravação não foi bem sucedida ... |
||||
|
if cronjob: # ... o chamador deseja a mensagem de erro |
||||
|
return str(e) |
||||
|
else: |
||||
|
pass # ... ou os dados poderão ser usados de qualquer forma |
||||
|
|
||||
|
if cronjob: |
||||
|
return "Arquivo %s gerado em %d segundos" % (JSON_FILE_NAME, time.time() - start) |
||||
|
|
||||
|
return json_data |
@ -0,0 +1,105 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.core.urlresolvers import reverse |
||||
|
from django.http import HttpResponseRedirect |
||||
|
from django.contrib import admin |
||||
|
from django.contrib.admin.views.main import ChangeList |
||||
|
from eav.admin import BaseEntityAdmin, BaseSchemaAdmin |
||||
|
from sigi.apps.servidores.models import Servidor |
||||
|
from sigi.apps.ocorrencias.models import Ocorrencia, Comentario, Anexo, Categoria |
||||
|
|
||||
|
class ComentarioViewInline(admin.TabularInline): |
||||
|
model = Comentario |
||||
|
extra = 0 |
||||
|
max_num=0 |
||||
|
can_delete = False |
||||
|
verbose_name, verbose_name_plural = u"Comentário anterior", u"Comentários anteriores" |
||||
|
fields = ('usuario', 'data_criacao', 'novo_status', 'encaminhar_setor', 'descricao', ) |
||||
|
readonly_fields = ('novo_status', 'encaminhar_setor', 'descricao', 'data_criacao', 'usuario',) |
||||
|
|
||||
|
class ComentarioInline(admin.StackedInline): |
||||
|
model = Comentario |
||||
|
extra = 3 |
||||
|
verbose_name, verbose_name_plural = u"Comentário novo", u"Comentários novos" |
||||
|
fieldsets = ((None, {'fields': (('novo_status', 'encaminhar_setor',), 'descricao', )}),) |
||||
|
def queryset(self, request): |
||||
|
return self.model.objects.get_empty_query_set() |
||||
|
|
||||
|
class AnexosInline(admin.TabularInline): |
||||
|
model = Anexo |
||||
|
extra = 2 |
||||
|
readonly_fields = ['data_pub',] |
||||
|
|
||||
|
class OcorrenciaChangeList(ChangeList): |
||||
|
request = None |
||||
|
def __init__(self, request, model, list_display, list_display_links, list_filter, date_hierarchy, search_fields, |
||||
|
list_select_related, list_per_page, list_editable, model_admin): |
||||
|
self.request = request |
||||
|
super(OcorrenciaChangeList, self).__init__(request, model, list_display, list_display_links, list_filter, |
||||
|
date_hierarchy, search_fields, list_select_related, list_per_page, |
||||
|
list_editable, model_admin) |
||||
|
def get_query_set(self): |
||||
|
tmp_params = self.params.copy() |
||||
|
grupo = None |
||||
|
if 'grupo' in self.params: |
||||
|
grupo = self.params['grupo'] |
||||
|
del self.params['grupo'] |
||||
|
qs = super(OcorrenciaChangeList, self).get_query_set() |
||||
|
self.params = tmp_params.copy() |
||||
|
if grupo: |
||||
|
servidor = Servidor.objects.get(user=self.request.user) |
||||
|
if grupo == 'S': # Apenas do meu setor |
||||
|
qs = qs.filter(setor_responsavel=servidor.servico) |
||||
|
elif grupo == 'M': # Apenas criados por mim |
||||
|
qs = qs.filter(servidor_registro=servidor) |
||||
|
return qs |
||||
|
|
||||
|
class OcorrenciaAdmin(admin.ModelAdmin): |
||||
|
list_display = ('data_criacao', 'casa_legislativa', 'assunto', 'prioridade', 'status', 'data_modificacao', 'setor_responsavel',) |
||||
|
list_filter = ('assunto', 'status', 'prioridade', 'categoria', 'setor_responsavel', ) |
||||
|
search_fields = ('casa_legislativa__search_text', 'assunto', 'servidor_registro__nome', ) |
||||
|
date_hierarchy = 'data_criacao' |
||||
|
fields = ('casa_legislativa', 'categoria', 'assunto', 'status', 'prioridade', 'descricao', 'servidor_registro', |
||||
|
'setor_responsavel', 'resolucao', ) |
||||
|
readonly_fields = ('servidor_registro', 'setor_responsavel', ) |
||||
|
inlines = (ComentarioViewInline, ComentarioInline, AnexosInline, ) |
||||
|
raw_id_fields = ('casa_legislativa', ) |
||||
|
|
||||
|
def get_changelist(self, request, **kwargs): |
||||
|
return OcorrenciaChangeList |
||||
|
|
||||
|
def get_readonly_fields(self, request, obj=None): |
||||
|
fields = list(self.readonly_fields) |
||||
|
if obj is not None: |
||||
|
fields.extend(['casa_legislativa', 'categoria', 'assunto', 'status', 'descricao', ]) |
||||
|
if obj.status in [3, 4, 5]: #Fechados |
||||
|
fields.append('prioridade') |
||||
|
return fields |
||||
|
|
||||
|
def get_fieldsets(self, request, obj=None): |
||||
|
if obj is None: |
||||
|
self.fields = ('casa_legislativa', 'categoria', 'assunto', 'prioridade', 'descricao', 'resolucao', ) |
||||
|
return super(OcorrenciaAdmin, self).get_fieldsets(request, obj) |
||||
|
|
||||
|
def save_model(self, request, obj, form, change): |
||||
|
if not change: |
||||
|
obj.servidor_registro = Servidor.objects.get(user=request.user) |
||||
|
obj.setor_responsavel = obj.categoria.setor_responsavel |
||||
|
obj.save() |
||||
|
|
||||
|
def save_formset(self, request, form, formset, change): |
||||
|
servidor = Servidor.objects.get(user=request.user) |
||||
|
instances = formset.save(commit=False) |
||||
|
for instance in instances: |
||||
|
instance.usuario = servidor |
||||
|
instance.save() |
||||
|
if instance.encaminhar_setor and (instance.encaminhar_setor != instance.ocorrencia.setor_responsavel): |
||||
|
instance.ocorrencia.setor_responsavel = instance.encaminhar_setor |
||||
|
instance.ocorrencia.save() |
||||
|
if instance.novo_status and (instance.novo_status != instance.ocorrencia.status): |
||||
|
instance.ocorrencia.status = instance.novo_status |
||||
|
instance.ocorrencia.save() |
||||
|
|
||||
|
formset.save_m2m() |
||||
|
|
||||
|
admin.site.register(Ocorrencia, OcorrenciaAdmin) |
||||
|
admin.site.register(Categoria) |
@ -0,0 +1,79 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.db import models |
||||
|
from datetime import datetime |
||||
|
from django.db import models |
||||
|
from sigi.apps.utils import SearchField |
||||
|
#from eav.models import BaseChoice, BaseEntity, BaseSchema, BaseAttribute |
||||
|
|
||||
|
class Categoria(models.Model): |
||||
|
nome= models.CharField(max_length=50) |
||||
|
descricao = models.TextField('descrição', blank=True, null=True) |
||||
|
setor_responsavel = models.ForeignKey('servidores.Servico', verbose_name=u"Setor responsável") |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name, verbose_name_plural = u'Categoria', u'Categorias' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.nome |
||||
|
|
||||
|
class Ocorrencia(models.Model): |
||||
|
STATUS_CHOICES = ( |
||||
|
(1, u'Aberto'), |
||||
|
(2, u'Reaberto'), |
||||
|
(3, u'Resolvido'), |
||||
|
(4, u'Fechado'), |
||||
|
(5, u'Duplicado'), |
||||
|
) |
||||
|
|
||||
|
PRIORITY_CHOICES = ( |
||||
|
(1, u'Altíssimo'), |
||||
|
(2, u'Alto'), |
||||
|
(3, u'Normal'), |
||||
|
(4, u'Baixo'), |
||||
|
(5, u'Baixíssimo'), |
||||
|
) |
||||
|
|
||||
|
casa_legislativa = models.ForeignKey('casas.CasaLegislativa', verbose_name=u'Casa Legislativa') |
||||
|
casa_legislativa.convenio_uf_filter = True |
||||
|
casa_legislativa.convenio_cl_tipo_filter = True |
||||
|
data_criacao = models.DateField(u'Data de criação', null=True, blank=True, auto_now_add=True) |
||||
|
data_modificacao = models.DateField(u'Data de modificação', null=True, blank=True, auto_now=True) |
||||
|
categoria = models.ForeignKey(Categoria, verbose_name=u'Categoria') |
||||
|
assunto = models.CharField(u'Assunto', max_length=200) |
||||
|
assunto.grupo_filter = True |
||||
|
status = models.IntegerField(u'Status', choices=STATUS_CHOICES, default=1,) |
||||
|
status.multichoice_filter = True |
||||
|
prioridade = models.IntegerField(u'Prioridade', choices=PRIORITY_CHOICES, default=3, ) |
||||
|
descricao = models.TextField(u'descrição', blank=True,) |
||||
|
resolucao = models.TextField(u'resolução', blank=True,) |
||||
|
servidor_registro = models.ForeignKey('servidores.Servidor', verbose_name=u"Servidor que registrou a ocorrência") |
||||
|
setor_responsavel = models.ForeignKey('servidores.Servico', verbose_name=u"Setor responsável") |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name, verbose_name_plural = u'ocorrência', u'ocorrências' |
||||
|
ordering = ['prioridade', 'data_modificacao', 'data_criacao', ] |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return u"%(casa_legislativa)s: %(assunto)s" % {'assunto': self.assunto, 'casa_legislativa': self.casa_legislativa} |
||||
|
|
||||
|
class Comentario(models.Model): |
||||
|
ocorrencia = models.ForeignKey(Ocorrencia, verbose_name=u'Ocorrência') |
||||
|
data_criacao = models.DateTimeField(u'Data de criação', null=True, blank=True, auto_now_add=True) |
||||
|
descricao = models.TextField(u'Descrição', blank=True, null=True) |
||||
|
usuario = models.ForeignKey('servidores.Servidor', verbose_name=u'Usuário') |
||||
|
novo_status = models.IntegerField(u'Novo status', choices=Ocorrencia.STATUS_CHOICES, blank=True, null=True) |
||||
|
encaminhar_setor = models.ForeignKey('servidores.Servico', verbose_name=u'Encaminhar para setor', blank=True, null=True) |
||||
|
|
||||
|
class Anexo(models.Model): |
||||
|
ocorrencia = models.ForeignKey(Ocorrencia, verbose_name=u'ocorrência') |
||||
|
arquivo = models.FileField(u'Arquivo anexado', upload_to='apps/ocorrencia/anexo/arquivo',) |
||||
|
descricao = models.CharField(u'descrição do anexo', max_length='70') |
||||
|
data_pub = models.DateTimeField( u'data da publicação do anexo', null=True, blank=True, auto_now_add=True) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('-data_pub',) |
||||
|
verbose_name, verbose_name_plural = u'Anexo', u'Anexos' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return u"%(arquivo_name)s: %(descricao)s" % {'arquivo_name': self.arquivo.name, 'descricao': self.descricao} |
||||
|
|
@ -0,0 +1,75 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.contrib import admin |
||||
|
from django.contrib.contenttypes import generic |
||||
|
from django.http import HttpResponse, HttpResponseRedirect |
||||
|
|
||||
|
from sigi.apps.contatos.models import Telefone |
||||
|
from sigi.apps.parlamentares.models import Partido, Parlamentar, Mandato |
||||
|
from sigi.apps.parlamentares.views import adicionar_parlamentar_carrinho |
||||
|
|
||||
|
class MandatosInline(admin.TabularInline): |
||||
|
model = Mandato |
||||
|
extra = 1 |
||||
|
raw_id_fields = ('legislatura', 'partido') |
||||
|
|
||||
|
class TelefonesInline(generic.GenericTabularInline): |
||||
|
model = Telefone |
||||
|
extra = 2 |
||||
|
|
||||
|
class PartidoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('nome', 'sigla') |
||||
|
list_display_links = ('nome', 'sigla') |
||||
|
search_fields = ('nome', 'sigla') |
||||
|
|
||||
|
class ParlamentarAdmin(admin.ModelAdmin): |
||||
|
inlines = (TelefonesInline, MandatosInline) |
||||
|
list_display = ('nome_completo', 'nome_parlamentar', 'sexo') |
||||
|
list_display_links = ('nome_completo', 'nome_parlamentar') |
||||
|
list_filter = ('nome_completo', 'nome_parlamentar') |
||||
|
actions = ['adiciona_parlamentar',] |
||||
|
fieldsets = ( |
||||
|
(None, { |
||||
|
'fields': ('nome_completo', 'nome_parlamentar', 'sexo'), |
||||
|
}), |
||||
|
# ('Endereço', { |
||||
|
# 'fields': ('logradouro', 'bairro', 'municipio', 'cep'), |
||||
|
# }), |
||||
|
('Outras informações', { |
||||
|
'fields': ('data_nascimento', 'email', 'pagina_web', 'foto'), |
||||
|
}), |
||||
|
) |
||||
|
radio_fields = {'sexo': admin.VERTICAL} |
||||
|
# raw_id_fields = ('municipio',) |
||||
|
search_fields = ('nome_completo', 'nome_parlamentar', 'email', |
||||
|
'pagina_web',) |
||||
|
|
||||
|
def adiciona_parlamentar(self, request, queryset): |
||||
|
if request.session.has_key('carrinho_parlametar'): |
||||
|
q1 = len(request.session['carrinho_parlamentar']) |
||||
|
else: |
||||
|
q1 = 0 |
||||
|
adicionar_parlamentar_carrinho(request,queryset=queryset) |
||||
|
q2 = len(request.session['carrinho_parlamentar']) |
||||
|
quant = q2 - q1 |
||||
|
if quant: |
||||
|
self.message_user(request,"%s Parlamentares adicionados no carrinho" % (quant) ) |
||||
|
else: |
||||
|
self.message_user(request,"Os parlamentares selecionadas já foram adicionadas anteriormente" ) |
||||
|
return HttpResponseRedirect('.') |
||||
|
|
||||
|
adiciona_parlamentar.short_description = u"Armazenar parlamentar no carrinho para exportar" |
||||
|
|
||||
|
|
||||
|
class MandatoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('parlamentar', 'legislatura', 'partido', |
||||
|
'inicio_mandato', 'fim_mandato', 'is_afastado') |
||||
|
list_filter = ('is_afastado', 'partido') |
||||
|
search_fields = ('legislatura__numero', 'parlamentar__nome_completo', |
||||
|
'parlamentar__nome_parlamentar', 'partido__nome', |
||||
|
'partido__sigla') |
||||
|
raw_id_fields = ('parlamentar', 'legislatura', 'partido') |
||||
|
# radio_fields = {'suplencia': admin.VERTICAL} |
||||
|
|
||||
|
admin.site.register(Partido, PartidoAdmin) |
||||
|
admin.site.register(Parlamentar, ParlamentarAdmin) |
||||
|
admin.site.register(Mandato, MandatoAdmin) |
@ -0,0 +1,218 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"pk": 5, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "DEM", |
||||
|
"nome": "Democratas" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 19, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PCB", |
||||
|
"nome": "Partido Comunista Brasileiro" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 6, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PCdoB", |
||||
|
"nome": "Partido Comunista do Brasil" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 4, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PDT", |
||||
|
"nome": "Partido Democr\u00e1tico Trabalhista" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 20, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PHS", |
||||
|
"nome": "Partido Humanista da Solidariedade" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 13, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PPS", |
||||
|
"nome": "Partido Popular Socialista" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 17, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PP", |
||||
|
"nome": "Partido Progressista" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 16, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PRTB", |
||||
|
"nome": "Partido Renovador Trabalhista Brasileiro" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 25, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PRB", |
||||
|
"nome": "Partido Republicano Brasileiro" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 12, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PRP", |
||||
|
"nome": "Partido Republicano Progressista" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 10, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PSC", |
||||
|
"nome": "Partido Social Crist\u00e3o" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 21, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PSDC", |
||||
|
"nome": "Partido Social Democrata Crist\u00e3o" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 24, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PSL", |
||||
|
"nome": "Partido Social Liberal" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 26, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PSOL", |
||||
|
"nome": "Partido Socialismo e Liberdade" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 7, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PSB", |
||||
|
"nome": "Partido Socialista Brasileiro" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 18, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PSTU", |
||||
|
"nome": "Partido Socialista dos Trabalhadores Unificado" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 3, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PTB", |
||||
|
"nome": "Partido Trabalhista Brasileiro" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 9, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PTC", |
||||
|
"nome": "Partido Trabalhista Crist\u00e3o" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 23, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PTN", |
||||
|
"nome": "Partido Trabalhista Nacional" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 15, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PTdoB", |
||||
|
"nome": "Partido Trabalhista do Brasil" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 14, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PV", |
||||
|
"nome": "Partido Verde" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 22, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PCO", |
||||
|
"nome": "Partido da Causa Oper\u00e1ria" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 11, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PMN", |
||||
|
"nome": "Partido da Mobiliza\u00e7\u00e3o Nacional" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 27, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PR", |
||||
|
"nome": "Partido da Rep\u00fablica" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 8, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PSDB", |
||||
|
"nome": "Partido da Social Democracia Brasileira" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 2, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PMDB", |
||||
|
"nome": "Partido do Movimento Democr\u00e1tico Brasileiro" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"pk": 1, |
||||
|
"model": "parlamentares.partido", |
||||
|
"fields": { |
||||
|
"sigla": "PT", |
||||
|
"nome": "Partido dos Trabalhadores" |
||||
|
} |
||||
|
} |
||||
|
] |
@ -0,0 +1,81 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.db import models |
||||
|
from django.contrib.contenttypes import generic |
||||
|
|
||||
|
|
||||
|
class Partido(models.Model): |
||||
|
nome = models.CharField(max_length=50) |
||||
|
sigla = models.CharField(max_length=10) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('nome',) |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return '%s (%s)' % (unicode(self.nome), unicode(self.sigla)) |
||||
|
|
||||
|
|
||||
|
class Parlamentar(models.Model): |
||||
|
SEXO_CHOICES = ( |
||||
|
('M', 'Masculino'), |
||||
|
('F', 'Feminino'), |
||||
|
) |
||||
|
nome_completo = models.CharField(max_length=128) |
||||
|
nome_completo.alphabetic_filter = True |
||||
|
nome_parlamentar = models.CharField(max_length=35, blank=True) |
||||
|
foto = models.ImageField( |
||||
|
upload_to='fotos/parlamentares', |
||||
|
width_field='foto_largura', |
||||
|
height_field='foto_altura', |
||||
|
blank=True |
||||
|
) |
||||
|
foto_largura = models.SmallIntegerField(editable=False, null=True) |
||||
|
foto_altura = models.SmallIntegerField(editable=False, null=True) |
||||
|
sexo = models.CharField( |
||||
|
max_length=1, |
||||
|
choices=SEXO_CHOICES, |
||||
|
) |
||||
|
data_nascimento = models.DateField( |
||||
|
'data de nascimento', |
||||
|
blank=True, |
||||
|
null=True, |
||||
|
) |
||||
|
email = models.EmailField('e-mail', blank=True) |
||||
|
pagina_web = models.URLField(u'página web', |
||||
|
blank=True) |
||||
|
|
||||
|
class Meta: |
||||
|
ordering = ('nome_completo',) |
||||
|
verbose_name_plural = 'parlamentares' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
if self.nome_parlamentar: |
||||
|
return self.nome_parlamentar |
||||
|
return self.nome_completo |
||||
|
|
||||
|
|
||||
|
class Mandato(models.Model): |
||||
|
SUPLENCIA_CHOICES = ( |
||||
|
('T', 'Titular'), |
||||
|
('S', 'Suplente'), |
||||
|
) |
||||
|
parlamentar = models.ForeignKey(Parlamentar) |
||||
|
legislatura = models.ForeignKey('mesas.Legislatura') |
||||
|
partido = models.ForeignKey(Partido) |
||||
|
cargo = models.ForeignKey('mesas.Cargo') |
||||
|
inicio_mandato = models.DateField(u'início de mandato') |
||||
|
fim_mandato = models.DateField('fim de mandato') |
||||
|
is_afastado = models.BooleanField( |
||||
|
'afastado', |
||||
|
default=False, |
||||
|
help_text=u'Marque caso parlamentar não esteja ativo.' |
||||
|
) |
||||
|
|
||||
|
# suplencia = models.CharField( |
||||
|
# u'suplência', |
||||
|
# max_length=1, |
||||
|
# choices=SUPLENCIA_CHOICES, |
||||
|
# ) |
||||
|
|
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return str(self.id) |
@ -0,0 +1,539 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from reportlab.lib.pagesizes import A4 |
||||
|
from reportlab.lib.units import cm |
||||
|
from reportlab.lib.enums import TA_CENTER, TA_RIGHT |
||||
|
from geraldo import Report, DetailBand, Label, ObjectValue, ManyElements, \ |
||||
|
ReportGroup, ReportBand, landscape, SubReport, BAND_WIDTH,SystemField |
||||
|
|
||||
|
from sigi.apps.relatorios.reports import ReportDefault |
||||
|
|
||||
|
from geraldo.graphics import Image |
||||
|
|
||||
|
def string_to_cm(texto): |
||||
|
tamanho = 0 |
||||
|
minEspeciais = { |
||||
|
'f':0.1, |
||||
|
'i':0.05, |
||||
|
'j':0.05, |
||||
|
'l':0.05, |
||||
|
'm':0.2, |
||||
|
'r':0.1, |
||||
|
't':0.15, |
||||
|
} |
||||
|
maiuEspeciais = { |
||||
|
'I':0.05, |
||||
|
'J':0.15, |
||||
|
'L':0.15, |
||||
|
'P':0.15, |
||||
|
} |
||||
|
for c in texto: |
||||
|
if c > 'a' and c<'z': |
||||
|
if c in minEspeciais: |
||||
|
tamanho += minEspeciais[c] |
||||
|
else: |
||||
|
tamanho += 0.17 |
||||
|
else: |
||||
|
if c in maiuEspeciais: |
||||
|
tamanho += maiuEspeciais[c] |
||||
|
else: |
||||
|
tamanho += 0.2 |
||||
|
return tamanho |
||||
|
|
||||
|
class ParlamentaresLabels(Report): |
||||
|
""" |
||||
|
Usage example:: |
||||
|
|
||||
|
>>> from geraldo.generators import PDFGenerator |
||||
|
>>> queryset = CasaLegislativa.objects.filter(municipio__uf__sigla='MG') |
||||
|
>>> report = LabelsReport(queryset) |
||||
|
>>> report.generate_by(PDFGenerator, filename='./inline-detail-report.pdf') |
||||
|
|
||||
|
""" |
||||
|
formato = '' |
||||
|
y = 2 |
||||
|
largura_etiqueta = 7 |
||||
|
altura_etiqueta = 3.3 |
||||
|
tamanho_fonte = 6.4 |
||||
|
altura_dados = 0.3 #logradouro, bairro, municipio, cep |
||||
|
delta = start = 0.5 |
||||
|
|
||||
|
def __init__(self, queryset, formato): |
||||
|
super(ParlamentaresLabels, self).__init__(queryset=queryset) |
||||
|
self.formato = formato |
||||
|
self.page_size = A4 |
||||
|
|
||||
|
if formato == '3x9_etiqueta': |
||||
|
self.margin_top = 0.0*cm |
||||
|
self.margin_bottom = 0.0*cm |
||||
|
self.margin_left = -1*cm |
||||
|
self.margin_right = 0.0*cm |
||||
|
self.delta = 0.4 # espaçamento entre as "strings/linhas" da etiqueta |
||||
|
self.start = 0.2 # valor entre a margin top e a etiqueta |
||||
|
else: |
||||
|
self.margin_top = 0.8*cm |
||||
|
self.margin_bottom = 0.8*cm |
||||
|
self.margin_left = 0.4*cm |
||||
|
self.margin_right = 0.4*cm |
||||
|
self.largura_etiqueta = 9.9 |
||||
|
self.altura_etiqueta = 5.6 |
||||
|
self.tamanho_fonte = 11 |
||||
|
self.altura_dados = 0.5 |
||||
|
self.y = 0.5 |
||||
|
|
||||
|
my_elements = [ |
||||
|
Label( |
||||
|
text=u'A Sua Excelência o(a) Senhor(a)', |
||||
|
top=(self.start + self.delta)*cm, left=self.y*cm, width=(self.largura_etiqueta-self.y)*cm, |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='nome_completo', |
||||
|
top=(self.start + 2*self.delta)*cm, left=self.y*cm, width=(self.largura_etiqueta-self.y)*cm, |
||||
|
get_value=lambda instance: |
||||
|
instance.nome_completo or "" |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='logradouro', |
||||
|
top=(self.start + 3*self.delta)*cm, left=self.y*cm, width=(self.largura_etiqueta-self.y)*cm, |
||||
|
get_value=lambda instance: |
||||
|
logradouro_parlamentar(instance) |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='bairro', |
||||
|
top=(self.start + 4*self.delta)*cm, left=self.y*cm, width=(self.largura_etiqueta-self.y)*cm, |
||||
|
get_value=lambda instance: |
||||
|
bairro_parlamentar(instance) |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='municipio', |
||||
|
top=(self.start + 5*self.delta)*cm, left=self.y*cm, width=(self.largura_etiqueta-self.y)*cm, |
||||
|
get_value=lambda instance: |
||||
|
municipio_parlamentar(instance) |
||||
|
), |
||||
|
ObjectValue( |
||||
|
attribute_name='cep', |
||||
|
top=(self.start + 6*self.delta)*cm, left=self.y*cm, width=(self.largura_etiqueta-self.y)*cm, |
||||
|
get_value=lambda instance: |
||||
|
cep_parlamentar(instance) |
||||
|
), |
||||
|
] |
||||
|
self.band_detail = DetailBand(width=(self.largura_etiqueta)*cm, height=(self.altura_etiqueta)*cm, margin_left = 0, margin_top = 0, margin_bottom=0.0*cm, margin_right = 0, elements=my_elements,display_inline=True, default_style={'fontName': 'Helvetica', 'fontSize': self.tamanho_fonte}) |
||||
|
|
||||
|
def logradouro_parlamentar(instance): |
||||
|
try: |
||||
|
return instance.mandato_set.latest('inicio_mandato').legislatura.casa_legislativa.logradouro |
||||
|
except: |
||||
|
return u"<<PARLAMENTAR SEM MANDATO - impossivel definir endereço>>" |
||||
|
|
||||
|
def bairro_parlamentar(instance): |
||||
|
try: |
||||
|
return instance.mandato_set.latest('inicio_mandato').legislatura.casa_legislativa.bairro |
||||
|
except: |
||||
|
return u"<<PARLAMENTAR SEM MANDATO - impossivel definir endereço>>" |
||||
|
|
||||
|
def municipio_parlamentar(instance): |
||||
|
try: |
||||
|
return instance.mandato_set.latest('inicio_mandato').legislatura.casa_legislativa.municipio |
||||
|
except: |
||||
|
return u"<<PARLAMENTAR SEM MANDATO - impossivel definir endereço>>" |
||||
|
|
||||
|
def cep_parlamentar(instance): |
||||
|
try: |
||||
|
return instance.mandato_set.latest('inicio_mandato').legislatura.casa_legislativa.cep |
||||
|
except: |
||||
|
return u"<<PARLAMENTAR SEM MANDATO - impossivel definir endereço>>" |
||||
|
|
||||
|
|
||||
|
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= ReportDefault.band_page_header.BASE_DIR + '/media/images/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= ReportDefault.band_page_header.BASE_DIR + '/media/images/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 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=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=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': 'Sul','SD': 'Sudeste','CO': 'Centro-Oeste','NE': 'Nordeste','NO': 'Norte',} |
||||
|
[instance.municipio.uf.regiao] |
||||
|
), |
||||
|
Label( |
||||
|
text=u"U.F.: ", |
||||
|
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=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=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=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=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=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=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=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':'Fixo','M':u'Móvel','X':'Fax','I':'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 != 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 != 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 != 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 != None else '-' |
||||
|
), |
||||
|
], |
||||
|
#borders = {'all':True}, |
||||
|
), |
||||
|
) |
||||
|
] |
@ -0,0 +1,78 @@ |
|||||
|
{% extends "admin/carrinho.html" %} |
||||
|
{% load adminmedia admin_list i18n %} |
||||
|
{% block extrastyle %} |
||||
|
{{ block.super }} |
||||
|
{% include "admin/tabs_style.html" %} |
||||
|
|
||||
|
|
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block title %}Parlamentares no Carrinho | SIGI{% endblock %} |
||||
|
{% block content_title %}<h1>Parlamentares no Carrinho</h1>{% endblock %} |
||||
|
|
||||
|
{% block mensagem%} |
||||
|
<ul class="messagelist"> |
||||
|
{%if carIsEmpty%} |
||||
|
<li class="warning">O carrinho está vazio, sendo assim todas as casas entram na lista para exportação de acordo com os filtros aplicados.</li> |
||||
|
{%else%} |
||||
|
<li>{{paginas.paginator.count}}Parlamentares no carrinho.</li> |
||||
|
{%endif%} |
||||
|
</ul> |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block action %}deleta_itens_carrinho{% endblock %} |
||||
|
|
||||
|
{% block tabela %} |
||||
|
<table> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
{%if not carIsEmpty%} |
||||
|
<th class="sorted ascending"><!-- <input type="checkbox" id="action-toggle" style="display: inline;">--> |
||||
|
</th> |
||||
|
{% endif %} |
||||
|
<th class="sorted ascending">Nome</th> |
||||
|
<th class="sorted ascending">Nome parlamentar</th> |
||||
|
<th class="sorted ascending">Sexo</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
{% for parlamentar in paginas.object_list %} |
||||
|
<tr class="{% cycle 'row1' 'row2' %}"> |
||||
|
{%if not carIsEmpty%} |
||||
|
<th><input type="checkbox" name="_selected_action" |
||||
|
value="{{parlamentar.id}}" class="action-select" /></th> |
||||
|
{% endif %} |
||||
|
<td style="text-align: left;">{{parlamentar.nome_completo}}</td> |
||||
|
<td>{{parlamentar.nome_parlamentar}}</td> |
||||
|
<td>{{parlamentar.get_sexo_display}}</td> |
||||
|
</tr> |
||||
|
{% endfor %} |
||||
|
</tbody> |
||||
|
</table> |
||||
|
{% endblock %} |
||||
|
|
||||
|
{% block botoes %} |
||||
|
<div id="tabs"> |
||||
|
<ul> |
||||
|
<li><a href="#tabs-1">Etiqueta</a></li> |
||||
|
</ul> |
||||
|
|
||||
|
<div id="tabs-1"> |
||||
|
<form action="../labels/{{query_str}}" method="post">{% csrf_token %} |
||||
|
<fieldset><legend>Formato da Etiqueta</legend> |
||||
|
<ul class="formato_etiqueta"> |
||||
|
<li><input type="radio" name="tamanho_etiqueta" |
||||
|
value="2x5_etiqueta"><label>2x5</label></li> |
||||
|
<li><input type="radio" name="tamanho_etiqueta" |
||||
|
value="3x9_etiqueta" checked="checked"><label>3x9</label></li> |
||||
|
|
||||
|
</ul> |
||||
|
</fieldset> |
||||
|
<ul class="botoes"> |
||||
|
<li><input type="submit" value="Gerar Etiqueta" /></li> |
||||
|
</ul> |
||||
|
</form> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
{% endblock %} |
@ -0,0 +1,14 @@ |
|||||
|
{% extends "admin/change_form.html" %} |
||||
|
{% load i18n reporting_tags %} |
||||
|
|
||||
|
{% block object-tools %} |
||||
|
{% if change %}{% if not is_popup %} |
||||
|
<ul class="object-tools"> |
||||
|
<li><a href="report_complete/">Relatório</a></li> |
||||
|
<li><a href="labels/">Etiqueta</a></li> |
||||
|
<li><a href="labels_sem_presidente/">Etiqueta sem presidente</a></li> |
||||
|
<li><a href="history/" class="historylink">{% trans "History" %}</a></li> |
||||
|
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%} |
||||
|
</ul> |
||||
|
{% endif %}{% endif %} |
||||
|
{% endblock %} |
@ -0,0 +1,9 @@ |
|||||
|
{% extends "admin/change_list.html" %} |
||||
|
{% load adminmedia admin_list i18n reporting_tags %} |
||||
|
|
||||
|
{% block object-tools %} |
||||
|
<ul class="object-tools"> |
||||
|
<li><a href="#">Casas sem Processo de Convênio</a></li> |
||||
|
</ul> |
||||
|
|
||||
|
{% endblock %} |
@ -0,0 +1,149 @@ |
|||||
|
# coding: utf-8 |
||||
|
import datetime |
||||
|
import csv |
||||
|
import ho.pisa as pisa |
||||
|
|
||||
|
from django.template import Context, loader |
||||
|
from django.core.paginator import Paginator, InvalidPage, EmptyPage |
||||
|
from django.conf import settings |
||||
|
from django.shortcuts import render_to_response, get_list_or_404 |
||||
|
from django.http import HttpResponse, HttpResponseRedirect |
||||
|
from django.views.decorators.csrf import csrf_protect |
||||
|
from django.template import RequestContext |
||||
|
|
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
from sigi.apps.parlamentares.models import Parlamentar |
||||
|
from sigi.apps.parlamentares.reports import ParlamentaresLabels |
||||
|
|
||||
|
from geraldo.generators import PDFGenerator |
||||
|
|
||||
|
|
||||
|
def adicionar_parlamentar_carrinho(request,queryset=None,id=None): |
||||
|
if request.method == 'POST': |
||||
|
ids_selecionados = request.POST.getlist('_selected_action') |
||||
|
if not request.session.has_key('carrinho_parlametar'): |
||||
|
request.session['carrinho_parlamentar'] = ids_selecionados |
||||
|
else: |
||||
|
lista = request.session['carrinho_parlamentar'] |
||||
|
# Verifica se id já não está adicionado |
||||
|
for id in ids_selecionados: |
||||
|
if not id in lista: |
||||
|
lista.append(id) |
||||
|
request.session['carrinho_parlamentar'] = lista |
||||
|
|
||||
|
|
||||
|
@csrf_protect |
||||
|
def visualizar_carrinho(request): |
||||
|
|
||||
|
qs = carrinhoOrGet_for_qs(request) |
||||
|
|
||||
|
paginator = Paginator(qs, 100) |
||||
|
|
||||
|
# Make sure page request is an int. If not, deliver first page. |
||||
|
# Esteja certo de que o `page request` é um inteiro. Se não, mostre a primeira página. |
||||
|
try: |
||||
|
page = int(request.GET.get('page', '1')) |
||||
|
except ValueError: |
||||
|
page = 1 |
||||
|
|
||||
|
# Se o page request (9999) está fora da lista, mostre a última página. |
||||
|
try: |
||||
|
paginas = paginator.page(page) |
||||
|
except (EmptyPage, InvalidPage): |
||||
|
paginas = paginator.page(paginator.num_pages) |
||||
|
|
||||
|
carrinhoIsEmpty = not(request.session.has_key('carrinho_parlamentares')) |
||||
|
|
||||
|
return render_to_response('parlamentares/carrinho.html', |
||||
|
{"ADMIN_MEDIA_PREFIX":settings.ADMIN_MEDIA_PREFIX, |
||||
|
'MEDIA_URL':settings.MEDIA_URL, |
||||
|
'carIsEmpty':carrinhoIsEmpty, |
||||
|
'paginas':paginas, |
||||
|
'query_str':'?'+request.META['QUERY_STRING']}, |
||||
|
context_instance=RequestContext(request)) |
||||
|
|
||||
|
|
||||
|
def carrinhoOrGet_for_qs(request): |
||||
|
""" |
||||
|
Verifica se existe parlamentares na sessão se não verifica get e retorna qs correspondente. |
||||
|
""" |
||||
|
if request.session.has_key('carrinho_parlamentar'): |
||||
|
ids = request.session['carrinho_parlamentar'] |
||||
|
qs = Parlamentar.objects.filter(pk__in=ids) |
||||
|
else: |
||||
|
qs = Parlamentar.objects.all() |
||||
|
if request.GET: |
||||
|
qs = get_for_qs(request.GET,qs) |
||||
|
return qs |
||||
|
|
||||
|
|
||||
|
def query_ordena(qs,o,ot): |
||||
|
list_display = ('nome_completo',) |
||||
|
|
||||
|
aux = list_display[(int(o)-1)] |
||||
|
if ot =='asc': |
||||
|
qs = qs.order_by(aux) |
||||
|
else: |
||||
|
qs = qs.order_by("-"+aux) |
||||
|
return qs |
||||
|
|
||||
|
|
||||
|
def get_for_qs(get,qs): |
||||
|
""" |
||||
|
Verifica atributos do GET e retorna queryset correspondente |
||||
|
""" |
||||
|
kwargs = {} |
||||
|
for k,v in get.iteritems(): |
||||
|
if not (k == 'page' or k == 'pop' or k == 'q'): |
||||
|
if not k == 'o': |
||||
|
if k == "ot": |
||||
|
qs = query_ordena(qs,get["o"],get["ot"]) |
||||
|
else: |
||||
|
kwargs[str(k)] = v |
||||
|
qs = qs.filter(**kwargs) |
||||
|
return qs |
||||
|
|
||||
|
|
||||
|
def deleta_itens_carrinho(request): |
||||
|
""" |
||||
|
Deleta itens selecionados do carrinho |
||||
|
""" |
||||
|
if request.method == 'POST': |
||||
|
ids_selecionados = request.POST.getlist('_selected_action') |
||||
|
if request.session.has_key('carrinho_parlamentar'): |
||||
|
lista = request.session['carrinho_parlamentar'] |
||||
|
for item in ids_selecionados: |
||||
|
lista.remove(item) |
||||
|
if lista: |
||||
|
request.session['carrinho_parlamentar'] = lista |
||||
|
else: |
||||
|
del lista; |
||||
|
del request.session['carrinho_parlamentar'] |
||||
|
|
||||
|
return HttpResponseRedirect('.') |
||||
|
|
||||
|
|
||||
|
def labels_report(request, id=None, formato='3x9_etiqueta'): |
||||
|
""" TODO: adicionar suporte para resultado de pesquisa do admin. |
||||
|
""" |
||||
|
|
||||
|
if request.POST: |
||||
|
if request.POST.has_key('tipo_etiqueta'): |
||||
|
tipo = request.POST['tipo_etiqueta'] |
||||
|
|
||||
|
|
||||
|
if id: |
||||
|
qs = Parlamentar.objects.filter(pk=id) |
||||
|
|
||||
|
else: |
||||
|
qs = carrinhoOrGet_for_qs(request) |
||||
|
|
||||
|
if not qs: |
||||
|
return HttpResponseRedirect('../') |
||||
|
|
||||
|
response = HttpResponse(mimetype='application/pdf') |
||||
|
response['Content-Disposition'] = 'attachment; filename=casas.pdf' |
||||
|
report = ParlamentaresLabels(queryset=qs, formato=formato) |
||||
|
report.generate_by(PDFGenerator, filename=response) |
||||
|
|
||||
|
return response |
@ -0,0 +1,3 @@ |
|||||
|
from django.db import models |
||||
|
|
||||
|
# Create your models here. |
@ -0,0 +1,76 @@ |
|||||
|
#-*- coding:utf-8 -*- |
||||
|
import os |
||||
|
|
||||
|
from geraldo import Report, ReportBand, ObjectValue, DetailBand, Label, \ |
||||
|
landscape,SystemField, BAND_WIDTH,ReportGroup, \ |
||||
|
FIELD_ACTION_SUM, FIELD_ACTION_COUNT, Line |
||||
|
from geraldo.graphics import Image |
||||
|
from reportlab.lib.units import cm |
||||
|
from reportlab.lib.pagesizes import A4 |
||||
|
from reportlab.lib.enums import TA_CENTER, TA_RIGHT |
||||
|
from reportlab.lib.colors import navy, red |
||||
|
|
||||
|
|
||||
|
class ReportDefault(Report): |
||||
|
#__metaclass__ = ABCMeta |
||||
|
title = u'Relatório' |
||||
|
author = u'Interlegis' |
||||
|
print_if_empty = True |
||||
|
page_size = A4 |
||||
|
|
||||
|
class band_page_header(ReportBand): |
||||
|
height = 4.2*cm |
||||
|
label_top = 3.7*cm |
||||
|
default_style = {'fontName': 'Helvetica', 'fontSize':9} |
||||
|
|
||||
|
BASE_DIR = os.path.abspath(os.path.dirname(__file__) + '../../../../') |
||||
|
#BASE_DIR = os.path.abspath(os.getcwd() + '../..') |
||||
|
|
||||
|
elements = [ |
||||
|
Image(filename= BASE_DIR + '/media/images/logo-interlegis.jpg', |
||||
|
left=15.5*cm,right=1*cm,top=0.1*cm,bottom=1*cm, |
||||
|
width=4.2*cm,height=3*cm, |
||||
|
), |
||||
|
Image(filename= BASE_DIR + '/media/images/logo-senado.png', |
||||
|
left=1*cm,right=1*cm,top=0.1*cm,bottom=1*cm, |
||||
|
width=3*cm,height=3*cm, |
||||
|
), |
||||
|
Label(text="SENADO FEDERAL",top=1*cm,left=0,width=BAND_WIDTH, |
||||
|
style={'fontName': 'Helvetica-Bold','fontSize':14, 'alignment': TA_CENTER} |
||||
|
), |
||||
|
Label(text="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} |
||||
|
), |
||||
|
] |
||||
|
borders = {'bottom': True} |
||||
|
|
||||
|
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), |
||||
|
SystemField(expression=u'Página %(page_number)d de %(page_count)d', top=0.3*cm, |
||||
|
width=BAND_WIDTH, style={'alignment': TA_RIGHT} |
||||
|
), |
||||
|
] |
||||
|
#borders = {'top': True} |
||||
|
|
||||
|
class band_detail(DetailBand): |
||||
|
height = 0.5*cm |
||||
|
default_style = {'fontName': 'Helvetica', 'fontSize': 8} |
||||
|
auto_expand_height = True |
||||
|
|
||||
|
class band_summary(ReportBand): |
||||
|
height = 0.8*cm |
||||
|
elements = [ |
||||
|
Label(text="Total:", top=0.1*cm, left=0), |
||||
|
ObjectValue(attribute_name='id', top=0.1*cm, left=1*cm,\ |
||||
|
action=FIELD_ACTION_COUNT, display_format='%s'), |
||||
|
] |
||||
|
borders = {'top': Line(stroke_color=navy, stroke_width=2)} |
||||
|
|
||||
|
|
@ -0,0 +1,23 @@ |
|||||
|
""" |
||||
|
This file demonstrates two different styles of tests (one doctest and one |
||||
|
unittest). These will both pass when you run "manage.py test". |
||||
|
|
||||
|
Replace these with more appropriate tests for your application. |
||||
|
""" |
||||
|
|
||||
|
from django.test import TestCase |
||||
|
|
||||
|
class SimpleTest(TestCase): |
||||
|
def test_basic_addition(self): |
||||
|
""" |
||||
|
Tests that 1 + 1 always equals 2. |
||||
|
""" |
||||
|
self.failUnlessEqual(1 + 1, 2) |
||||
|
|
||||
|
__test__ = {"doctest": """ |
||||
|
Another way to test that 1 + 1 is equal to 2. |
||||
|
|
||||
|
>>> 1 + 1 == 2 |
||||
|
True |
||||
|
"""} |
||||
|
|
@ -0,0 +1 @@ |
|||||
|
# Create your views here. |
@ -0,0 +1,214 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.contrib import admin |
||||
|
from sigi.apps.servicos.models import Servico, LogServico, CasaAtendida, TipoServico |
||||
|
#from sigi.apps.casas.models import Funcionario |
||||
|
from sigi.apps.casas.admin import FuncionariosInline |
||||
|
from django.http import Http404, HttpResponseRedirect |
||||
|
from django.forms.models import ModelForm |
||||
|
from django.utils.encoding import force_unicode |
||||
|
from django.utils.translation import ugettext as _ |
||||
|
from django.core.urlresolvers import reverse |
||||
|
from apps.casas.models import CasaLegislativa |
||||
|
|
||||
|
#---------------- inlines --------------------- |
||||
|
class LogServicoInline(admin.StackedInline): |
||||
|
model = LogServico |
||||
|
Fieldset = ((None, {'fields': (('data', 'descricao'), 'log')})) |
||||
|
extra = 1 |
||||
|
|
||||
|
# --------------- forms ----------------------- |
||||
|
class ServicoFormAdmin(ModelForm): |
||||
|
class Meta: |
||||
|
model = Servico |
||||
|
|
||||
|
def __init__(self, *args, **kwargs): |
||||
|
super(ServicoFormAdmin, self).__init__(*args, **kwargs) |
||||
|
|
||||
|
self.fields['contato_tecnico'].choices = () |
||||
|
self.fields['contato_administrativo'].choices = () |
||||
|
|
||||
|
if self.instance.casa_legislativa_id: |
||||
|
id_casa = self.instance.casa_legislativa_id |
||||
|
elif kwargs.has_key('initial') and kwargs['initial'].has_key('id_casa'): |
||||
|
id_casa = kwargs['initial']['id_casa'] |
||||
|
self.instance.casa_legislativa_id = id_casa |
||||
|
else: |
||||
|
id_casa = None |
||||
|
|
||||
|
if id_casa: |
||||
|
casa = CasaAtendida.objects.get(pk=id_casa) |
||||
|
contatos = [(f.id, unicode(f)) for f in casa.funcionario_set.all()] |
||||
|
self.fields['contato_tecnico'].choices = contatos |
||||
|
self.fields['contato_administrativo'].choices = contatos |
||||
|
|
||||
|
#---------------- admins ---------------------- |
||||
|
class TipoServicoAdmin(admin.ModelAdmin): |
||||
|
list_display = ('id', 'sigla', 'nome', 'qtde_casas_atendidas', ) |
||||
|
ordering = ['id'] |
||||
|
|
||||
|
class ServicoAdmin(admin.ModelAdmin): |
||||
|
form = ServicoFormAdmin |
||||
|
actions = ['calcular_data_uso',] |
||||
|
list_display = ('casa_legislativa', 'get_codigo_interlegis', 'get_uf', 'tipo_servico', 'hospedagem_interlegis', |
||||
|
'data_ativacao', 'data_desativacao', 'getUrl', 'data_ultimo_uso', 'get_link_erro') |
||||
|
fieldsets = (( None, { |
||||
|
'fields': ('casa_legislativa', 'data_ativacao',) |
||||
|
}), |
||||
|
( 'Serviço', { |
||||
|
'fields': ('tipo_servico', ('url', 'hospedagem_interlegis'), ('nome_servidor', 'porta_servico', 'senha_inicial'),) |
||||
|
}), |
||||
|
( 'Contatos', { |
||||
|
'fields': ('contato_tecnico', 'contato_administrativo',) |
||||
|
}), |
||||
|
( 'Alterações', { |
||||
|
'fields': ('data_alteracao', 'data_desativacao', 'motivo_desativacao',) |
||||
|
})) |
||||
|
readonly_fields = ('casa_legislativa', 'data_ativacao', 'data_alteracao') |
||||
|
list_filter = ('tipo_servico', 'hospedagem_interlegis', 'data_ultimo_uso', 'casa_legislativa', ) |
||||
|
list_display_links = [] |
||||
|
ordering = ('casa_legislativa__municipio__uf', 'casa_legislativa', 'tipo_servico',) |
||||
|
inlines = (LogServicoInline,) |
||||
|
search_fields = ('casa_legislativa__search_text',) |
||||
|
|
||||
|
def get_codigo_interlegis(self, obj): |
||||
|
return obj.casa_legislativa.codigo_interlegis |
||||
|
get_codigo_interlegis.short_description = u'Código Interlegis' |
||||
|
get_codigo_interlegis.admin_order_field = 'casa_legislativa__codigo_interlegis' |
||||
|
|
||||
|
def get_uf(self, obj): |
||||
|
return u'%s' % (obj.casa_legislativa.municipio.uf) |
||||
|
get_uf.short_description = 'UF' |
||||
|
get_uf.admin_order_field = 'casa_legislativa__municipio__uf' |
||||
|
|
||||
|
def getUrl(self, obj): |
||||
|
return u'<a href="%s" target="_blank">%s</a>' % (obj.url, obj.url) |
||||
|
getUrl.short_description = 'Url' |
||||
|
getUrl.allow_tags = True |
||||
|
|
||||
|
def get_link_erro(self, obj): |
||||
|
if not obj.erro_atualizacao: |
||||
|
return u"" |
||||
|
url = obj.url |
||||
|
if url[-1] != '/': |
||||
|
url += '/' |
||||
|
url += obj.tipo_servico.string_pesquisa |
||||
|
return u'<a href="%s" target="_blank">%s</a>' % (url, obj.erro_atualizacao) |
||||
|
get_link_erro.allow_tags = True |
||||
|
get_link_erro.short_description = u"Erro na atualização" |
||||
|
get_link_erro.admin_order_field = 'erro_atualizacao' |
||||
|
|
||||
|
def calcular_data_uso(self, request, queryset): |
||||
|
for servico in queryset: |
||||
|
servico.atualiza_data_uso() |
||||
|
self.message_user(request, "Atualização concluída. Os sites que não responderam foram deixados com a data em branco" ) |
||||
|
return HttpResponseRedirect('.') |
||||
|
calcular_data_uso.short_description = u"Atualizar a data do último uso do(s) serviço(s)" |
||||
|
|
||||
|
def get_actions(self, request): |
||||
|
from django.utils.datastructures import SortedDict |
||||
|
actions = [self.get_action(action) for action in self.actions] |
||||
|
actions = filter(None, actions) |
||||
|
actions.sort(lambda a,b: cmp(a[2].lower(), b[2].lower())) |
||||
|
actions = SortedDict([ (name, (func, name, desc)) for func, name, desc in actions ]) |
||||
|
return actions |
||||
|
|
||||
|
def lookup_allowed(self, lookup, value): |
||||
|
return super(ServicoAdmin, self).lookup_allowed(lookup, value) or \ |
||||
|
lookup in ['casa_legislativa__municipio__uf__codigo_ibge__exact'] |
||||
|
|
||||
|
|
||||
|
def add_view(self, request, form_url='', extra_context=None): |
||||
|
id_casa = request.GET.get('id_casa', None) |
||||
|
|
||||
|
if not id_casa: |
||||
|
raise Http404 |
||||
|
|
||||
|
return super(ServicoAdmin, self).add_view(request, form_url, extra_context=extra_context) |
||||
|
|
||||
|
def response_add(self, request, obj): |
||||
|
opts = obj._meta |
||||
|
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj)} |
||||
|
|
||||
|
if request.POST.has_key("_addanother"): |
||||
|
self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name))) |
||||
|
return HttpResponseRedirect(request.path + '?id_casa=%s' % (obj.casa_legislativa.id,)) |
||||
|
elif request.POST.has_key("_save"): |
||||
|
self.message_user(request, msg) |
||||
|
return HttpResponseRedirect(reverse('admin:servicos_casaatendida_change', args=[obj.casa_legislativa.id])) |
||||
|
|
||||
|
return super(ServicoAdmin, self).response_add(request, obj) |
||||
|
|
||||
|
def response_change(self, request, obj): |
||||
|
opts = obj._meta |
||||
|
msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj)} |
||||
|
|
||||
|
if request.POST.has_key("_addanother"): |
||||
|
self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name))) |
||||
|
return HttpResponseRedirect("../add/?id_casa=%s" % (obj.casa_legislativa.id,)) |
||||
|
elif request.POST.has_key("_save"): |
||||
|
self.message_user(request, msg) |
||||
|
return HttpResponseRedirect(reverse('admin:servicos_casaatendida_change', args=[obj.casa_legislativa.id])) |
||||
|
|
||||
|
return super(ServicoAdmin, self).response_change(request, obj) |
||||
|
|
||||
|
def save_form(self, request, form, change): |
||||
|
obj = super( ServicoAdmin, self).save_form(request, form, change) |
||||
|
|
||||
|
if not change: |
||||
|
id_casa = request.GET.get('id_casa', None) |
||||
|
|
||||
|
if not id_casa: |
||||
|
raise Http404 |
||||
|
|
||||
|
obj.casa_legislativa = CasaAtendida.objects.get(pk=id_casa) |
||||
|
|
||||
|
return obj |
||||
|
|
||||
|
class ContatosInline(FuncionariosInline): |
||||
|
can_delete = False # Equipe do SEIT não pode excluir pessoas de contato |
||||
|
|
||||
|
class CasaAtendidaAdmin(admin.ModelAdmin): |
||||
|
actions = None |
||||
|
list_display = ('codigo_interlegis', 'nome', 'get_servicos',) |
||||
|
ordering = ['nome'] |
||||
|
fieldsets = ( |
||||
|
('Casa legislativa', { |
||||
|
'fields': (('codigo_interlegis', 'nome'), ('logradouro', 'bairro', 'municipio', 'cep'), ('email', 'pagina_web')) |
||||
|
}) |
||||
|
,) |
||||
|
readonly_fields = ('nome', 'logradouro', 'bairro', 'municipio', 'cep') |
||||
|
inlines = (ContatosInline,) |
||||
|
list_filter = ('tipo', 'codigo_interlegis', 'municipio', ) |
||||
|
search_fields = ('search_text','cnpj', 'bairro', 'logradouro', |
||||
|
'cep', 'municipio__nome', 'municipio__uf__nome', |
||||
|
'municipio__codigo_ibge', 'pagina_web', 'observacoes') |
||||
|
|
||||
|
def get_servicos(self, obj): |
||||
|
result = [] |
||||
|
for servico in obj.servico_set.all(): |
||||
|
result.append(u"%s (%s). Contato: %s" % (servico.tipo_servico.nome, 'ativo' if servico.data_desativacao is None |
||||
|
else 'Desativado', servico.contato_administrativo.nome)) |
||||
|
|
||||
|
return "<ul><li>" + "</li><li>".join(result) + "</li></ul>" |
||||
|
get_servicos.allow_tags = True |
||||
|
get_servicos.short_description = u"Serviços" |
||||
|
|
||||
|
def lookup_allowed(self, lookup, value): |
||||
|
return super(CasaAtendidaAdmin, self).lookup_allowed(lookup, value) or \ |
||||
|
lookup in ['municipio__uf__codigo_ibge__exact', 'servico__tipo_servico__id__exact', ] |
||||
|
|
||||
|
def change_view(self, request, object_id, extra_context=None): |
||||
|
# Se a Casa ainda não é atendida, gerar o código interlegis para ela |
||||
|
# Assim ela passa a ser uma casa atendida |
||||
|
casa = CasaLegislativa.objects.get(id=object_id) |
||||
|
|
||||
|
if casa.codigo_interlegis == '': |
||||
|
casa.gerarCodigoInterlegis() |
||||
|
|
||||
|
return super(CasaAtendidaAdmin, self).change_view(request, object_id, extra_context=extra_context) |
||||
|
|
||||
|
def has_add_permission(self, request): |
||||
|
return False # Nunca é permitido inserir uma nova Casa Legislativa por aqui |
||||
|
|
||||
|
def has_delete_permission(self, request, obj=None): |
||||
|
return False # Nunca deletar casas por aqui |
@ -0,0 +1 @@ |
|||||
|
[{"pk": 1, "model": "servicos.tiposervico", "fields": {"template_email_altera": "Seu Portal Modelo foi alterado com sucesso. O endere\u00e7o de acesso \u00e9 {url} e a senha \u00e9 {senha}. Altere sua senha no primeiro acesso.", "sigla": "PM", "template_email_ativa": "Seu Portal Modelo foi ativado com sucesso. O endere\u00e7o de acesso \u00e9 {url} e a senha inicial \u00e9 {senha}. Altere sua senha no primeiro acesso.", "template_email_desativa": "Seu Portal Modelo foi desativado com sucesso. O endere\u00e7o de acesso era {url}.\r\nO motivo do cancelamento foi: {motivo}", "nome": "Portal Modelo"}}, {"pk": 2, "model": "servicos.tiposervico", "fields": {"template_email_altera": "Seu SAPL foi alterado com sucesso. O endere\u00e7o de acesso \u00e9 {url} e a senha \u00e9 {senha}. Altere sua senha no primeiro acesso.", "sigla": "SAPL", "template_email_ativa": "Seu SAPL foi ativado com sucesso. O endere\u00e7o de acesso \u00e9 {url} e a senha inicial \u00e9 {senha}. Altere sua senha no primeiro acesso.", "template_email_desativa": "Seu SAPL foi desativado com sucesso. O endere\u00e7o de acesso era {url}.\r\nO motivo do cancelamento foi: {motivo}", "nome": "Hospedagem SAPL"}}, {"pk": 3, "model": "servicos.tiposervico", "fields": {"template_email_altera": "Seu SAAP foi alterado com sucesso. O endere\u00e7o de acesso \u00e9 {url} e a senha \u00e9 {senha}. Altere sua senha no primeiro acesso.", "sigla": "SAAP", "template_email_ativa": "Seu SAAP foi ativado com sucesso. O endere\u00e7o de acesso \u00e9 {url} e a senha inicial \u00e9 {senha}. Altere sua senha no primeiro acesso.", "template_email_desativa": "Seu SAAP foi desativado com sucesso. O endere\u00e7o de acesso era {url}.\r\nO motivo do cancelamento foi: {motivo}", "nome": "Hospedagem SAAP"}}] |
@ -0,0 +1,35 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# |
||||
|
# sigi.apps.servicos.management.commands.atualiza_uso_servico |
||||
|
# |
||||
|
# Copyright (c) 2012 by Interlegis |
||||
|
# |
||||
|
# GNU General Public License (GPL) |
||||
|
# |
||||
|
# This program is free software; you can redistribute it and/or |
||||
|
# modify it under the terms of the GNU General Public License |
||||
|
# as published by the Free Software Foundation; either version 2 |
||||
|
# of the License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU General Public License |
||||
|
# along with this program; if not, write to the Free Software |
||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
||||
|
# 02110-1301, USA. |
||||
|
# |
||||
|
from django.core.management.base import BaseCommand |
||||
|
from sigi.apps.servicos.models import Servico |
||||
|
|
||||
|
class Command(BaseCommand): |
||||
|
help = u'Atualiza a informação de data de último serviço dos serviços SEIT hospedados no Interlegis.' |
||||
|
def handle(self, *args, **options): |
||||
|
verbosity = int(options['verbosity']) |
||||
|
queryset = Servico.objects.exclude(url="").exclude(tipo_servico__string_pesquisa="") |
||||
|
for obj in queryset: |
||||
|
obj.atualiza_data_uso() |
||||
|
if ((verbosity == 1) and (obj.data_ultimo_uso is None)) or (verbosity > 1): |
||||
|
self.stdout.write(u"%s \t %s \t %s\n" % (obj.url, obj.data_ultimo_uso, obj.erro_atualizacao)) |
@ -0,0 +1,196 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.db import models |
||||
|
from sigi.apps.casas.models import CasaLegislativa, Funcionario |
||||
|
from datetime import date |
||||
|
from django.core.mail import send_mail |
||||
|
from sigi.settings import DEFAULT_FROM_EMAIL |
||||
|
|
||||
|
class TipoServico(models.Model): |
||||
|
email_help = u'''Use:<br/> |
||||
|
{url} para incluir a URL do serviço,<br/> |
||||
|
{senha} para incluir a senha inicial do serviço''' |
||||
|
nome = models.CharField(u'Nome', max_length=60) |
||||
|
sigla = models.CharField(u'Sigla', max_length='12') |
||||
|
string_pesquisa = models.CharField(u'String de pesquisa', blank=True, max_length=200, |
||||
|
help_text=u'Sufixo para pesquisa RSS para averiguar a data da última atualização do serviço') |
||||
|
template_email_ativa = models.TextField(u'Template de email de ativação', help_text = email_help, blank=True) |
||||
|
template_email_altera = models.TextField(u'Template de email de alteração', help_text = email_help, blank=True) |
||||
|
template_email_desativa = models.TextField(u'Template de email de desativação', help_text = email_help + u'<br/>{motivo} para incluir o motivo da desativação do serviço', blank=True) |
||||
|
|
||||
|
@property |
||||
|
def qtde_casas_atendidas(self): |
||||
|
u"""Quantidade de casas atendidas""" |
||||
|
return self.servico_set.filter(data_desativacao=None).count() |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = u'Tipo de serviço' |
||||
|
verbose_name_plural = u'Tipos de serviço' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.nome; |
||||
|
|
||||
|
class Servico(models.Model): |
||||
|
casa_legislativa = models.ForeignKey(CasaLegislativa, verbose_name=u'Casa legislativa') |
||||
|
tipo_servico = models.ForeignKey(TipoServico, verbose_name=u'Tipo de serviço') |
||||
|
contato_tecnico = models.ForeignKey(Funcionario, verbose_name=u'Contato técnico', related_name='contato_tecnico') |
||||
|
contato_administrativo = models.ForeignKey(Funcionario, verbose_name=u'Contato administrativo', related_name='contato_administrativo') |
||||
|
url = models.URLField(u'URL do serviço', blank=True) |
||||
|
hospedagem_interlegis = models.BooleanField(u'Hospedagem no Interlegis?') |
||||
|
nome_servidor = models.CharField(u'Hospedado em', max_length=60, blank=True, |
||||
|
help_text=u'Se hospedado no Interlegis, informe o nome do servidor.<br/>Senão, informe o nome do provedor de serviços.') |
||||
|
porta_servico = models.PositiveSmallIntegerField(u'Porta de serviço (instância)', blank=True, null=True) |
||||
|
senha_inicial = models.CharField(u'Senha inicial', max_length=33, blank=True) |
||||
|
data_ativacao = models.DateField(u'Data de ativação', default=date.today) |
||||
|
data_alteracao = models.DateField(u'Data da última alteração', blank=True, null=True, auto_now=True) |
||||
|
data_desativacao = models.DateField(u'Data de desativação', blank=True, null=True) |
||||
|
motivo_desativacao = models.TextField(u'Motivo da desativação', blank=True) |
||||
|
data_ultimo_uso = models.DateField(u'Data da última utilização', blank=True, null=True, |
||||
|
help_text=u'Data em que o serviço foi utilizado pela Casa Legislativa pela última vez<br/><strong>NÃO É ATUALIZADO AUTOMATICAMENTE!</strong>') |
||||
|
erro_atualizacao = models.CharField(u"Erro na atualização", blank=True, max_length=200, |
||||
|
help_text=u"Erro ocorrido na última tentativa de atualizar a data de último acesso") |
||||
|
|
||||
|
casa_legislativa.casa_uf_filter = True |
||||
|
|
||||
|
def atualiza_data_uso(self): |
||||
|
def reset(erro=u"", comment=u""): |
||||
|
if self.data_ultimo_uso is None and not erro: |
||||
|
return |
||||
|
self.data_ultimo_uso = None |
||||
|
self.erro_atualizacao = comment + '<br/>' + erro |
||||
|
self.save() |
||||
|
return |
||||
|
|
||||
|
if self.tipo_servico.string_pesquisa == "": |
||||
|
reset() |
||||
|
return |
||||
|
|
||||
|
url = self.url |
||||
|
|
||||
|
if not url: |
||||
|
reset() |
||||
|
return |
||||
|
|
||||
|
if url[-1] != '/': |
||||
|
url += '/' |
||||
|
url += self.tipo_servico.string_pesquisa |
||||
|
|
||||
|
import urllib2 |
||||
|
from xml.dom.minidom import parseString |
||||
|
|
||||
|
try: # Captura erros de conexão |
||||
|
try: # Tentar conxão sem proxy |
||||
|
req = urllib2.urlopen(url=url, timeout=5) |
||||
|
except: # Tentar com proxy |
||||
|
proxy = urllib2.ProxyHandler() |
||||
|
opener = urllib2.build_opener(proxy) |
||||
|
req = opener.open(fullurl=url, timeout=5) |
||||
|
except Exception as e: |
||||
|
reset(erro=str(e), comment=u'Não foi possível conectar com o servidor. Pode estar fora do ar ou não ser um ' + |
||||
|
self.tipo_servico.nome) |
||||
|
return |
||||
|
|
||||
|
try: |
||||
|
rss = req.read() |
||||
|
except Exception as e: |
||||
|
reset(erro=str(e), comment=u'Não foi possível receber os dados do servidor. O acesso pode ter sido negado.') |
||||
|
return |
||||
|
|
||||
|
try: |
||||
|
xml = parseString(rss) |
||||
|
items = xml.getElementsByTagName('item') |
||||
|
first_item = items[0] |
||||
|
date_list = first_item.getElementsByTagName('dc:date') |
||||
|
date_item = date_list[0] |
||||
|
date_text = date_item.firstChild.nodeValue |
||||
|
self.data_ultimo_uso = date_text[:10] # Apenas YYYY-MM-DD |
||||
|
self.erro_atualizacao = "" |
||||
|
self.save() |
||||
|
except Exception as e: |
||||
|
reset(erro=str(e), comment=u'A resposta do servidor não é compatível com %s. Pode ser outro software que está sendo usado' % |
||||
|
self.tipo_servico.nome) |
||||
|
return |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return "%s (%s)" % (self.tipo_servico.nome, 'ativo' if self.data_desativacao is None else 'Desativado') |
||||
|
|
||||
|
def save(self, *args, **kwargs): |
||||
|
# Reter o objeto original para verificar mudanças |
||||
|
|
||||
|
if self.id is not None: |
||||
|
original = Servico.objects.get(id=self.id) |
||||
|
|
||||
|
if self.id is None: |
||||
|
# Novo serviço, email de ativação |
||||
|
subject = u'INTERLEGIS - Ativação de serviço %s' % (self.tipo_servico.nome,) |
||||
|
body = self.tipo_servico.template_email_ativa |
||||
|
elif self.data_desativacao is not None and original.data_desativacao is None: |
||||
|
# Serviço foi desativado. Email de desativação |
||||
|
subject = u'INTERLEGIS - Desativação de serviço %s' % (self.tipo_servico.nome,) |
||||
|
body = self.tipo_servico.template_email_desativa |
||||
|
elif (self.tipo_servico != original.tipo_servico or |
||||
|
self.contato_tecnico != original.contato_tecnico or |
||||
|
self.url != original.url or |
||||
|
self.nome_servidor != original.nome_servidor or |
||||
|
self.senha_inicial != original.senha_inicial): |
||||
|
# Serviço foi alterado |
||||
|
subject = u'INTERLEGIS - Alteração de serviço %s' % (self.tipo_servico.nome,) |
||||
|
body = self.tipo_servico.template_email_altera |
||||
|
else: |
||||
|
# Salvar o Servico |
||||
|
super(Servico, self).save(*args, **kwargs) |
||||
|
return # sem enviar email |
||||
|
|
||||
|
# Prepara e envia o email |
||||
|
body = body.replace('{url}', self.url) \ |
||||
|
.replace('{senha}', self.senha_inicial) \ |
||||
|
.replace('{motivo}', self.motivo_desativacao) |
||||
|
|
||||
|
# send_mail(subject, body, DEFAULT_FROM_EMAIL, \ |
||||
|
# (self.contato_tecnico.email,), fail_silently=False) |
||||
|
|
||||
|
# Salvar o Servico |
||||
|
super(Servico, self).save(*args, **kwargs) |
||||
|
|
||||
|
return |
||||
|
|
||||
|
class LogServico(models.Model): |
||||
|
servico = models.ForeignKey(Servico, verbose_name='Serviço') |
||||
|
descricao = models.CharField('Breve descrição da ação', max_length=60) |
||||
|
data = models.DateField('Data da ação', default=date.today) |
||||
|
log = models.TextField('Log da ação') |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return "%s (%s)" % (self.descricao, self.data) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'Log do serviço' |
||||
|
verbose_name_plural = 'Logs do serviço' |
||||
|
|
||||
|
class CasaAtendidaManager(models.Manager): |
||||
|
def get_query_set(self): |
||||
|
qs = super(CasaAtendidaManager, self).get_query_set() |
||||
|
qs = qs.exclude(codigo_interlegis='') |
||||
|
return qs |
||||
|
|
||||
|
class CasaAtendida(CasaLegislativa): |
||||
|
class Meta: |
||||
|
proxy = True |
||||
|
verbose_name_plural = 'Casas atendidas' |
||||
|
|
||||
|
objects = CasaAtendidaManager() |
||||
|
|
||||
|
class CasaManifesta(models.Model): |
||||
|
casa_legislativa = models.OneToOneField(CasaLegislativa) |
||||
|
data_manifestacao = models.DateTimeField(auto_now_add=True) |
||||
|
data_atualizacao = models.DateTimeField(auto_now=True) |
||||
|
informante = models.CharField(u'Nome do informante', max_length=100) |
||||
|
cargo = models.CharField(u'Cargo do informante', max_length=100) |
||||
|
|
||||
|
class ServicoManifesto(models.Model): |
||||
|
casa_manifesta = models.ForeignKey(CasaManifesta) |
||||
|
servico = models.ForeignKey(TipoServico) |
||||
|
url = models.URLField(blank=True) |
||||
|
hospedagem_interlegis = models.BooleanField(u'Hospedagem no Interlegis?') |
||||
|
|
||||
|
class Meta: |
||||
|
unique_together = ('casa_manifesta', 'servico') |
@ -0,0 +1,122 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.db import models |
||||
|
from sigi.apps.casas.models import CasaLegislativa, Funcionario |
||||
|
from datetime import date |
||||
|
from django.core.mail import send_mail |
||||
|
from sigi.settings import DEFAULT_FROM_EMAIL |
||||
|
|
||||
|
class TipoServico(models.Model): |
||||
|
email_help = '''Use:<br/> |
||||
|
{url} para incluir a URL do serviço,<br/> |
||||
|
{senha} para incluir a senha inicial do serviço''' |
||||
|
nome = models.CharField('Nome', max_length=60) |
||||
|
sigla = models.CharField('Sigla', max_length='12') |
||||
|
template_email_ativa = models.TextField('Template de email de ativação', help_text = email_help, blank=True) |
||||
|
template_email_altera = models.TextField('Template de email de alteração', help_text = email_help, blank=True) |
||||
|
template_email_desativa = models.TextField('Template de email de desativação', help_text = email_help + '<br/>{motivo} para incluir o motivo da desativação do serviço', blank=True) |
||||
|
|
||||
|
@property |
||||
|
def qtde_casas_atendidas(self): |
||||
|
u"""Quantidade de casas atendidas""" |
||||
|
return self.servico_set.filter(data_desativacao=None).count() |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'Tipo de serviço' |
||||
|
verbose_name_plural = 'Tipos de serviço' |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return self.nome; |
||||
|
|
||||
|
class Servico(models.Model): |
||||
|
casa_legislativa = models.ForeignKey(CasaLegislativa, verbose_name='Casa legislativa') |
||||
|
tipo_servico = models.ForeignKey(TipoServico, verbose_name='Tipo de serviço') |
||||
|
contato_tecnico = models.ForeignKey(Funcionario, verbose_name='Contato técnico', related_name='contato_tecnico') |
||||
|
contato_administrativo = models.ForeignKey(Funcionario, verbose_name='Contato administrativo', related_name='contato_administrativo') |
||||
|
url = models.URLField('URL do serviço', verify_exists=False, blank=True) |
||||
|
hospedagem_interlegis = models.BooleanField('Hospedagem no Interlegis?') |
||||
|
nome_servidor = models.CharField('Hospedado em', max_length=60, blank=True, help_text='Se hospedado no Interlegis, informe o nome do servidor.<br/>Senão, informe o nome do provedor de serviços.') |
||||
|
porta_servico = models.PositiveSmallIntegerField('Porta de serviço (instância)', blank=True, null=True) |
||||
|
senha_inicial = models.CharField('Senha inicial', max_length=33, blank=True) |
||||
|
data_ativacao = models.DateField('Data de ativação', default=date.today) |
||||
|
data_alteracao = models.DateField('Data da última alteração', blank=True, null=True, auto_now=True) |
||||
|
data_desativacao = models.DateField('Data de desativação', blank=True, null=True) |
||||
|
motivo_desativacao = models.TextField('Motivo da desativação', blank=True) |
||||
|
|
||||
|
casa_legislativa.casa_uf_filter = True |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return "%s (%s)" % (self.tipo_servico.nome, 'ativo' if self.data_desativacao is None else 'Desativado') |
||||
|
|
||||
|
def save(self, *args, **kwargs): |
||||
|
# Reter o objeto original para verificar mudanças |
||||
|
|
||||
|
if self.id is not None: |
||||
|
original = Servico.objects.get(id=self.id) |
||||
|
|
||||
|
if self.id is None: |
||||
|
# Novo serviço, email de ativação |
||||
|
subject = u'INTERLEGIS - Ativação de serviço %s' % (self.tipo_servico.nome,) |
||||
|
body = self.tipo_servico.template_email_ativa |
||||
|
elif self.data_desativacao is not None and original.data_desativacao is None: |
||||
|
# Serviço foi desativado. Email de desativação |
||||
|
subject = u'INTERLEGIS - Desativação de serviço %s' % (self.tipo_servico.nome,) |
||||
|
body = self.tipo_servico.template_email_desativa |
||||
|
elif (self.tipo_servico != original.tipo_servico or |
||||
|
self.contato_tecnico != original.contato_tecnico or |
||||
|
self.url != original.url or |
||||
|
self.nome_servidor != original.nome_servidor or |
||||
|
self.senha_inicial != original.senha_inicial): |
||||
|
# Serviço foi alterado |
||||
|
subject = u'INTERLEGIS - Alteração de serviço %s' % (self.tipo_servico.nome,) |
||||
|
body = self.tipo_servico.template_email_altera |
||||
|
else: |
||||
|
# Salvar o Servico |
||||
|
super(Servico, self).save(*args, **kwargs) |
||||
|
return # sem enviar email |
||||
|
|
||||
|
# Prepara e envia o email |
||||
|
body = body.replace('{url}', self.url) \ |
||||
|
.replace('{senha}', self.senha_inicial) \ |
||||
|
.replace('{motivo}', self.motivo_desativacao) |
||||
|
|
||||
|
# send_mail(subject, body, DEFAULT_FROM_EMAIL, \ |
||||
|
# (self.contato_tecnico.email,), fail_silently=False) |
||||
|
|
||||
|
# Salvar o Servico |
||||
|
super(Servico, self).save(*args, **kwargs) |
||||
|
|
||||
|
return |
||||
|
|
||||
|
class LogServico(models.Model): |
||||
|
servico = models.ForeignKey(Servico, verbose_name='Serviço') |
||||
|
descricao = models.CharField('Breve descrição da ação', max_length=60) |
||||
|
data = models.DateField('Data da ação', default=date.today) |
||||
|
log = models.TextField('Log da ação') |
||||
|
|
||||
|
def __unicode__(self): |
||||
|
return "%s (%s)" % (self.descricao, self.data) |
||||
|
|
||||
|
class Meta: |
||||
|
verbose_name = 'Log do serviço' |
||||
|
verbose_name_plural = 'Logs do serviço' |
||||
|
|
||||
|
class CasaAtendidaManager(models.Manager): |
||||
|
def get_query_set(self): |
||||
|
qs = super(CasaAtendidaManager, self).get_query_set() |
||||
|
qs = qs.exclude(codigo_interlegis='') |
||||
|
return qs |
||||
|
|
||||
|
class CasaAtendida(CasaLegislativa): |
||||
|
class Meta: |
||||
|
proxy = True |
||||
|
verbose_name_plural = 'Casas atendidas' |
||||
|
|
||||
|
objects = CasaAtendidaManager() |
||||
|
|
||||
|
@property |
||||
|
def servicos(self): |
||||
|
result = [] |
||||
|
for servico in self.servico_set.all(): |
||||
|
result.append(unicode(servico)) |
||||
|
|
||||
|
return ", ".join(result) |
@ -0,0 +1,127 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django import forms |
||||
|
from django.http import HttpResponse |
||||
|
from django.utils import simplejson |
||||
|
from django.shortcuts import render_to_response, get_object_or_404 |
||||
|
from django.db.models import Q |
||||
|
from sigi.apps.servicos.models import TipoServico, CasaAtendida, CasaManifesta, ServicoManifesto |
||||
|
from sigi.apps.contatos.models import UnidadeFederativa |
||||
|
from sigi.apps.casas.models import CasaLegislativa |
||||
|
from django.template.context import RequestContext |
||||
|
from django.utils.encoding import force_unicode |
||||
|
from django.forms.forms import BoundField |
||||
|
from django.utils.html import conditional_escape |
||||
|
from django.utils.safestring import mark_safe |
||||
|
from django.contrib.admin.helpers import AdminForm |
||||
|
|
||||
|
def municipios_atendidos(self, servico): |
||||
|
municipios = [] |
||||
|
servico = servico.upper() |
||||
|
|
||||
|
query = Q() |
||||
|
|
||||
|
if servico != 'ALL': |
||||
|
for sigla in servico.split('_'): |
||||
|
query = query | Q(tipo_servico__sigla=sigla) |
||||
|
|
||||
|
query = Q(data_desativacao=None) & query |
||||
|
|
||||
|
for casa in CasaAtendida.objects.all(): |
||||
|
if casa.servico_set.filter(query).exists(): |
||||
|
m = casa.municipio |
||||
|
municipio = {'nome': casa.nome + ', ' + m.uf.sigla, |
||||
|
'lat': str(m.latitude), |
||||
|
'lng': str(m.longitude), |
||||
|
'servicos': "<ul><li>" + "</li><li>".join([s.tipo_servico.nome for s in casa.servico_set.filter(query)]) + "</li></ul>",} |
||||
|
municipios.append(municipio) |
||||
|
|
||||
|
return HttpResponse(simplejson.dumps(municipios), mimetype="application/json") |
||||
|
|
||||
|
class CasaManifestaProtoForm(forms.Form): |
||||
|
fieldsets = None |
||||
|
informante = forms.CharField(max_length=100, required=False) |
||||
|
cargo = forms.CharField(max_length=100, required=False) |
||||
|
|
||||
|
def set_fieldsets(self, fieldsets): |
||||
|
result = [] |
||||
|
for name, lines in fieldsets: |
||||
|
field_lines = [] |
||||
|
for line in lines: |
||||
|
if isinstance(line, str): |
||||
|
line = (line,) |
||||
|
field_line = [] |
||||
|
for field_name in line: |
||||
|
field = self.fields[field_name] |
||||
|
bf = BoundField(self, field, field_name) |
||||
|
field_line.append(bf) |
||||
|
field_lines.append(field_line) |
||||
|
result.append({'name': name, 'lines': field_lines},) |
||||
|
self.fieldsets = result |
||||
|
|
||||
|
def casa_manifesta_view(request): |
||||
|
if 'casa_id' in request.GET: |
||||
|
casa_id = request.GET.get('casa_id') |
||||
|
casa = get_object_or_404(CasaLegislativa, pk=casa_id) |
||||
|
|
||||
|
# Criar um formulário dinâmico |
||||
|
|
||||
|
campos = {} |
||||
|
fieldsets = ((None, ('informante', 'cargo'),),) |
||||
|
|
||||
|
for ts in TipoServico.objects.all(): |
||||
|
campos['possui_%s' % ts.pk] = forms.BooleanField(label=u'Possui o serviço de %s' % ts.nome, required=False) |
||||
|
campos['url_%s' % ts.pk] = forms.URLField(label=u'Informe a URL', required=False) |
||||
|
campos['hospedagem_interlegis_%s' % ts.pk] = forms.BooleanField(label=u'Serviço está hospedado no Interlegis', required=False) |
||||
|
fieldsets += ((ts.nome, ('possui_%s' % ts.pk, 'url_%s' % ts.pk, 'hospedagem_interlegis_%s' % ts.pk )),) |
||||
|
|
||||
|
CasaManifestaForm = type('', (CasaManifestaProtoForm,), campos) |
||||
|
|
||||
|
if request.method == 'POST': |
||||
|
cmf = CasaManifestaForm(request.POST) |
||||
|
if cmf.is_valid(): |
||||
|
thanks = [] |
||||
|
cm, created = CasaManifesta.objects.get_or_create(casa_legislativa=casa) |
||||
|
cm.informante = cmf.cleaned_data['informante'] |
||||
|
cm.cargo = cmf.cleaned_data['cargo'] |
||||
|
cm.save() |
||||
|
thanks.append((u'Informante', cmf.cleaned_data['informante'])) |
||||
|
thanks.append((u'Cargo', cmf.cleaned_data['cargo'])) |
||||
|
for ts in TipoServico.objects.all(): |
||||
|
if cmf.cleaned_data['possui_%s' % ts.pk]: |
||||
|
sm, created = ServicoManifesto.objects.get_or_create(casa_manifesta=cm, servico=ts) |
||||
|
sm.url = cmf.cleaned_data['url_%s' % ts.pk] |
||||
|
sm.hospedagem_interlegis = cmf.cleaned_data['hospedagem_interlegis_%s' % ts.pk] |
||||
|
sm.save() |
||||
|
thanks.append((ts.nome, u'Possui o serviço acessível em %s %s' % (sm.url, u'hospedado no Interlegis' if |
||||
|
sm.hospedagem_interlegis else ''))) |
||||
|
else: |
||||
|
ServicoManifesto.objects.filter(casa_manifesta=cm, servico=ts).delete() |
||||
|
thanks.append((ts.nome, u'Não possui')) |
||||
|
extra_context = {'casa': casa, 'thanks': thanks} |
||||
|
else: |
||||
|
extra_context = {'casa': casa, 'cmf': cmf} |
||||
|
else: |
||||
|
try: |
||||
|
cm = casa.casamanifesta |
||||
|
values = { |
||||
|
'informante': cm.informante, |
||||
|
'cargo': cm.cargo, |
||||
|
} |
||||
|
for sm in cm.servicomanifesto_set.all(): |
||||
|
values['possui_%s' % sm.servico.pk] = True |
||||
|
values['url_%s' % sm.servico.pk] = sm.url |
||||
|
values['hospedagem_interlegis_%s' % sm.servico.pk] = sm.hospedagem_interlegis |
||||
|
cmf = CasaManifestaForm(values) |
||||
|
except: |
||||
|
cmf = CasaManifestaForm() |
||||
|
|
||||
|
cmf.set_fieldsets(fieldsets) |
||||
|
|
||||
|
extra_context = {'casa': casa, 'cmf': cmf} |
||||
|
elif 'uf' in request.GET: |
||||
|
uf = request.GET.get('uf') |
||||
|
extra_context = {'casa_list': CasaLegislativa.objects.filter(municipio__uf__sigla=uf)} |
||||
|
else: |
||||
|
extra_context = {'uf_list': UnidadeFederativa.objects.all()} |
||||
|
|
||||
|
return render_to_response('servicos/casa_manifesta.html', extra_context, context_instance=RequestContext(request)) |
Loading…
Reference in new issue