Browse Source

adicionando exportacao para pdf dos diagnostico

stable/1.0
Felipe Vieira 13 years ago
parent
commit
0b4d2ccdb0
  1. BIN
      media/images/logo-interlegis-grande.jpg
  2. BIN
      media/images/logo-interlegis-grande.png
  3. BIN
      media/images/logo-senado.jpg
  4. 5
      sigi/apps/diagnosticos/forms.py
  5. 12
      sigi/apps/diagnosticos/models.py
  6. 0
      sigi/apps/diagnosticos/templatetags/__init__.py
  7. 401
      sigi/apps/diagnosticos/templatetags/smart_if.py
  8. 34
      sigi/apps/diagnosticos/views.py
  9. 9
      sigi/shortcuts.py
  10. 189
      sigi/templates/diagnosticos/diagnostico_pdf.html

BIN
media/images/logo-interlegis-grande.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
media/images/logo-interlegis-grande.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
media/images/logo-senado.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

5
sigi/apps/diagnosticos/forms.py

@ -83,10 +83,7 @@ class DiagnosticoMobileForm(BaseDynamicEntityForm):
# Se determinada pergunta é da categoria pesquisada,
# então, gere o campo no formulário.
for schema in self.instance.get_schemata():
if not schema.categoria_id == int(category):
continue
for schema in self.instance.get_schemata(int(category)):
defaults = {
'label': schema.title,

12
sigi/apps/diagnosticos/models.py

@ -113,6 +113,16 @@ class Diagnostico(BaseEntity):
'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]
return schemas
@classmethod
def get_schemata_for_model(self):
return Pergunta.objects.all()
@ -121,7 +131,7 @@ class Diagnostico(BaseEntity):
return str(self.casa_legislativa).decode('utf8')
def get_absolute_url(self):
return "/sigi/diagnosticos/diagnostico/%i/" % (self.id, )
return "/sigi/diagnosticos/diagnostico/%i.pdf" % (self.id, )
class Categoria(models.Model):

0
sigi/apps/diagnosticos/templatetags/__init__.py

401
sigi/apps/diagnosticos/templatetags/smart_if.py

@ -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()

34
sigi/apps/diagnosticos/views.py

@ -193,23 +193,33 @@ def diagnostico_pdf(request, id_diagnostico):
diagnostico = Diagnostico.objects.get(pk=id_diagnostico)
categorias = Categoria.objects.all()
forms = []
casa_legislativa = diagnostico.casa_legislativa
funcionarios = [casa_legislativa.funcionario_set.get_or_create(setor=n)[0]
for n, l in Funcionario.SETOR_CHOICES]
schemas_by_categoria = []
for categoria in categorias:
form = DiagnosticoMobileForm(
instance=diagnostico,
category=categoria.id
)
fields = []
for field in form:
#field.value = field.data[field.name]
fields.append(field)
forms.append((categoria,fields))
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,
'forms': forms,
'schemas_by_categoria': schemas_by_categoria,
})
return render_to_response('diagnosticos/diagnostico_pdf.html', context)
return render_to_pdf('diagnosticos/diagnostico_pdf.html', context)

9
sigi/shortcuts.py

@ -3,16 +3,23 @@ import ho.pisa as pisa
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
from django.conf import settings
from cgi import escape
import os
def fetch_resources(uri, rel):
path = os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ""))
return path
def render_to_pdf(template_src, context_dict):
template = get_template(template_src)
context = Context(context_dict)
html = template.render(context)
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode('utf-8')), result)
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode('utf-8')), result, link_callback=fetch_resources)
if not pdf.err:
return HttpResponse(result.getvalue(), mimetype='application/pdf')
return HttpResponse('We had some errors<pre>%s</pre>' % escape(html))

189
sigi/templates/diagnosticos/diagnostico_pdf.html

@ -1,18 +1,75 @@
{% load smart_if %}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My Title</title>
<style type="text/css">
div#capa h3 {
text-align: center;
margin-top: 5px;
margin-bottom: 0px;
}
div#capa p {
text-align: center;
}
td.logo {
text-align: center;
}
td.header_text p {
margin: 0px;
font-size: 1.4em;
}
td.header_text {
width: 550px;
}
ul {
list-style-type: none;
padding-left: 15px;
}
li {
padding-left: 5px;
color: #999;
}
li.selected {
list-style-type: disc;
color: #000;
}
p.strong {
margin-left: 25px;
line-height: 1em;
}
h1 {
font-size: 2em;
text-align: center;
}
h2 {
font-size: 1.7em;
}
h3 {
margin-top: 10px;
margin-bottom: 0px;
}
body {
font-family: "Helvetica, Arial, sans-serif";
font-size: 1.3em;
line-height: 1em;
}
div.new_page {
page-break-before: always;
}
div.same_page_ {
-pdf-keep-with-next: true;
}
@page {
size: {{ pagesize }};
margin: 2cm;
margin: 4cm 1cm 1cm 2cm;
font-family: "Helvetica, Arial, sans-serif";
font-size: 2em;
@frame header {
-pdf-frame-content: header;
top: 0.5cm;
margin-left: 9cm;
margin-right: 9cm;
height: 1cm;
top: 1cm;
}
@frame footer {
-pdf-frame-content: footer;
@ -26,26 +83,114 @@
</head>
<body>
<div id="header">
{%block page_header%}
Interlegis
{%endblock%}
<table>
<tr>
<td class="logo"><img src="{{MEDIA_URL}}images/logo-senado.jpg"/></td>
<td class="header_text">
<p><strong>SENADO FEDERAL</strong></p>
<p><strong>SECRETARIA ESPECIAL DO INTERLEGIS – SINTER</strong></p>
<p>SUBSECRETARIA DE PLANEJAMENTO E FOMENTO – SSPLF</p>
</td>
<td class="logo"><img src="{{MEDIA_URL}}images/logo-interlegis.jpg"/></td>
</tr>
</table>
</div>
<div id="capa">
<center>
<img src="{{MEDIA_URL}}images/logo-interlegis-grande.jpg"/>
</center>
<h1>
PROJETO DE MODERNIZAÇÃO DO LEGISLATIVO
</br>
</br>
QUESTIONÁRIO DE DIAGNÓSTICO
</h1>
<h3>Data do Questionário:</h3>
<p>De {{diagnostico.data_visita_inicio}} à {{diagnostico.data_visita_fim}}</p>
<h3>Nome do Responsável pelas Informações:</h3>
<p>{{diagnostico.responsavel}}</p>
<h3>Cargo do Responsável pelas Informações:</h3>
<p>{{diagnostico.responsavel.cargo|default_if_none:""}}&nbsp;</p>
<h3>E-mail do Responsável pelas Informações:</h3>
<p>{{diagnostico.responsavel.email|default_if_none:""}}&nbsp;</p>
{% for telefone in diagnostico.responsavel.telefones.all %}
<h3>Telefone {{telefone.get_tipo_display}} do Responsável pelas Informações:</h3>
<p>{{telefone}}</p>
{% endfor %}
</div>
<div class="new_page">
<h2>Bloco 01. Identificação da {{casa_legislativa.tipo}}</h2>
<h3>01. Municipio - Estado:</h3>
<p class="strong">{{casa_legislativa.municipio|default_if_none:""}}&nbsp;</p>
<h3>02. Data de criação do Município:</h3>
<p class="strong">{{casa_legislativa.municipio.data_criacao|default_if_none:""}}&nbsp;</p>
<h3>03. Nome da {{casa_legislativa.tipo}}</h3>
<p class="strong">{{casa_legislativa.municipio.nome|default_if_none:""}}&nbsp;</p>
<h3>04. Data de instalação da {{casa_legislativa.tipo}}</h3>
<p class="strong">{{casa_legislativa.data_instalacao|default_if_none:""}}&nbsp;</p>
<h3>05. Endereço:</h3>
<p class="strong">{{casa_legislativa.logradouro|default_if_none:""}} - {{casa_legislativa.cep|default_if_none:""}}</p>
<h3>06. CNPJ:</h3>
<p class="strong">{{casa_legislativa.cnpj|default_if_none:""}}&nbsp;</p>
<h3>07. E-mail:</h3>
<p class="strong">{{casa_legislativa.email|default_if_none:""}}&nbsp;</p>
<h3>08. Página web:</h3>
<p class="strong">{{casa_legislativa.pagina_web|default_if_none:""}}&nbsp;</p>
</div>
<div class="new_page">
<h2>Bloco 02. Identificação de Competências na Câmara Municipal</h2>
{% for funcionario in funcionarios %}
<div class="same_page">
<h3>{{funcionario.get_setor_display}}</h3>
<p class="strong">Nome completo: {{funcionario.nome|default_if_none:""}}</p>
<p class="strong">E-mail: {{funcionario.email|default_if_none:""}}</p>
<p class="strong">Tempo de serviço: {{funcionario.tempo_de_servico|default_if_none:""}}</p>
{% for telefone in funcionario.telefones.all %}
<p class="strong">Telefone {{telefone.get_tipo_display}}: {{telefone}}</p>
{% endfor %}
</div>
{% endfor %}
</div>
<div>
{% for categoria, fields in forms %}
<h1>Bloco {{categoria.nome}}</h1>
{% for field in fields %}
<h2>
{% if field.help_text %}
{{ field.label }} ({{ field.help_text }})
{% else %}
{{ field.label }}
{% endif %}
</h2>
<p>{{ field }}<p>
{% for categoria, schemas in schemas_by_categoria %}
<div class="new_page">
<h2>Bloco {{categoria.nome}}</h2>
{% for schema in schemas %}
<div class="same_page">
<h3>{{ schema.title }}</h3>
{% if schema.datatype == schema.TYPE_MANY or schema.datatype == schema.TYPE_ONE %}
<ul class="{{ schema.datatype }}">
{% for choice in schema.get_choices %}
{% if choice.pk in schema.value %}
<li class="selected"> {{ choice.title }} </li>
{% else %}
<li> {{ choice.title }} </li>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p class="strong">{{ schema.value|default_if_none:""}}&nbsp;</p>
{% endif %}
</div>
{% endfor %}
<pdf:nextpage>
{% endfor %}
</div>
{% endfor %}
<div id="footer">
{%block page_foot%}
Página <pdf:pagenumber>

Loading…
Cancel
Save