forked from elmau/empresa-libre
PDF a partir de JSON
This commit is contained in:
parent
7864e236db
commit
cf0c4b8622
|
@ -340,6 +340,7 @@ class SendMail(object):
|
||||||
|
|
||||||
class NumberedCanvas(canvas.Canvas):
|
class NumberedCanvas(canvas.Canvas):
|
||||||
X = 20.59 * cm
|
X = 20.59 * cm
|
||||||
|
XC = 21.6 * cm / 2 + 1.5 * cm
|
||||||
Y = 1.5 * cm
|
Y = 1.5 * cm
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -363,10 +364,14 @@ class NumberedCanvas(canvas.Canvas):
|
||||||
|
|
||||||
def draw_page_number(self, page_count):
|
def draw_page_number(self, page_count):
|
||||||
self.setFont('Helvetica', 8)
|
self.setFont('Helvetica', 8)
|
||||||
self.setFillColor(colors.darkred)
|
# ~ self.setFillColor(colors.darkred)
|
||||||
text = 'Página {} de {}'.format(self._pageNumber, page_count)
|
text = f'Página {self._pageNumber} de {page_count}'
|
||||||
self.drawRightString(self.X, self.Y, text)
|
self.drawRightString(self.X, self.Y, text)
|
||||||
text = 'Factura elaborada con software libre: www.empresalibre.net'
|
|
||||||
|
text = 'Este documento es una representación impresa de un CFDI'
|
||||||
|
self.drawCentredString(self.XC, self.Y, text)
|
||||||
|
|
||||||
|
text = 'Factura elaborada con software libre'
|
||||||
self.drawString(1.5 * cm, 1.5 * cm, text)
|
self.drawString(1.5 * cm, 1.5 * cm, text)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -418,6 +423,8 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
def _emisor(self, styles, data):
|
def _emisor(self, styles, data):
|
||||||
logo_path = data.pop('logo', '')
|
logo_path = data.pop('logo', '')
|
||||||
logo_style = styles.pop('logo', {})
|
logo_style = styles.pop('logo', {})
|
||||||
|
logo_path2 = data.pop('logo2', '')
|
||||||
|
logo_style2 = styles.pop('logo2', {})
|
||||||
|
|
||||||
for k, v in styles.items():
|
for k, v in styles.items():
|
||||||
self._set_text(styles[k], data.get(k, ''))
|
self._set_text(styles[k], data.get(k, ''))
|
||||||
|
@ -428,6 +435,14 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
for k in keys:
|
for k in keys:
|
||||||
rect[k] = rect[k] * cm
|
rect[k] = rect[k] * cm
|
||||||
self.canv.drawImage(logo_path, **rect)
|
self.canv.drawImage(logo_path, **rect)
|
||||||
|
|
||||||
|
if logo_path2 and logo_style2:
|
||||||
|
rect = logo_style2['rectangulo']
|
||||||
|
keys = ('x', 'y', 'width', 'height')
|
||||||
|
for k in keys:
|
||||||
|
rect[k] = rect[k] * cm
|
||||||
|
self.canv.drawImage(logo_path2, **rect)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _receptor(self, styles, data):
|
def _receptor(self, styles, data):
|
||||||
|
@ -449,6 +464,7 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
|
|
||||||
def _comprobante1(self, styles, data):
|
def _comprobante1(self, styles, data):
|
||||||
title = styles.pop('titulo', {})
|
title = styles.pop('titulo', {})
|
||||||
|
self.canv.setTitle(f"Factura {data.get('seriefolio', '')}")
|
||||||
|
|
||||||
for k, v in styles.items():
|
for k, v in styles.items():
|
||||||
self._set_text(styles[k], data.get(k, ''))
|
self._set_text(styles[k], data.get(k, ''))
|
||||||
|
@ -480,6 +496,12 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
fields = ('valorunitario', 'importe')
|
fields = ('valorunitario', 'importe')
|
||||||
if field in fields:
|
if field in fields:
|
||||||
return self._currency(value)
|
return self._currency(value)
|
||||||
|
|
||||||
|
if field == 'descripcion':
|
||||||
|
html = '<font color="black" size=7>{}</font>'
|
||||||
|
style_bt = getSampleStyleSheet()['BodyText']
|
||||||
|
return Paragraph(html.format(value), style_bt)
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _conceptos(self, conceptos):
|
def _conceptos(self, conceptos):
|
||||||
|
@ -515,8 +537,8 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
('GRID', (0, 0), (-1, -1), 0.05 * cm, colors.white),
|
('GRID', (0, 0), (-1, -1), 0.05 * cm, colors.white),
|
||||||
('ALIGN', (1, 0), (-1, -1), 'RIGHT'),
|
('ALIGN', (1, 0), (-1, -1), 'RIGHT'),
|
||||||
('FONTSIZE', (0, 0), (-1, -1), 8),
|
('FONTSIZE', (0, 0), (-1, -1), 8),
|
||||||
('BACKGROUND', (1, 0), (-1, -1), colors.linen),
|
('BACKGROUND', (1, 0), (-1, -1), colors.lightgrey),
|
||||||
('TEXTCOLOR', (1, 0), (-1, -1), colors.darkred),
|
('TEXTCOLOR', (1, 0), (-1, -1), colors.black),
|
||||||
('FACE', (1, 0), (-1, -1), 'Helvetica-Bold'),
|
('FACE', (1, 0), (-1, -1), 'Helvetica-Bold'),
|
||||||
]
|
]
|
||||||
table = Table(rows, colWidths=widths, spaceBefore=0.25*cm)
|
table = Table(rows, colWidths=widths, spaceBefore=0.25*cm)
|
||||||
|
@ -524,7 +546,7 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
return table
|
return table
|
||||||
|
|
||||||
def _comprobante2(self, styles, data):
|
def _comprobante2(self, styles, data):
|
||||||
leyenda = styles.pop('leyenda', {})
|
leyendas = styles.pop('leyendas', {})
|
||||||
|
|
||||||
ls = []
|
ls = []
|
||||||
for k, v in styles.items():
|
for k, v in styles.items():
|
||||||
|
@ -542,7 +564,7 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
style_bt = getSampleStyleSheet()['BodyText']
|
style_bt = getSampleStyleSheet()['BodyText']
|
||||||
style_bt.leading = 8
|
style_bt.leading = 8
|
||||||
html_t = '<b><font size=6>{}</font></b>'
|
html_t = '<b><font size=6>{}</font></b>'
|
||||||
html = '<font color="darkred" size=5>{}</font>'
|
html = '<font color="black" size=5>{}</font>'
|
||||||
msg = 'Cadena original del complemento de certificación digital del SAT'
|
msg = 'Cadena original del complemento de certificación digital del SAT'
|
||||||
rows = [
|
rows = [
|
||||||
(cbb, Paragraph(html_t.format('Sello Digital del CFDI'), style_bt)),
|
(cbb, Paragraph(html_t.format('Sello Digital del CFDI'), style_bt)),
|
||||||
|
@ -558,13 +580,13 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
('FONTSIZE', (0, 0), (-1, -1), 6),
|
('FONTSIZE', (0, 0), (-1, -1), 6),
|
||||||
('SPAN', (0, 0), (0, -1)),
|
('SPAN', (0, 0), (0, -1)),
|
||||||
('FACE', (1, 0), (1, 0), 'Helvetica-Bold'),
|
('FACE', (1, 0), (1, 0), 'Helvetica-Bold'),
|
||||||
('BACKGROUND', (1, 1), (1, 1), colors.linen),
|
('BACKGROUND', (1, 1), (1, 1), colors.lightgrey),
|
||||||
('TEXTCOLOR', (1, 1), (1, 1), colors.darkred),
|
('TEXTCOLOR', (1, 1), (1, 1), colors.darkred),
|
||||||
('FACE', (1, 2), (1, 2), 'Helvetica-Bold'),
|
('FACE', (1, 2), (1, 2), 'Helvetica-Bold'),
|
||||||
('BACKGROUND', (1, 3), (1, 3), colors.linen),
|
('BACKGROUND', (1, 3), (1, 3), colors.lightgrey),
|
||||||
('TEXTCOLOR', (1, 3), (1, 3), colors.darkred),
|
('TEXTCOLOR', (1, 3), (1, 3), colors.darkred),
|
||||||
('FACE', (1, 4), (1, 4), 'Helvetica-Bold'),
|
('FACE', (1, 4), (1, 4), 'Helvetica-Bold'),
|
||||||
('BACKGROUND', (1, 5), (1, 5), colors.linen),
|
('BACKGROUND', (1, 5), (1, 5), colors.lightgrey),
|
||||||
('TEXTCOLOR', (1, 5), (1, 5), colors.darkred),
|
('TEXTCOLOR', (1, 5), (1, 5), colors.darkred),
|
||||||
('ALIGN', (0, 0), (0, 0), 'CENTER'),
|
('ALIGN', (0, 0), (0, 0), 'CENTER'),
|
||||||
('VALIGN', (0, 0), (0, 0), 'MIDDLE'),
|
('VALIGN', (0, 0), (0, 0), 'MIDDLE'),
|
||||||
|
@ -573,14 +595,14 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
table.setStyle(TableStyle(table_styles))
|
table.setStyle(TableStyle(table_styles))
|
||||||
ls.append(table)
|
ls.append(table)
|
||||||
|
|
||||||
if leyenda:
|
if leyendas:
|
||||||
if 'spaceBefore' in leyenda['estilo']:
|
if 'spaceBefore' in leyendas['estilo']:
|
||||||
leyenda['estilo']['spaceBefore'] = \
|
leyendas['estilo']['spaceBefore'] = \
|
||||||
leyenda['estilo']['spaceBefore'] * cm
|
leyendas['estilo']['spaceBefore'] * cm
|
||||||
msg = 'Este documento es una representación impresa de un CFDI'
|
for t in leyendas['textos']:
|
||||||
ps = ParagraphStyle(**leyenda['estilo'])
|
ps = ParagraphStyle(**leyendas['estilo'])
|
||||||
p = Paragraph(msg, ps)
|
p = Paragraph(t, ps)
|
||||||
ls.append(p)
|
ls.append(p)
|
||||||
|
|
||||||
return ls
|
return ls
|
||||||
|
|
||||||
|
@ -607,13 +629,13 @@ class TemplateInvoice(BaseDocTemplate):
|
||||||
('ALIGN', (0, 0), (-1, 0), 'CENTER'),
|
('ALIGN', (0, 0), (-1, 0), 'CENTER'),
|
||||||
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
|
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
|
||||||
('FACE', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
('FACE', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
||||||
('BACKGROUND', (0, 0), (-1, 0), colors.darkred),
|
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
|
||||||
('FONTSIZE', (0, 1), (-1, -1), 7),
|
('FONTSIZE', (0, 1), (-1, -1), 7),
|
||||||
('VALIGN', (0, 1), (-1, -1), 'TOP'),
|
('VALIGN', (0, 1), (-1, -1), 'TOP'),
|
||||||
('ALIGN', (0, 1), (0, -1), 'CENTER'),
|
('ALIGN', (0, 1), (0, -1), 'CENTER'),
|
||||||
('ALIGN', (2, 1), (2, -1), 'CENTER'),
|
('ALIGN', (2, 1), (2, -1), 'CENTER'),
|
||||||
('ALIGN', (3, 1), (5, -1), 'RIGHT'),
|
('ALIGN', (3, 1), (5, -1), 'RIGHT'),
|
||||||
('LINEBELOW', (0, 1), (-1, -1), 0.05 * cm, colors.darkred),
|
('LINEBELOW', (0, 1), (-1, -1), 0.05 * cm, colors.grey),
|
||||||
('LINEBEFORE', (0, 1), (-1, -1), 0.05 * cm, colors.white),
|
('LINEBEFORE', (0, 1), (-1, -1), 0.05 * cm, colors.white),
|
||||||
]
|
]
|
||||||
table_conceptos = Table(rows, colWidths=widths, repeatRows=1)
|
table_conceptos = Table(rows, colWidths=widths, repeatRows=1)
|
||||||
|
|
|
@ -1592,9 +1592,15 @@ def to_pdf(data, emisor_rfc, ods=False, pdf_from='1'):
|
||||||
|
|
||||||
|
|
||||||
def to_pdf_from_json(rfc, version, data):
|
def to_pdf_from_json(rfc, version, data):
|
||||||
|
rfc = rfc.lower()
|
||||||
name = '{}_{}.json'.format(rfc, version)
|
name = '{}_{}.json'.format(rfc, version)
|
||||||
custom_styles = get_custom_styles(name)
|
custom_styles = get_custom_styles(name)
|
||||||
|
|
||||||
|
path_logo = _join(PATHS['IMG'], f"{rfc}.png")
|
||||||
|
data['emisor']['logo'] = path_logo
|
||||||
|
path_logo = _join(PATHS['IMG'], f"{rfc}_2.png")
|
||||||
|
data['emisor']['logo2'] = path_logo
|
||||||
|
|
||||||
path = get_path_temp()
|
path = get_path_temp()
|
||||||
pdf = TemplateInvoice(path)
|
pdf = TemplateInvoice(path)
|
||||||
pdf.custom_styles = custom_styles
|
pdf.custom_styles = custom_styles
|
||||||
|
|
|
@ -3719,6 +3719,7 @@ class Facturas(BaseModel):
|
||||||
values['receptor'] = {}
|
values['receptor'] = {}
|
||||||
for k, v in receptor.items():
|
for k, v in receptor.items():
|
||||||
values['receptor'][k] = v
|
values['receptor'][k] = v
|
||||||
|
|
||||||
return values
|
return values
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"colores": {"piepagina": "darkred"},
|
||||||
"encabezado": {
|
"encabezado": {
|
||||||
"emisor": {
|
"emisor": {
|
||||||
"direccion": {
|
"direccion": {
|
||||||
|
@ -208,10 +209,9 @@
|
||||||
"estilo": {"name": "tipocambio", "fontName": "Helvetica",
|
"estilo": {"name": "tipocambio", "fontName": "Helvetica",
|
||||||
"fontSize": 7, "alignment": 0, "textColor": "black"}
|
"fontSize": 7, "alignment": 0, "textColor": "black"}
|
||||||
},
|
},
|
||||||
"leyenda": {
|
"notas": {
|
||||||
"estilo": {"name": "leyenda", "fontName": "Helvetica-Bold",
|
"estilo": {"name": "notas", "fontName": "Helvetica",
|
||||||
"fontSize": 6, "alignment": 1, "textColor": "black",
|
"fontSize": 7, "alignment": 0, "textColor": "black"}
|
||||||
"spaceBefore": 0.2}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue