Browse Source

Merge branch 'stable/2.2' of github.com:interlegis/sigi into new_sigi

pull/102/head
Lude Ribeiro 3 years ago
parent
commit
0864539052
  1. 22
      sigi/apps/convenios/admin.py
  2. 30
      sigi/apps/convenios/migrations/0014_gescon.py
  3. 18
      sigi/apps/convenios/migrations/0015_remove_convenio_search_text.py
  4. 26
      sigi/apps/convenios/migrations/0016_auto_20210909_0732.py
  5. 420
      sigi/apps/convenios/models.py
  6. 18
      sigi/apps/convenios/templates/convenios/importar_gescon.html
  7. 1
      sigi/apps/convenios/urls.py
  8. 16
      sigi/apps/convenios/views.py
  9. 20
      sigi/shortcuts.py
  10. 1
      templates/admin/base_site.html

22
sigi/apps/convenios/admin.py

@ -6,7 +6,8 @@ from geraldo.generators import PDFGenerator
from sigi.apps.convenios.models import (Projeto, StatusConvenio, from sigi.apps.convenios.models import (Projeto, StatusConvenio,
TipoSolicitacao, Convenio, TipoSolicitacao, Convenio,
EquipamentoPrevisto, Anexo, Tramitacao) EquipamentoPrevisto, Anexo, Tramitacao,
Gescon)
from sigi.apps.convenios.reports import ConvenioReport from sigi.apps.convenios.reports import ConvenioReport
from sigi.apps.convenios.views import adicionar_convenios_carrinho from sigi.apps.convenios.views import adicionar_convenios_carrinho
from sigi.apps.utils import queryset_ascii from sigi.apps.utils import queryset_ascii
@ -57,11 +58,14 @@ class ConvenioAdmin(BaseModelAdmin):
{'fields': ('servico_gestao', 'servidor_gestao',)} {'fields': ('servico_gestao', 'servidor_gestao',)}
), ),
(_(u'Datas'), (_(u'Datas'),
{'fields': ('data_retorno_assinatura', 'data_termino_vigencia', {'fields': ('data_retorno_assinatura', 'data_termino_vigencia',
'data_pub_diario',)} 'data_pub_diario',)}
), ),
(_(u'Gescon'),
{'fields': ('atualizacao_gescon', 'observacao_gescon',)}
),
) )
readonly_fields = ('data_sigi',) readonly_fields = ('data_sigi', 'atualizacao_gescon', 'observacao_gescon',)
actions = ['adicionar_convenios'] actions = ['adicionar_convenios']
inlines = (AnexosInline,) inlines = (AnexosInline,)
list_display = ('num_convenio', 'casa_legislativa', 'get_uf', list_display = ('num_convenio', 'casa_legislativa', 'get_uf',
@ -76,8 +80,9 @@ class ConvenioAdmin(BaseModelAdmin):
ordering = ('casa_legislativa', '-data_retorno_assinatura') ordering = ('casa_legislativa', '-data_retorno_assinatura')
raw_id_fields = ('casa_legislativa',) raw_id_fields = ('casa_legislativa',)
get_queryset = queryset_ascii get_queryset = queryset_ascii
search_fields = ('id', 'search_text', 'casa_legislativa__sigla', search_fields = ('id', 'casa_legislativa__search_text',
'num_processo_sf', 'num_convenio') 'casa_legislativa__sigla', 'num_processo_sf',
'num_convenio')
def get_uf(self, obj): def get_uf(self, obj):
return obj.casa_legislativa.municipio.uf.sigla return obj.casa_legislativa.municipio.uf.sigla
@ -170,6 +175,11 @@ class EquipamentoPrevistoAdmin(BaseModelAdmin):
search_fields = ('convenio__id', 'equipamento__fabricante__nome', search_fields = ('convenio__id', 'equipamento__fabricante__nome',
'equipamento__modelo__modelo', 'equipamento__modelo__tipo__tipo') 'equipamento__modelo__modelo', 'equipamento__modelo__tipo__tipo')
@admin.register(Gescon)
class GesconAdmin(admin.ModelAdmin):
list_display = ('url_gescon', 'email', 'ultima_importacao')
readonly_fields = ('ultima_importacao',)
admin.site.register(Projeto) admin.site.register(Projeto)
admin.site.register(StatusConvenio) admin.site.register(StatusConvenio)
admin.site.register(TipoSolicitacao) admin.site.register(TipoSolicitacao)

30
sigi/apps/convenios/migrations/0014_gescon.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('convenios', '0013_remove_convenio_duracao'),
]
operations = [
migrations.CreateModel(
name='Gescon',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('url_gescon', models.URLField(default='https://adm.senado.gov.br/gestao-contratos/api/contratos/busca?especie={s}', help_text='Informe o ponto de consulta do webservice do Gescon, inclusive com a querystring. No ponto onde deve ser inserida a sigla da subespecie do contrato, use a marca\xe7\xe3o {s}.<br/><strong>Por exemplo:</strong> https://adm.senado.gov.br/gestao-contratos/api/contratos/busca?especie=<strong>{s}</strong>', verbose_name='Webservice Gescon')),
('subespecies', models.TextField(default='AC=ACT\nPI=PI\nCN=PML\nTA=PML', help_text='Informe as siglas das subesp\xe9cies de contratos que devem ser pesquisados no Gescon com a sigla correspondente do projeto no SIGI. Coloque um par de siglas por linha, no formato SIGLA_GESTON=SIGLA_SIGI. As siglas n\xe3o encontradas ser\xe3o ignoradas.', verbose_name='Subesp\xe9cies')),
('palavras', models.TextField(default='ILB\nINTERLEGIS', help_text='Palavras que devem aparecer no campo OBJETO dos dados do Gescon para identificar se o contrato pertence ao ILB. <ul><li>Informe uma palavra por linha.</li><li>Ocorrendo qualquer uma das palavras, o contrato ser\xe1 importado.</li></ul>', verbose_name='Palavras de filtro')),
('email', models.EmailField(help_text='Caixa de e-mail para onde o relat\xf3rio di\xe1rio de importa\xe7\xe3o ser\xe1 enviado.', max_length=75, verbose_name='E-mail')),
('ultima_importacao', models.TextField(verbose_name='Resultado da \xfaltima importa\xe7\xe3o', blank=True)),
],
options={
'verbose_name': 'Configura\xe7\xe3o do Gescon',
'verbose_name_plural': 'Configura\xe7\xf5es do Gescon',
},
bases=(models.Model,),
),
]

