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