# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
##
## Copyright (C) 2011-2012 Async Open Source
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., or visit: http://www.gnu.org/.
##
## Author(s): Stoq Team <stoq-devel@async.com.br>
##
# This is mostly lifted from
# http://code.google.com/p/pyboleto licensed under MIT
import sys
import traceback
from reportlab.graphics.barcode.common import I2of5
from reportlab.lib import colors, pagesizes, utils
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
from stoqlib.exceptions import ReportError
from stoqlib.lib.crashreport import collect_traceback
from stoqlib.lib.boleto import BoletoException, get_bank_info_by_number
from stoqlib.lib.message import warning
from stoqlib.lib.translation import stoqlib_gettext
_ = stoqlib_gettext
[docs]class BoletoPDF(object):
(FORMAT_BOLETO,
FORMAT_CARNE) = range(2)
def __init__(self, file_descr, format=FORMAT_BOLETO):
self.file_descr = file_descr
self.width = 190 * mm
self.widthCanhoto = 70 * mm
self.space = 2
self.fontSizeTitle = 6
self.fontSizeValue = 9
pagesize = pagesizes.A4
if format == self.FORMAT_CARNE:
pagesize = pagesizes.landscape(pagesize)
self.heightLine = 5.75 * mm
else:
self.heightLine = 6.5 * mm
self.deltaTitle = self.heightLine - (self.fontSizeTitle + 1)
self.deltaFont = self.fontSizeValue + 1
self.format = format
self.pdfCanvas = canvas.Canvas(self.file_descr, pagesize=pagesize)
self.pdfCanvas.setStrokeColor(colors.black)
self.boletos = []
[docs] def drawReciboSacadoCanhoto(self, boletoDados, x, y):
self.pdfCanvas.saveState()
self.pdfCanvas.translate(x * mm, y * mm)
linhaInicial = 12
# Horizontal Lines
self.pdfCanvas.setLineWidth(2)
self._horizontalLine(0, 0, self.widthCanhoto)
self.pdfCanvas.setLineWidth(1)
self._horizontalLine(0, (linhaInicial + 0) * self.heightLine,
self.widthCanhoto)
self._horizontalLine(0, (linhaInicial + 1) * self.heightLine,
self.widthCanhoto)
self.pdfCanvas.setLineWidth(2)
self._horizontalLine(0, (linhaInicial + 2) * self.heightLine,
self.widthCanhoto)
# Vertical Lines
self.pdfCanvas.setLineWidth(1)
self._verticalLine(self.widthCanhoto - (35 * mm),
(linhaInicial + 0) * self.heightLine, self.heightLine)
self._verticalLine(self.widthCanhoto - (35 * mm),
(linhaInicial + 1) * self.heightLine, self.heightLine)
self.pdfCanvas.setFont('Helvetica-Bold', 6)
self.pdfCanvas.drawRightString(self.widthCanhoto,
0 * self.heightLine + 3,
'Recibo do Sacado')
# Titles
self.pdfCanvas.setFont('Helvetica', 6)
self.deltaTitle = self.heightLine - (6 + 1)
self.pdfCanvas.drawString(
self.space,
(((linhaInicial + 0) * self.heightLine)) + self.deltaTitle,
'Nosso Número')
self.pdfCanvas.drawString(
self.widthCanhoto - (35 * mm) + self.space,
(((linhaInicial + 0) * self.heightLine)) + self.deltaTitle,
'Vencimento')
self.pdfCanvas.drawString(
self.space,
(((linhaInicial + 1) * self.heightLine)) + self.deltaTitle,
'Agência/Código do Beneficiário')
self.pdfCanvas.drawString(
self.widthCanhoto - (35 * mm) + self.space,
(((linhaInicial + 1) * self.heightLine)) + self.deltaTitle,
'Valor Documento')
# Values
self.pdfCanvas.setFont('Helvetica', 9)
heighFont = 9 + 1
valorDocumento = self._format_value(boletoDados.payment.value)
self.pdfCanvas.drawString(
self.space,
(((linhaInicial + 0) * self.heightLine)) + self.space,
boletoDados.format_nosso_numero())
self.pdfCanvas.drawString(
self.widthCanhoto - (35 * mm) + self.space,
(((linhaInicial + 0) * self.heightLine)) + self.space,
boletoDados.payment.due_date.strftime('%d/%m/%Y'))
self.pdfCanvas.drawString(
self.space,
(((linhaInicial + 1) * self.heightLine)) + self.space,
boletoDados.agencia_conta)
self.pdfCanvas.drawString(
self.widthCanhoto - (35 * mm) + self.space,
(((linhaInicial + 1) * self.heightLine)) + self.space,
valorDocumento)
demonstrativo = boletoDados.demonstrativo[0:12]
for i in range(len(demonstrativo)):
parts = utils.simpleSplit(demonstrativo[i], 'Helvetica', 9,
self.widthCanhoto)
self.pdfCanvas.drawString(
2 * self.space,
(((linhaInicial - 1) * self.heightLine)) - (i * heighFont),
parts[0])
self.pdfCanvas.restoreState()
return (self.widthCanhoto / mm,
((linhaInicial + 2) * self.heightLine) / mm)
[docs] def drawReciboSacado(self, boletoDados, x, y):
self.pdfCanvas.saveState()
self.pdfCanvas.translate(x * mm, y * mm)
linhaInicial = 16
# Horizontal Lines
self.pdfCanvas.setLineWidth(1)
# Cedente
self._horizontalLine(0,
linhaInicial * self.heightLine, self.width)
# Endereço
self._horizontalLine(0,
(linhaInicial + 1) * self.heightLine, self.width)
# Sacado
self._horizontalLine(0,
(linhaInicial - 1) * self.heightLine, self.width)
self.pdfCanvas.setLineWidth(2)
self._horizontalLine(0,
(linhaInicial + 2) * self.heightLine, self.width)
# Vertical Lines
# Vertical line 1
# Linha Sacado
self.pdfCanvas.setLineWidth(1)
self._verticalLine(
self.width - (35 * mm) - (30 * mm) - (40 * mm),
(linhaInicial - 1) * self.heightLine,
1 * self.heightLine)
# Linha Cedente
self._verticalLine(
self.width - (35 * mm) - (30 * mm) - (40 * mm),
(linhaInicial + 1) * self.heightLine,
1 * self.heightLine)
# Vertical line 2
# Cedente
self.pdfCanvas.setLineWidth(1)
self._verticalLine(
self.width - (35 * mm) - (30 * mm),
(linhaInicial + 1) * self.heightLine,
1 * self.heightLine)
# Sacado
self.pdfCanvas.setLineWidth(1)
self._verticalLine(
self.width - (35 * mm) - (30 * mm),
(linhaInicial - 1) * self.heightLine,
1 * self.heightLine)
# Vertical line 3
# Cedente/Endereço/Sacado
self.pdfCanvas.setLineWidth(1)
self._verticalLine(
self.width - (35 * mm),
(linhaInicial + -1) * self.heightLine,
3 * self.heightLine)
# Head
self.pdfCanvas.setLineWidth(2)
self._verticalLine(40 * mm,
(linhaInicial + 2) * self.heightLine, self.heightLine)
self._verticalLine(60 * mm,
(linhaInicial + 2) * self.heightLine, self.heightLine)
if boletoDados.logo_image_path:
self.pdfCanvas.drawImage(
boletoDados.logo_image_path,
0, (linhaInicial + 2) * self.heightLine + 3,
40 * mm,
self.heightLine,
preserveAspectRatio=True,
anchor='sw')
self.pdfCanvas.setFont('Helvetica-Bold', 18)
self.pdfCanvas.drawCentredString(
50 * mm,
(linhaInicial + 2) * self.heightLine + 3,
boletoDados.codigo_dv_banco)
self.pdfCanvas.setFont('Helvetica-Bold', 10)
self.pdfCanvas.drawRightString(
self.width,
(linhaInicial + 2) * self.heightLine + 3,
'Recibo do Pagador')
# Titles
self.pdfCanvas.setFont('Helvetica', 6)
self.deltaTitle = self.heightLine - (6 + 1)
self.pdfCanvas.drawRightString(
self.width,
self.heightLine,
'Autenticação Mecânica')
# Linha Beneficiário
self.pdfCanvas.drawString(
0,
(((linhaInicial + 1) * self.heightLine)) + self.deltaTitle,
'Beneficiário')
self.pdfCanvas.drawString(
self.width - (35 * mm) - (30 * mm) - (40 * mm) + self.space,
(((linhaInicial + 1) * self.heightLine)) + self.deltaTitle,
'Agência/Código Beneficiário')
self.pdfCanvas.drawString(
self.width - (35 * mm) - (30 * mm) + self.space,
(((linhaInicial + 1) * self.heightLine)) + self.deltaTitle,
'Data Documento')
self.pdfCanvas.drawString(
self.width - (35 * mm) + self.space,
(((linhaInicial + 1) * self.heightLine)) + self.deltaTitle,
'Vencimento')
# Linha Endereço
self.pdfCanvas.drawString(
0,
(((linhaInicial + 0) * self.heightLine)) + self.deltaTitle,
'Endereço Beneficiário')
self.pdfCanvas.drawString(
self.width - (35 * mm) + self.space,
(((linhaInicial + 0) * self.heightLine)) + self.deltaTitle,
'CNPJ Beneficiário')
# Linha Sacado
self.pdfCanvas.drawString(
0,
(((linhaInicial - 1) * self.heightLine)) + self.deltaTitle,
'Pagador')
self.pdfCanvas.drawString(
self.width - (35 * mm) - (30 * mm) - (40 * mm) + self.space,
(((linhaInicial - 1) * self.heightLine)) + self.deltaTitle,
'Nosso Número')
self.pdfCanvas.drawString(
self.width - (35 * mm) - (30 * mm) + self.space,
(((linhaInicial - 1) * self.heightLine)) + self.deltaTitle,
'N. do documento')
self.pdfCanvas.drawString(
self.width - (35 * mm) + self.space,
(((linhaInicial - 1) * self.heightLine)) + self.deltaTitle,
'Valor Documento')
self.pdfCanvas.drawString(
0,
(((linhaInicial - 2) * self.heightLine)) + self.deltaTitle,
'Demonstrativo')
# Values
self.pdfCanvas.setFont('Helvetica', 9)
heighFont = 9 + 1
# Valores da linha Beneficiário
self.pdfCanvas.drawString(
0 + self.space,
(((linhaInicial + 1) * self.heightLine)) + self.space,
boletoDados.branch.get_description())
self.pdfCanvas.drawString(
self.width - (35 * mm) - (30 * mm) - (40 * mm) + self.space,
(((linhaInicial + 1) * self.heightLine)) + self.space,
boletoDados.agencia_conta)
self.pdfCanvas.drawString(
self.width - (35 * mm) - (30 * mm) + self.space,
(((linhaInicial + 1) * self.heightLine)) + self.space,
boletoDados.payment.open_date.strftime('%d/%m/%Y'))
self.pdfCanvas.drawString(
self.width - (35 * mm) + self.space,
(((linhaInicial + 1) * self.heightLine)) + self.space,
boletoDados.payment.due_date.strftime('%d/%m/%Y'))
# Valores da linha Endereço
# Endereço
address = boletoDados.branch.person.get_main_address()
self.pdfCanvas.drawString(
0 + self.space,
(((linhaInicial + 0) * self.heightLine)) + self.space,
'{}, {}'.format(address.get_address_string(),
address.get_details_string()))
# CNPJ
self.pdfCanvas.drawString(
self.width - (35 * mm) + self.space,
(((linhaInicial + 0) * self.heightLine)) + self.space,
boletoDados.branch.person.company.cnpj)
# Valores da linha Sacado
valorDocumento = self._format_value(boletoDados.payment.value)
self.pdfCanvas.drawString(
0 + self.space,
(((linhaInicial - 1) * self.heightLine)) + self.space,
boletoDados.payer.name[:80])
self.pdfCanvas.drawString(
self.width - (35 * mm) - (30 * mm) - (40 * mm) + self.space,
(((linhaInicial - 1) * self.heightLine)) + self.space,
boletoDados.format_nosso_numero())
self.pdfCanvas.drawString(
self.width - (35 * mm) - (30 * mm) + self.space,
(((linhaInicial - 1) * self.heightLine)) + self.space,
str(boletoDados.payment.identifier))
self.pdfCanvas.drawString(
self.width - (35 * mm) + self.space,
(((linhaInicial - 1) * self.heightLine)) + self.space,
valorDocumento)
demonstrativo = boletoDados.demonstrativo[0:25]
for i in range(len(demonstrativo)):
self.pdfCanvas.drawString(
2 * self.space,
(((linhaInicial - 2) * self.heightLine)) - (i * heighFont),
demonstrativo[i])
self.pdfCanvas.restoreState()
return (self.width / mm,
((linhaInicial + 2) * self.heightLine) / mm)
[docs] def drawHorizontalCorteLine(self, x, y, width):
self.pdfCanvas.saveState()
self.pdfCanvas.translate(x * mm, y * mm)
self.pdfCanvas.setLineWidth(1)
self.pdfCanvas.setDash(1, 2)
self._horizontalLine(0, 0, width * mm)
self.pdfCanvas.restoreState()
[docs] def drawVerticalCorteLine(self, x, y, height):
self.pdfCanvas.saveState()
self.pdfCanvas.translate(x * mm, y * mm)
self.pdfCanvas.setLineWidth(1)
self.pdfCanvas.setDash(1, 2)
self._verticalLine(0, 0, height * mm)
self.pdfCanvas.restoreState()
[docs] def drawReciboCaixa(self, boletoDados, x, y):
self.pdfCanvas.saveState()
self.pdfCanvas.translate(x * mm, y * mm)
# De baixo para cima posicao 0,0 esta no canto inferior esquerdo
self.pdfCanvas.setFont('Helvetica', self.fontSizeTitle)
y = 1.5 * self.heightLine
self.pdfCanvas.drawRightString(
self.width,
(1.5 * self.heightLine) + self.deltaTitle - 1,
'Autenticação Mecânica / Ficha de Compensação')
# Primeira linha depois do codigo de barra
y += self.heightLine
self.pdfCanvas.setLineWidth(2)
self._horizontalLine(0, y, self.width)
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.space, 'Código de baixa')
self.pdfCanvas.drawString(0, y + self.space, 'Pagador / Avalista')
y += self.heightLine
self.pdfCanvas.drawString(0, y + self.deltaTitle, 'Pagador')
# Linha grossa dividindo o Sacado
y += self.heightLine
self.pdfCanvas.setLineWidth(2)
self._horizontalLine(0, y, self.width)
address = boletoDados.payer.get_main_address()
self.pdfCanvas.setFont('Helvetica', self.fontSizeValue)
self.pdfCanvas.drawString(15 * mm, (y - 10),
boletoDados.payer.name[:80])
self.pdfCanvas.drawString(15 * mm, (y - 10) - (1 * self.deltaFont),
address.get_address_string()[:80])
self.pdfCanvas.drawString(15 * mm, (y - 10) - (2 * self.deltaFont),
address.get_details_string()[:80])
self.pdfCanvas.setFont('Helvetica', self.fontSizeTitle)
# Linha vertical limitando todos os campos da direita
self.pdfCanvas.setLineWidth(1)
self._verticalLine(self.width - (45 * mm), y, 9 * self.heightLine)
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.deltaTitle,
'(=) Valor cobrado')
# Campos da direita
y += self.heightLine
self._horizontalLine(self.width - (45 * mm), y, 45 * mm)
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.deltaTitle,
'(+) Outros acréscimos')
y += self.heightLine
self._horizontalLine(self.width - (45 * mm), y, 45 * mm)
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.deltaTitle,
'(+) Mora/Multa')
y += self.heightLine
self._horizontalLine(self.width - (45 * mm), y, 45 * mm)
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.deltaTitle,
'(-) Outras deduções')
y += self.heightLine
self._horizontalLine(self.width - (45 * mm), y, 45 * mm)
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.deltaTitle,
'(-) Descontos/Abatimentos')
self.pdfCanvas.drawString(
0,
y + self.deltaTitle,
'Instruções')
self.pdfCanvas.setFont('Helvetica', self.fontSizeValue)
instrucoes = boletoDados.instrucoes[:7]
for i in range(len(instrucoes)):
parts = utils.simpleSplit(instrucoes[i], 'Helvetica', 9,
self.width - 45 * mm)
if not parts:
parts = [' ']
self.pdfCanvas.drawString(
2 * self.space,
y - (i * self.deltaFont),
parts[0])
self.pdfCanvas.setFont('Helvetica', self.fontSizeTitle)
# Linha horizontal com primeiro campo Uso do Banco
y += self.heightLine
self._horizontalLine(0, y, self.width)
self.pdfCanvas.drawString(0, y + self.deltaTitle, 'Uso do banco')
self._verticalLine((30) * mm, y, 2 * self.heightLine)
self.pdfCanvas.drawString(
(30 * mm) + self.space,
y + self.deltaTitle,
'Carteira')
self._verticalLine((30 + 20) * mm, y, self.heightLine)
self.pdfCanvas.drawString(
((30 + 20) * mm) + self.space,
y + self.deltaTitle,
'Espécie')
self._verticalLine(
(30 + 20 + 20) * mm,
y,
2 * self.heightLine)
self.pdfCanvas.drawString(
((30 + 40) * mm) + self.space,
y + self.deltaTitle,
'Quantidade')
self._verticalLine(
(30 + 20 + 20 + 20 + 20) * mm, y, 2 * self.heightLine)
self.pdfCanvas.drawString(
((30 + 40 + 40) * mm) + self.space, y + self.deltaTitle, 'Valor')
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.deltaTitle,
'(=) Valor documento')
self.pdfCanvas.setFont('Helvetica', self.fontSizeValue)
self.pdfCanvas.drawString(
(30 * mm) + self.space,
y + self.space,
boletoDados.carteira)
self.pdfCanvas.drawString(
((30 + 20) * mm) + self.space,
y + self.space,
boletoDados.especie)
self.pdfCanvas.drawString(
((30 + 20 + 20) * mm) + self.space,
y + self.space,
boletoDados.quantidade)
valor = self._format_value(boletoDados.valor)
self.pdfCanvas.drawString(
((30 + 20 + 20 + 20 + 20) * mm) + self.space,
y + self.space,
valor)
valorDocumento = self._format_value(boletoDados.payment.value)
self.pdfCanvas.drawRightString(
self.width - 2 * self.space,
y + self.space,
valorDocumento)
self.pdfCanvas.setFont('Helvetica', self.fontSizeTitle)
# Linha horizontal com primeiro campo Data documento
y += self.heightLine
self._horizontalLine(0, y, self.width)
self.pdfCanvas.drawString(
0,
y + self.deltaTitle,
'Data do documento')
self.pdfCanvas.drawString(
(30 * mm) + self.space,
y + self.deltaTitle,
'N. do documento')
self.pdfCanvas.drawString(
((30 + 40) * mm) + self.space,
y + self.deltaTitle,
'Espécie doc')
self._verticalLine(
(30 + 20 + 20 + 20) * mm,
y,
self.heightLine)
self.pdfCanvas.drawString(
((30 + 40 + 20) * mm) + self.space,
y + self.deltaTitle,
'Aceite')
self.pdfCanvas.drawString(
((30 + 40 + 40) * mm) + self.space,
y + self.deltaTitle,
'Data processamento')
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.deltaTitle,
'Nosso número')
self.pdfCanvas.setFont('Helvetica', self.fontSizeValue)
self.pdfCanvas.drawString(
0,
y + self.space,
boletoDados.payment.open_date.strftime('%d/%m/%Y'))
self.pdfCanvas.drawString(
(30 * mm) + self.space,
y + self.space,
str(boletoDados.payment.identifier))
self.pdfCanvas.drawString(
((30 + 40) * mm) + self.space,
y + self.space,
boletoDados.especie_documento)
self.pdfCanvas.drawString(
((30 + 40 + 20) * mm) + self.space,
y + self.space,
boletoDados.aceite)
self.pdfCanvas.drawString(
((30 + 40 + 40) * mm) + self.space,
y + self.space,
boletoDados.data_processamento.strftime('%d/%m/%Y'))
self.pdfCanvas.drawRightString(
self.width - 2 * self.space,
y + self.space,
boletoDados.format_nosso_numero())
self.pdfCanvas.setFont('Helvetica', self.fontSizeTitle)
# Linha horizontal com primeiro campo Beneficiário
y += self.heightLine
self._horizontalLine(0, y, self.width)
self.pdfCanvas.drawString(0, y + self.deltaTitle, 'Beneficiário')
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.deltaTitle,
'Agência/Código Beneficiário')
self.pdfCanvas.setFont('Helvetica', self.fontSizeValue)
self.pdfCanvas.drawString(0, y + self.space,
boletoDados.branch.get_description())
self.pdfCanvas.drawRightString(
self.width - 2 * self.space,
y + self.space,
boletoDados.agencia_conta)
self.pdfCanvas.setFont('Helvetica', self.fontSizeTitle)
# Linha horizontal com primeiro campo Local de Pagamento
y += self.heightLine
self._horizontalLine(0, y, self.width)
self.pdfCanvas.drawString(
0,
y + self.deltaTitle,
'Local de pagamento')
self.pdfCanvas.drawString(
self.width - (45 * mm) + self.space,
y + self.deltaTitle,
'Vencimento')
self.pdfCanvas.setFont('Helvetica', self.fontSizeValue)
self.pdfCanvas.drawString(
0,
y + self.space,
boletoDados.local_pagamento)
self.pdfCanvas.drawRightString(
self.width - 2 * self.space,
y + self.space,
boletoDados.payment.due_date.strftime('%d/%m/%Y'))
self.pdfCanvas.setFont('Helvetica', self.fontSizeTitle)
# Linha grossa com primeiro campo logo tipo do banco
self.pdfCanvas.setLineWidth(3)
y += self.heightLine
self._horizontalLine(0, y, self.width)
self.pdfCanvas.setLineWidth(2)
self._verticalLine(40 * mm, y, self.heightLine) # Logo Tipo
self._verticalLine(60 * mm, y, self.heightLine) # Numero do Banco
if boletoDados.logo_image_path:
self.pdfCanvas.drawImage(
boletoDados.logo_image_path,
0,
y + self.space + 1,
40 * mm,
self.heightLine,
preserveAspectRatio=True,
anchor='sw')
self.pdfCanvas.setFont('Helvetica-Bold', 18)
self.pdfCanvas.drawCentredString(
50 * mm,
y + 2 * self.space,
boletoDados.codigo_dv_banco)
self.pdfCanvas.setFont('Helvetica-Bold', 10)
self.pdfCanvas.drawRightString(
self.width,
y + 2 * self.space,
boletoDados.linha_digitavel)
# Codigo de barras
self._codigoBarraI25(boletoDados.barcode, 2 * self.space, 0)
self.pdfCanvas.restoreState()
return self.width, (y + self.heightLine) / mm
[docs] def drawBoletoCarneDuplo(self, boletoDados1, boletoDados2):
if self.format == self.FORMAT_CARNE:
y = 25
else:
y = 5
d = self.drawBoletoCarne(boletoDados1, y)
y += d[1] + 6
# self.drawHorizontalCorteLine(0, y, d[0])
y += 7
if boletoDados2:
self.drawBoletoCarne(boletoDados2, y)
[docs] def drawBoletoCarne(self, boletoDados, y):
x = 5
d = self.drawReciboSacadoCanhoto(boletoDados, x, y)
x += d[0] + 6
self.drawVerticalCorteLine(x, y, d[1])
x += 6
d = self.drawReciboCaixa(boletoDados, x, y)
x += d[0]
return x, d[1]
[docs] def drawBoleto(self, boletoDados):
x = 5
y = 40
self.drawHorizontalCorteLine(x, y, self.width / mm)
y += 5
d = self.drawReciboCaixa(boletoDados, x, y)
y += d[1] + 10
self.drawHorizontalCorteLine(x, y, self.width / mm)
y += 10
d = self.drawReciboSacado(boletoDados, x, y)
return self.width, y
[docs] def nextPage(self):
self.pdfCanvas.showPage()
[docs] def save(self):
self.pdfCanvas.save()
[docs] def add_data(self, data):
self.boletos.append(data)
[docs] def render(self):
try:
self._render_bill()
except (BoletoException, ValueError):
exc = sys.exc_info()
tb_str = ''.join(traceback.format_exception(*exc))
collect_traceback(exc, submit=True)
raise ReportError(tb_str)
#
# Private API
#
def _render_bill(self):
if self.format == self.FORMAT_BOLETO:
for b in self.boletos:
self.drawBoleto(b)
self.nextPage()
elif self.format == self.FORMAT_CARNE:
for i in range(0, len(self.boletos), 2):
args = [self.boletos[i], None]
if i + 1 < len(self.boletos):
args[1] = self.boletos[i + 1]
self.drawBoletoCarneDuplo(*args)
self.nextPage()
def _horizontalLine(self, x, y, width):
self.pdfCanvas.line(x, y, x + width, y)
def _verticalLine(self, x, y, width):
self.pdfCanvas.line(x, y, x, y + width)
def _centreText(self, x, y, text):
self.pdfCanvas.drawCentredString(self.refX + x, self.refY + y, text)
def _rightText(self, x, y, text):
self.pdfCanvas.drawRightString(self.refX + x, self.refY + y, text)
def _format_value(self, value):
if value is not None:
txt = "%.2f" % value
txt = txt.replace('.', ',')
else:
txt = ""
return txt
def _codigoBarraI25(self, num, x, y):
# http://en.wikipedia.org/wiki/Interleaved_2_of_5
altura = 13 * mm
comprimento = 103 * mm
tracoFino = 0.254320987654 * mm # Tamanho correto aproximado
bc = I2of5(num,
barWidth=tracoFino,
ratio=3,
barHeight=altura,
bearers=0,
quiet=0,
checksum=0)
# Recalcula o tamanho do tracoFino para que o cod de barras tenha o
# comprimento correto
tracoFino = (tracoFino * comprimento) / bc.width
bc.__init__(num, barWidth=tracoFino)
bc.drawOn(self.pdfCanvas, x, y)
[docs]class BillReport(object):
title = _('Bill')
def __init__(self, filename, payments):
self._payments = payments
self._filename = filename
self._bill = self._get_bill()
@classmethod
[docs] def check_printable(cls, payments):
for payment in payments:
msg = cls.validate_payment_for_printing(payment)
if msg:
warning(_("Could not print Bill Report"),
description=msg)
return False
return True
@classmethod
[docs] def validate_payment_for_printing(cls, payment):
account = payment.method.destination_account
if not account:
msg = _("Payment method missing a destination account: '%s'") % (
account.description, )
return msg
from stoqlib.domain.account import Account
if (account.account_type != Account.TYPE_BANK or
not account.bank):
msg = _("Account '%s' must be a bank account.\n"
"You need to configure the bill payment method in "
"the admin application and try again") % account.description
return msg
bank = account.bank
if bank.bank_number == 0:
msg = _("Improperly configured bank account: %r") % (bank, )
return msg
# FIXME: Verify that all bill option fields are configured properly
bank_no = bank.bank_number
bank_info = get_bank_info_by_number(bank_no)
if not bank_info:
msg = _("Missing stoq support for bank %d") % (bank_no, )
return msg
def _get_bill(self):
format = BoletoPDF.FORMAT_BOLETO
if len(self._payments) > 1:
format = BoletoPDF.FORMAT_CARNE
# This is a PrintOperationPoppler's workaround to really print
# the page in landscape, without cutting the edges
self.print_as_landscape = True
return BoletoPDF(self._filename, format)
[docs] def add_payments(self):
if self._bill.boletos:
return
for p in self._payments:
if p.method.method_name != 'bill':
continue
account = p.method.destination_account
_render_class = get_bank_info_by_number(account.bank.bank_number)
data = _render_class(p)
self._bill.add_data(data)
[docs] def save(self):
self.add_payments()
self._bill.render()
self._bill.save()
[docs]class BillTestReport(object):
def __init__(self, filename, data):
self.title = _("Bill")
self._bill = BoletoPDF(filename, BoletoPDF.FORMAT_BOLETO)
self._bill.add_data(data)
[docs] def save(self):
self._bill.render()
self._bill.save()