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, # Se determinada pergunta é da categoria pesquisada,
# então, gere o campo no formulário. # então, gere o campo no formulário.
for schema in self.instance.get_schemata(): for schema in self.instance.get_schemata(int(category)):
if not schema.categoria_id == int(category):
continue
defaults = { defaults = {
'label': schema.title, 'label': schema.title,

12
sigi/apps/diagnosticos/models.py

@ -113,6 +113,16 @@ class Diagnostico(BaseEntity):
'status': "Alterado", '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 @classmethod
def get_schemata_for_model(self): def get_schemata_for_model(self):
return Pergunta.objects.all() return Pergunta.objects.all()
@ -121,7 +131,7 @@ class Diagnostico(BaseEntity):
return str(self.casa_legislativa).decode('utf8') return str(self.casa_legislativa).decode('utf8')
def get_absolute_url(self): def get_absolute_url(self):
return "/sigi/diagnosticos/diagnostico/%i/" % (self.id, ) return "/sigi/diagnosticos/diagnostico/%i.pdf" % (self.id, )
class Categoria(models.Model): 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) diagnostico = Diagnostico.objects.get(pk=id_diagnostico)
categorias = Categoria.objects.all() 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: for categoria in categorias:
form = DiagnosticoMobileForm( schemas = []
instance=diagnostico, for schema in diagnostico.get_schemata(categoria.id):
category=categoria.id datatype = schema.datatype
) data = getattr(diagnostico, schema.name)
fields = [] if datatype == schema.TYPE_MANY:
for field in form: schema.value = [x.pk for x in data]
#field.value = field.data[field.name] elif datatype == schema.TYPE_ONE:
fields.append(field) schema.value = data.pk if data else None,
forms.append((categoria,fields)) else:
schema.value = data
schemas.append(schema)
schemas_by_categoria.append((categoria,schemas))
context = RequestContext(request, { context = RequestContext(request, {
'pagesize':'A4', 'pagesize':'A4',
'casa_legislativa': casa_legislativa,
'funcionarios': funcionarios,
'diagnostico': diagnostico, '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.loader import get_template
from django.template import Context from django.template import Context
from django.http import HttpResponse from django.http import HttpResponse
from django.conf import settings
from cgi import escape 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): def render_to_pdf(template_src, context_dict):
template = get_template(template_src) template = get_template(template_src)
context = Context(context_dict) context = Context(context_dict)
html = template.render(context) html = template.render(context)
result = StringIO.StringIO() 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: if not pdf.err:
return HttpResponse(result.getvalue(), mimetype='application/pdf') return HttpResponse(result.getvalue(), mimetype='application/pdf')
return HttpResponse('We had some errors<pre>%s</pre>' % escape(html)) 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"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My Title</title> <title>My Title</title>
<style type="text/css"> <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 { @page {
size: {{ pagesize }}; size: {{ pagesize }};
margin: 2cm; margin: 4cm 1cm 1cm 2cm;
font-family: "Helvetica, Arial, sans-serif";
font-size: 2em;
@frame header { @frame header {
-pdf-frame-content: header; -pdf-frame-content: header;
top: 0.5cm; top: 1cm;
margin-left: 9cm;
margin-right: 9cm;
height: 1cm;
} }
@frame footer { @frame footer {
-pdf-frame-content: footer; -pdf-frame-content: footer;
@ -26,26 +83,114 @@
</head> </head>
<body> <body>
<div id="header"> <div id="header">
{%block page_header%} <table>
Interlegis <tr>
{%endblock%} <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>
<div>
{% for categoria, fields in forms %} {% for categoria, schemas in schemas_by_categoria %}
<h1>Bloco {{categoria.nome}}</h1> <div class="new_page">
{% for field in fields %} <h2>Bloco {{categoria.nome}}</h2>
<h2> {% for schema in schemas %}
{% if field.help_text %} <div class="same_page">
{{ field.label }} ({{ field.help_text }}) <h3>{{ schema.title }}</h3>
{% else %} {% if schema.datatype == schema.TYPE_MANY or schema.datatype == schema.TYPE_ONE %}
{{ field.label }} <ul class="{{ schema.datatype }}">
{% endif %} {% for choice in schema.get_choices %}
</h2> {% if choice.pk in schema.value %}
<p>{{ field }}<p> <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 %} {% endfor %}
<pdf:nextpage>
{% endfor %}
</div> </div>
{% endfor %}
<div id="footer"> <div id="footer">
{%block page_foot%} {%block page_foot%}
Página <pdf:pagenumber> Página <pdf:pagenumber>

Loading…
Cancel
Save