18
sigi/apps/convenios/migrations/0015_remove_convenio_search_text.py

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('convenios', '0014_gescon'),
]
operations = [
migrations.RemoveField(
model_name='convenio',
name='search_text',
),
]

26
sigi/apps/convenios/migrations/0016_auto_20210909_0732.py

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('convenios', '0015_remove_convenio_search_text'),
]
operations = [
migrations.AddField(
model_name='convenio',
name='atualizacao_gescon',
field=models.DateTimeField(null=True, verbose_name='Data de atualiza\xe7\xe3o pelo Gescon', blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='convenio',
name='observacao_gescon',
field=models.TextField(verbose_name='Observa\xe7\xf5es da atualiza\xe7\xe3o do Gescon', blank=True),
preserve_default=True,
),
]

420
sigi/apps/convenios/models.py

@ -1,9 +1,14 @@
#-*- coding: utf-8 -*- #-*- coding: utf-8 -*-
import re import re
import requests
from datetime import datetime, date from datetime import datetime, date
from django.db import models from django.db import models
from django.db.models import Q
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from sigi.apps.utils import SearchField from sigi.apps.utils import SearchField, to_ascii
from sigi.apps.casas.models import Orgao
from sigi.apps.servidores.models import Servidor, Servico from sigi.apps.servidores.models import Servidor, Servico
class Projeto(models.Model): class Projeto(models.Model):
@ -49,7 +54,6 @@ class Convenio(models.Model):
verbose_name=_(u'órgão conveniado') verbose_name=_(u'órgão conveniado')
) )
# campo de busca em caixa baixa e sem acentos # campo de busca em caixa baixa e sem acentos
search_text = SearchField(field_names=['casa_legislativa'])
projeto = models.ForeignKey( projeto = models.ForeignKey(
Projeto, Projeto,
on_delete=models.PROTECT, on_delete=models.PROTECT,
@ -177,6 +181,15 @@ class Convenio(models.Model):
) )
conveniada = models.BooleanField(default=False) conveniada = models.BooleanField(default=False)
equipada = models.BooleanField(default=False) equipada = models.BooleanField(default=False)
atualizacao_gescon = models.DateTimeField(
_(u"Data de atualização pelo Gescon"),
blank=True,
null=True
)
observacao_gescon = models.TextField(
_(u"Observações da atualização do Gescon"),
blank=True
)
def get_status(self): def get_status(self):
if self.status and self.status.cancela: if self.status and self.status.cancela:
@ -360,3 +373,406 @@ class Tramitacao(models.Model):
if self.observacao: if self.observacao:
result = result + u" (%s)" % (self.observacao) result = result + u" (%s)" % (self.observacao)
return unicode(result) # XXX is this unicode(...) really necessary??? return unicode(result) # XXX is this unicode(...) really necessary???
class Gescon(models.Model):
url_gescon = models.URLField(
_(u"Webservice Gescon"),
default=(u"https://adm.senado.gov.br/gestao-contratos/api/contratos"
u"/busca?especie={s}"),
help_text=_(u"Informe o ponto de consulta do webservice do Gescon, "
u"inclusive com a querystring. No ponto onde deve ser "
u"inserida a sigla da subespecie do contrato, use a "
u"marcação {s}.<br/><strong>Por exemplo:</strong> "
u"https://adm.senado.gov.br/gestao-contratos/api/contratos"
u"/busca?especie=<strong>{s}</strong>")
)
subespecies = models.TextField(
_(u"Subespécies"),
default=u"AC=ACT\nPI=PI\nCN=PML\nTA=PML",
help_text=_(u"Informe as siglas das subespécies de contratos que "
u"devem ser pesquisados no Gescon com a sigla "
u"correspondente do projeto no SIGI. Coloque um par de "
u"siglas por linha, no formato SIGLA_GESTON=SIGLA_SIGI. "
u"As siglas não encontradas serão ignoradas.")
)
palavras = models.TextField(
_(u"Palavras de filtro"),
default=u"ILB\nINTERLEGIS",
help_text=_(u"Palavras que devem aparecer no campo OBJETO dos dados do "
u"Gescon para identificar se o contrato pertence ao ILB. "
u"<ul><li>Informe uma palavra por linha.</li>"
u"<li>Ocorrendo qualquer uma das palavras, o contrato será "
u"importado.</li></ul>")
)
email = models.EmailField(
_(u"E-mail"),
help_text=_(u"Caixa de e-mail para onde o relatório diário de "
u"importação será enviado.")
)
ultima_importacao = models.TextField(
_(u"Resultado da última importação"),
blank=True
)
class Meta:
verbose_name = _(u"Configuração do Gescon")
verbose_name_plural = _(u"Configurações do Gescon")
def __unicode__(self):
return self.url_gescon
def save(self, *args, **kwargs):
self.pk = 1 # Highlander (singleton pattern)
return super(Gescon, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
pass # Highlander is immortal
def add_message(self, msg, save=False):
self.ultima_importacao += msg + "\n"
if save:
self.save()
self.email_report()
def email_report(self):
if self.email:
send_mail(
subject=_(u"Relatório de importação GESCON"),
message=self.ultima_importacao,
recipient_list=self.email,
fail_silently=True
)
else:
self.ultima_importacao += _(
u"\n\n*Não foi definida uma caixa de e-mail nas configurações "
u"do Gescon*"
)
self.save()
def importa_contratos(self):
self.ultima_importacao = ""
self.add_message(
_(u"Importação iniciada em {:%d/%m/%Y %H:%M:%S}\n"
u"==========================================\n").format(
datetime.now()
)
)
if self.palavras == "":
self.add_message(_(u"Nenhuma palavra de pesquisa definida - "
u"processo abortado."), True)
return
if self.subespecies == "":
self.add_message(_(u"Nenhuma subespécie definida - processo "
u"abortado."), True)
return
if "{s}" not in self.url_gescon:
self.add_message(
_(
u"Falta a marcação {s} na URL para indicar o local onde "
u"inserir a sigla da subespécia na consulta ao webservice "
u"- processo abortado."
),
True
)
return
palavras = self.palavras.split()
subespecies = {tuple(s.split("=")) for s in self.subespecies.split()}
for sigla_gescon, sigla_sigi in subespecies:
self.add_message(_(u"\nImportando subespécie {s}".format(
s=sigla_gescon)))
url = self.url_gescon.format(s=sigla_gescon)
projeto = Projeto.objects.get(sigla=sigla_sigi)
try:
response = requests.get(url)
except Exception as e:
self.add_message(
_(u"\tErro ao acessar {url}: {errmsg}").format(
url=url,
errmsg=str(e)
)
)
continue
if not response.ok:
self.add_message(
_(u"\tErro ao acessar {url}: {reason}").format(
url=url,
reason=response.reason
)
)
continue
if not 'application/json' in response.headers.get('Content-Type'):
self.add_message(_(u"\tResultado da consulta à {url} não "
u"retornou dados em formato json").format(
url=url
)
)
continue
contratos = response.json()
# Pegar só os contratos que possuem alguma das palavras-chave
nossos = [c for c in contratos
if any(palavra in c['objeto'] for palavra in palavras)]
self.add_message(
_(u"\t{count} contratos encontrados no Gescon").format(
count=len(nossos)
)
)
novos = 0
erros = 0
alertas = 0
atualizados = 0
for contrato in nossos:
numero = contrato['numero'].zfill(8)
numero = "{}/{}".format(numero[:4], numero[4:])
sigad = contrato['processo'].zfill(17)
sigad = "{}.{}/{}-{}".format(sigad[:5], sigad[5:11],
sigad[11:15], sigad[15:])
if contrato['cnpjCpfFornecedor']:
cnpj = contrato['cnpjCpfFornecedor'].zfill(14)
cnpj = "{}.{}.{}/{}-{}".format(cnpj[:2], cnpj[2:5],
cnpj[5:8], cnpj[8:12],
cnpj[12:])
else:
cnpj = None
if contrato['nomeFornecedor']:
nome = contrato['nomeFornecedor']
nome = nome.replace(u'VEREADORES DE', '')
nome = nome.split('-')[0]
nome = nome.split('/')[0]
nome = nome.strip()
nome = nome.replace(" ", " ")
nome = to_ascii(nome)
else:
nome = None
if (cnpj is None) and (nome is None):
self.add_message(
_(u"\tO contrato {numero} no Gescon não informa o CNPJ "
u"nem o nome do órgão.").format(numero=numero)
)
erros += 1
continue
orgao = None
if cnpj is not None:
try:
orgao = Orgao.objects.get(cnpj=cnpj)
except (
Orgao.DoesNotExist,
Orgao.MultipleObjectsReturned) as e:
orgao = None
pass
if (orgao is None) and (nome is not None):
try:
orgao = Orgao.objects.get(search_text__iexact=nome)
except (
Orgao.DoesNotExist,
Orgao.MultipleObjectsReturned) as e:
orgao = None
pass
if orgao is None:
self.add_message(
_(u"\tÓrgão não encontrado no SIGI ou mais de um órgão"
u"encontrado com o mesmo CNPJ ou nome. Favor "
u"regularizar o cadastro: CNPJ: {cnpj}, "
u"Nome: {nome}".format(
cnpj=contrato['cnpjCpfFornecedor'],
nome=contrato['nomeFornecedor']
)
)
)
erros += 1
continue
# O mais seguro é o NUP sigad
convenios = Convenio.objects.filter(num_processo_sf=sigad)
chk = convenios.count()
if chk == 0:
# NUP não encontrado, talvez exista apenas com o número
# do GESCON
convenios = Convenio.objects.filter(
Q(num_convenio=numero) |
Q(num_processo_sf=numero)
)
chk = convenios.count()
if chk > 1:
# Pode ser que existam vários contratos de subespécies
# diferentes com o mesmo número Gescon. Neste caso, o
# ideal é filtrar pelo tipo de projeto. Existindo, é
# ele mesmo. Se não existir, então segue com os
# múltiplos para registrar o problema mais adiante
if convenios.filter(projeto=projeto).count() == 1:
convenios = convenios.filter(projeto=projeto)
chk = 1
if chk == 0:
convenio = Convenio(
casa_legislativa=orgao,
projeto=projeto,
num_processo_sf=sigad,
num_convenio=numero,
data_sigi=date.today(),
data_sigad=contrato['assinatura'],
observacao=contrato['objeto'],
data_retorno_assinatura=contrato['inicioVigencia'],
data_termino_vigencia=contrato['terminoVigencia'],
data_pub_diario=contrato['publicacao'],
atualizacao_gescon=datetime.now(),
observacao_gescon=_(u"Importado integralmente do"
u"Gescon")
)
convenio.save()
novos += 1
continue
elif chk == 1:
convenio = convenios.get()
convenio.atualizacao_gescon = datetime.now()
convenio.observacao_gescon = ''
if convenio.casa_legislativa != orgao:
self.add_message(
_(u"\tO órgao no convênio {url} diverge do que "
u"consta no Gescon ({cnpj}, {nome})").format(
url=reverse('admin:%s_%s_change' % (
convenio._meta.app_label,
convenio._meta.model_name),
args=[convenio.id]),
cnpj=cnpj,
nome=contrato['nomeFornecedor']
)
)
convenio.observacao_gescon = _(
u'ERRO: Órgão diverge do Gescon. Não atualizado!'
)
convenio.save()
erros += 1
continue
if convenio.num_processo_sf != sigad:
self.add_message(
_(u"\tO contrato Gescon nº {numero} corresponde"
u" ao convênio SIGI {url}, mas o NUP sigad "
u"diverge (Gescon: {sigad_gescon}, "
u"SIGI: {sigad_sigi}). CORRIGIDO!").format(
numero=numero,
url=reverse('admin:%s_%s_change' % (
convenio._meta.app_label,
convenio._meta.model_name),
args=[convenio.id]),
sigad_gescon=sigad,
sigad_sigi=convenio.num_processo_sf
)
)
convenio.num_processo_sf = sigad
convenio.observacao_gescon += _(
u"Número do SIGAD atualizado.\n"
)
alertas += 1
if convenio.num_convenio != numero:
self.add_message(
_(u"\tO contrato Gescon ID {id} corresponde ao "
u"convênio SIGI {url}, mas o número do convênio"
u" diverge (Gescon: {numero_gescon}, SIGI: "
u"{numero_sigi}). CORRIGIDO!").format(
id=contrato['id'],
url=reverse('admin:%s_%s_change' % (
convenio._meta.app_label,
convenio._meta.model_name),
args=[convenio.id]
),
numero_gescon=numero,
numero_sigi=convenio.num_convenio
)
)
convenio.num_convenio = numero
convenio.observacao_gescon += _(
u"Número do convênio atualizado.\n"
)
alertas += 1
if contrato['objeto'] not in convenio.observacao:
convenio.observacao += "\n" + contrato['objeto']
convenio.observacao_gescon += _(
u"Observação atualizada.\n"
)
convenio.data_sigad = contrato['assinatura']
convenio.data_retorno_assinatura = contrato[
'inicioVigencia'
]
convenio.data_termino_vigencia = contrato[
'terminoVigencia'
]
convenio.data_pub_diario = contrato['publicacao']
try:
convenio.save()
except Exception as e:
self.add_message(
_(u"Ocorreu um erro ao salvar o convênio {url} no "
u"SIGI. Alguma informação do Gescon pode ter "
u"quebrado o sistema. Informe ao suporte. Erro:"
u"{errmsg}").format(
url=reverse('admin:%s_%s_change' % (
convenio._meta.app_label,
convenio._meta.model_name),
args=[convenio.id]
),
errmsg=str(e)
)
)
erros += 1
continue
atualizados += 1
else:
self.add_message(_(u"\tExistem {count} convênios no SIGI "
u"que correspondem ao mesmo contrato no "
u"Gescon (contrato {numero}, sigad "
u"{sigad})").format(
count=chk,
numero=numero,
sigad=sigad
)
)
erros += 1
continue
self.add_message(
_(u"\t{novos} novos convenios adicionados ao SIGI, "
u"{atualizados} atualizados, sendo {alertas} com alertas, e "
u"{erros} reportados com erro.").format(
novos=novos,
atualizados=atualizados,
alertas=alertas,
erros=erros
)
)
self.save()
@classmethod
def load(cls):
obj, created = cls.objects.get_or_create(pk=1)
return obj

18
sigi/apps/convenios/templates/convenios/importar_gescon.html

@ -0,0 +1,18 @@
{% extends 'admin/base_site.html' %}
{% load i18n %}
{% block content_title %}<h1>{% trans 'Importar dados do Gescon' %}</h1>{% endblock %}
{% block object-tools-items %}
<li class="nav-item"><a class="nav-link active" href="{% url 'importar-gescon' %}?action=importar">Importar</a></li>
<li class="nav-item"><a class="nav-link" href="{% url 'admin:convenios_gescon_change' gescon.id %}">Configurações</a></li>
{% endblock %}
{% block content %}
{% if gescon.ultima_importacao %}
<pre><code>{{ gescon.ultima_importacao }}</code></pre>
{% else %}
{% blocktrans %}
<p class="alert alert-danger"><strong>Nenhuma importação anterior foi realizada!</strong></p>
<p class="">Configure a conexão com o Gescon para realizar a primeira importação.</p>
{% endblocktrans %}
{% endif %}
{% endblock %}

1
sigi/apps/convenios/urls.py

@ -11,4 +11,5 @@ urlpatterns = patterns(
url(r'^convenio/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho', name='deleta-itens-carrinho'), # tagerror url(r'^convenio/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho', name='deleta-itens-carrinho'), # tagerror
url(r'^convenio/csv/$', 'export_csv', name='convenios-csv'), url(r'^convenio/csv/$', 'export_csv', name='convenios-csv'),
url(r'^reportsRegiao/(?P<regiao>\w+)/$', 'report_regiao', name='convenios-report_regiao_pdf'), url(r'^reportsRegiao/(?P<regiao>\w+)/$', 'report_regiao', name='convenios-report_regiao_pdf'),
url(r'^importar/$', 'importar_gescon', name='importar-gescon'),
) )

16
sigi/apps/convenios/views.py

@ -2,6 +2,7 @@
import csv import csv
import datetime import datetime
from django.http.response import HttpResponseForbidden
import ho.pisa as pisa import ho.pisa as pisa
from django.conf import settings from django.conf import settings
from django.core.paginator import Paginator, InvalidPage, EmptyPage from django.core.paginator import Paginator, InvalidPage, EmptyPage
@ -13,7 +14,7 @@ from geraldo.generators import PDFGenerator
from sigi.apps.casas.models import Orgao from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import UnidadeFederativa from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Convenio, Projeto from sigi.apps.convenios.models import Convenio, Gescon, Projeto
from sigi.apps.convenios.reports import (ConvenioReport, from sigi.apps.convenios.reports import (ConvenioReport,
ConvenioReportSemAceite, ConvenioReportSemAceite,
ConvenioPorCMReport, ConvenioPorCMReport,
@ -372,3 +373,16 @@ def export_csv(request):
csv_writer.writerow(lista) csv_writer.writerow(lista)
return response return response
@login_required
def importar_gescon(request):
if not request.user.is_superuser:
return HttpResponseForbidden()
action = request.GET.get('action', "")
gescon = Gescon.load()
if action == 'importar':
gescon.importa_contratos()
return render(request, "convenios/importar_gescon.html", {'gescon': gescon})

20
sigi/shortcuts.py

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from cgi import escape from cgi import escape
from datetime import datetime
import os import os
from django.conf import settings from django.conf import settings
@ -28,12 +29,15 @@ def render_to_pdf(template_src, context_dict):
filename = template_src.replace('.html', '').replace('_pdf', '.pdf') filename = template_src.replace('.html', '').replace('_pdf', '.pdf')
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()
response = HttpResponse(content_type='application/pdf')
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode('utf-8')), result, link_callback=fetch_resources) response['Content-Disposition'] = 'attachment; filename=' + filename
if not pdf.err:
response = HttpResponse(result.getvalue(), content_type='application/pdf') pdf = pisa.CreatePDF(html, dest=response,
response['Content-Disposition'] = 'attachment; filename=' + filename link_callback=fetch_resources)
return response
return HttpResponse(_(u'We had some errors<pre>%s</pre>') % escape(html)) if pdf.err:
return HttpResponse(_(u'We had some errors<pre>%s</pre>') % escape(html))
return response

1
templates/admin/base_site.html

@ -41,6 +41,7 @@
<li><a href="/sites/site/">{% trans 'Sites' %}</a></li> <li><a href="/sites/site/">{% trans 'Sites' %}</a></li>
<li><a href="/diagnosticos/">{% trans 'Diagnósticos' %}</a></li> <li><a href="/diagnosticos/">{% trans 'Diagnósticos' %}</a></li>
<li><a href="{% url 'importar-casas' %}">{% trans 'Importar dados de Casas' %}</a></li> <li><a href="{% url 'importar-casas' %}">{% trans 'Importar dados de Casas' %}</a></li>
<li><a href="{% url 'importar-gescon' %}">{% trans 'Importar convênios do Gescon' %}</a></li>
</ul> </ul>
</li> </li>
{% endif %} {% endif %}

Loading…
Cancel
Save