diff --git a/source/app/controllers/helper.py b/source/app/controllers/helper.py index 55d9056..0ccfc90 100644 --- a/source/app/controllers/helper.py +++ b/source/app/controllers/helper.py @@ -12,7 +12,7 @@ from email.mime.text import MIMEText from email import encoders from email.utils import formatdate -from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate +from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Image from reportlab.lib import colors from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import cm @@ -105,7 +105,7 @@ class NumLet(object): #~ texto_final='/100 m.n.)-', fraccion_letras=False, fraccion=''): def _letters(self, numero, moneda='peso'): - texto_inicial = '' + texto_inicial = '-(' texto_final = '/100 m.n.)-' fraccion_letras = False fraccion = '' @@ -309,7 +309,7 @@ class SendMail(object): class NumberedCanvas(canvas.Canvas): X = 20.59 * cm - Y = 1 * cm + Y = 1.5 * cm def __init__(self, *args, **kwargs): canvas.Canvas.__init__(self, *args, **kwargs) @@ -335,6 +335,8 @@ class NumberedCanvas(canvas.Canvas): self.setFillColor(colors.darkred) text = 'Página {} de {}'.format(self._pageNumber, page_count) self.drawRightString(self.X, self.Y, text) + text = 'Factura elaborada con software libre: www.empresalibre.net' + self.drawString(1.5 * cm, 1.5 * cm, text) return @@ -366,6 +368,10 @@ class TemplateInvoice(BaseDocTemplate): return def _set_text(self, styles, value): + text = styles.pop('valor', '') + if not value: + value = text + rect = styles['rectangulo'] if value: self.canv.setFillColor(colors.white) @@ -379,17 +385,174 @@ class TemplateInvoice(BaseDocTemplate): return def _emisor(self, styles, data): + logo_path = data.pop('logo', '') + logo_style = styles.pop('logo', {}) + for k, v in styles.items(): self._set_text(styles[k], data.get(k, '')) + + if logo_path and logo_style: + rect = logo_style['rectangulo'] + keys = ('x', 'y', 'width', 'height') + for k in keys: + rect[k] = rect[k] * cm + self.canv.drawImage(logo_path, **rect) + return + + def _receptor(self, styles, data): + title = styles.pop('titulo', {}) + + for k, v in styles.items(): + self._set_text(styles[k], data.get(k, '')) + + if title: + rect = title['rectangulo'] + self.canv.saveState() + self.canv.rotate(90) + value = title.pop('valor', '') + title['rectangulo']['x'], title['rectangulo']['y'] = \ + title['rectangulo']['y'], title['rectangulo']['x'] * -1 + self._set_text(title, value) + self.canv.restoreState() + return + + def _comprobante1(self, styles, data): + title = styles.pop('titulo', {}) + + for k, v in styles.items(): + self._set_text(styles[k], data.get(k, '')) + + if title: + rect = title['rectangulo'] + self.canv.saveState() + self.canv.rotate(90) + value = title.pop('valor', '') + title['rectangulo']['x'], title['rectangulo']['y'] = \ + title['rectangulo']['y'], title['rectangulo']['x'] * -1 + self._set_text(title, value) + self.canv.restoreState() return def afterPage(self): encabezado = self._custom_styles['encabezado'] self.canv.saveState() self._emisor(encabezado['emisor'], self._data['emisor']) + self._receptor(encabezado['receptor'], self._data['receptor']) + self._comprobante1(encabezado['comprobante'], self._data['comprobante']) self.canv.restoreState() return + def _currency(self, value, simbol='$'): + return '{} {:,.2f}'.format(simbol, float(value)) + + def _format(self, value, field): + fields = ('valorunitario', 'importe') + if field in fields: + return self._currency(value) + return value + + def _conceptos(self, conceptos): + headers = (('Clave', 'Descripción', 'Unidad', 'Cantidad', + 'Valor Unitario', 'Importe'),) + fields = ('noidentificacion', 'descripcion', 'unidad', 'cantidad', + 'valorunitario', 'importe') + rows = [] + for concepto in conceptos: + row = tuple([self._format(concepto[f], f) for f in fields]) + rows.append(row) + return headers + tuple(rows) + + def _totales(self, values): + #~ print (values) + rows = [('', 'Subtotal', self._currency(values['subtotal']))] + + for tax in values['traslados']: + row = ('', tax[0], self._currency(tax[1])) + rows.append(row) + for tax in values['retenciones']: + row = ('', tax[0], self._currency(tax[1])) + rows.append(row) + for tax in values['taxlocales']: + row = ('', tax[0], self._currency(tax[1])) + rows.append(row) + + row = ('', 'Total', self._currency(values['total'])) + rows.append(row) + + widths = [12.5 * cm, 4 * cm, 3 * cm] + table_styles = [ + ('GRID', (0, 0), (-1, -1), 0.05 * cm, colors.white), + ('ALIGN', (1, 0), (-1, -1), 'RIGHT'), + ('FONTSIZE', (0, 0), (-1, -1), 8), + ('BACKGROUND', (1, 0), (-1, -1), colors.linen), + ('TEXTCOLOR', (1, 0), (-1, -1), colors.darkred), + ('FACE', (1, 0), (-1, -1), 'Helvetica-Bold'), + ] + table = Table(rows, colWidths=widths, spaceBefore=0.25*cm) + table.setStyle(TableStyle(table_styles)) + return table + + def _comprobante2(self, styles, data): + leyenda = styles.pop('leyenda', {}) + + ls = [] + for k, v in styles.items(): + if k in data: + if 'spaceBefore' in v['estilo']: + v['estilo']['spaceBefore'] = v['estilo']['spaceBefore'] * cm + ps = ParagraphStyle(**v['estilo']) + p = Paragraph(data[k], ps) + ls.append(p) + + cbb = Image(data['path_cbb']) + cbb.drawHeight = 4 * cm + cbb.drawWidth = 4 * cm + + style_bt = getSampleStyleSheet()['BodyText'] + style_bt.leading = 8 + html_t = '{}' + html = '{}' + msg = 'Cadena original del complemento de certificación digital del SAT' + rows = [ + (cbb, Paragraph(html_t.format('Sello Digital del CFDI'), style_bt)), + ('', Paragraph(html.format(data['sellocfd']), style_bt)), + ('', Paragraph(html_t.format('Sello Digital del SAT'), style_bt)), + ('', Paragraph(html.format(data['sellosat']), style_bt)), + ('', Paragraph(html_t.format(msg), style_bt)), + ('', Paragraph(html.format(data['cadenaoriginal']), style_bt)), + ] + + widths = [4 * cm, 15.5 * cm] + table_styles = [ + ('FONTSIZE', (0, 0), (-1, -1), 6), + ('SPAN', (0, 0), (0, -1)), + ('FACE', (1, 0), (1, 0), 'Helvetica-Bold'), + ('BACKGROUND', (1, 1), (1, 1), colors.linen), + ('TEXTCOLOR', (1, 1), (1, 1), colors.darkred), + ('FACE', (1, 2), (1, 2), 'Helvetica-Bold'), + ('BACKGROUND', (1, 3), (1, 3), colors.linen), + ('TEXTCOLOR', (1, 3), (1, 3), colors.darkred), + ('FACE', (1, 4), (1, 4), 'Helvetica-Bold'), + ('BACKGROUND', (1, 5), (1, 5), colors.linen), + ('TEXTCOLOR', (1, 5), (1, 5), colors.darkred), + ('ALIGN', (0, 0), (0, 0), 'CENTER'), + ('VALIGN', (0, 0), (0, 0), 'MIDDLE'), + ] + table = Table(rows, colWidths=widths) + table.setStyle(TableStyle(table_styles)) + ls.append(table) + + if leyenda: + if 'spaceBefore' in leyenda['estilo']: + leyenda['estilo']['spaceBefore'] = \ + leyenda['estilo']['spaceBefore'] * cm + msg = 'Este documento es una representación impresa de un CFDI' + ps = ParagraphStyle(**leyenda['estilo']) + p = Paragraph(msg, ps) + ls.append(p) + + return ls + @property def custom_styles(self): return self._custom_styles @@ -402,23 +565,34 @@ class TemplateInvoice(BaseDocTemplate): return self._data @data.setter def data(self, values): + #~ print (values) self._data = values - text = 'Total este reporte = $ {}'.format('1,000.00') - ps = ParagraphStyle( - name='Total', - fontSize=12, - fontName='Helvetica-BoldOblique', - textColor=colors.darkred, - spaceBefore=0.5 * cm, - spaceAfter=0.5 * cm) - p1 = Paragraph(text, ps) - text = 'Nota: esta suma no incluye documentos cancelados' - ps = ParagraphStyle( - name='Note', - fontSize=7, - fontName='Helvetica-BoldOblique') - p2 = Paragraph('', ps) - self._rows = [p2] + + rows = self._conceptos(self._data['conceptos']) + widths = [2 * cm, 9 * cm, 1.5 * cm, 2 * cm, 2 * cm, 3 * cm] + table_styles = [ + ('GRID', (0, 0), (-1, -1), 0.05 * cm, colors.white), + ('FONTSIZE', (0, 0), (-1, 0), 7), + ('ALIGN', (0, 0), (-1, 0), 'CENTER'), + ('TEXTCOLOR', (0, 0), (-1, 0), colors.white), + ('FACE', (0, 0), (-1, 0), 'Helvetica-Bold'), + ('BACKGROUND', (0, 0), (-1, 0), colors.darkred), + ('FONTSIZE', (0, 1), (-1, -1), 7), + ('VALIGN', (0, 1), (-1, -1), 'TOP'), + ('ALIGN', (0, 1), (0, -1), 'CENTER'), + ('ALIGN', (2, 1), (2, -1), 'CENTER'), + ('ALIGN', (3, 1), (5, -1), 'RIGHT'), + ('LINEBELOW', (0, 1), (-1, -1), 0.05 * cm, colors.darkred), + ('LINEBEFORE', (0, 1), (-1, -1), 0.05 * cm, colors.white), + ] + table_conceptos = Table(rows, colWidths=widths, repeatRows=1) + table_conceptos.setStyle(TableStyle(table_styles)) + + totales = self._totales(self.data['totales']) + comprobante = self._comprobante2( + self._custom_styles['comprobante'], self.data['comprobante']) + + self._rows = [Spacer(0, 6*cm), table_conceptos, totales] + comprobante def render(self): frame = Frame(self.leftMargin, self.bottomMargin, @@ -487,7 +661,7 @@ class ReportTemplate(BaseDocTemplate): ('GRID', (0, 0), (-1, -1), 0.25, colors.darkred), ('FONTSIZE', (0, 0), (-1, 0), 9), ('BOX', (0, 0), (-1, 0), 1, colors.darkred), - ('TEXTCOLOR', (0, 0), (-1, 0), colors.darkred), + ('TEXTCOLOR', (0, 0), (-1, 0), colors.black), ('FONTSIZE', (0, 1), (-1, -1), 8), ('ALIGN', (0, 0), (-1, 0), 'CENTER'), ('ALIGN', (0, 0), (0, -1), 'RIGHT'), diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index 0ec5d31..a616f15 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -29,7 +29,7 @@ from dateutil import parser from .helper import CaseInsensitiveDict, NumLet, SendMail, TemplateInvoice from settings import DEBUG, log, template_lookup, COMPANIES, DB_SAT, \ - PATH_XSLT, PATH_XSLTPROC, PATH_OPENSSL, PATH_TEMPLATES, PRE + PATH_XSLT, PATH_XSLTPROC, PATH_OPENSSL, PATH_TEMPLATES, PATH_MEDIA, PRE #~ def _get_hash(password): @@ -774,14 +774,15 @@ def _comprobante(values, options): 'T': 'traslado', } data['tipodecomprobante'] = tipos.get(data['tipodecomprobante']) - data['lugarexpedicion'] = 'C.P. Expedición: {}'.format(data['lugarexpedicion']) + data['lugarexpedicion'] = 'C.P. de Expedición: {}'.format(data['lugarexpedicion']) data['metododepago'] = options['metododepago'] data['formadepago'] = options['formadepago'] data['moneda'] = options['moneda'] data['tipocambio'] = 'Tipo de Cambio: $ {:0.2f}'.format( float(data['tipocambio'])) - + if 'serie' in data: + data['folio'] = '{}-{}'.format(data['serie'], data['folio']) return data @@ -792,6 +793,11 @@ def _emisor(doc, version, values): if not node is None: data.update(CaseInsensitiveDict(node.attrib.copy())) data['regimenfiscal'] = values['regimenfiscal'] + + path = _join(PATH_MEDIA, 'logos', '{}.png'.format(data['rfc'].lower())) + if is_file(path): + data['logo'] = path + return data @@ -813,7 +819,7 @@ def _conceptos(doc, version): if version == '3.3': values['noidentificacion'] = '{}\n(SAT {})'.format( values['noidentificacion'], values['ClaveProdServ']) - values['unidad'] = '({}) {}'.format( + values['unidad'] = '({})\n{}'.format( values['ClaveUnidad'], values['unidad']) data.append(values) return data @@ -926,6 +932,7 @@ def get_data_from_xml(invoice, rfc, values): 'total': data['comprobante']['total'], } data['timbre'] = _timbre(doc, version, options) + data['comprobante'].update(data['timbre']) return custom_styles, data diff --git a/source/app/models/main.py b/source/app/models/main.py index 392d58c..432e8a7 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -137,7 +137,7 @@ class SATRegimenes(BaseModel): ) def __str__(self): - return '({}) {}'.format(self.key, self.name) + return '{} ({})'.format(self.name, self.key) @classmethod def get_(cls, ids): @@ -597,7 +597,7 @@ class SATUsoCfdi(BaseModel): ) def __str__(self): - return 'Uso del CFDI: ({}) {}'.format(self.key, self.name) + return 'Uso del CFDI: {} ({})'.format(self.name, self.key) @classmethod def get_activos(cls, values): diff --git a/source/app/settings.py b/source/app/settings.py index 1e68df6..52205e6 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -17,6 +17,7 @@ EMAIL_SUPPORT = ('soporte@empresalibre.net',) BASE_DIR = os.path.abspath(os.path.dirname(__file__)) PATH_STATIC = os.path.abspath(os.path.join(BASE_DIR, '..')) PATH_TEMPLATES = os.path.abspath(os.path.join(BASE_DIR, '..', 'templates')) +PATH_MEDIA = os.path.abspath(os.path.join(BASE_DIR, '..', 'docs')) PATH_CP = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'cp.db')) COMPANIES = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'rfc.db')) diff --git a/source/templates/plantilla_factura.json b/source/templates/plantilla_factura.json index 9f17882..6aabf3f 100644 --- a/source/templates/plantilla_factura.json +++ b/source/templates/plantilla_factura.json @@ -2,25 +2,216 @@ "encabezado": { "emisor": { "direccion": { - "rectangulo": {"x": 1.0, "y": 26.9, "width": 19.6, "height": 0.4, + "rectangulo": {"x": 1.0, "y": 26.2, "width": 19.6, "height": 0.4, "radius": 0.1, "stroke": false, "fill": true, "color": "darkred"} }, "nombre": { - "rectangulo": {"x": 10.6, "y": 25.9, "width": 10.0, "height": 0.4, + "rectangulo": {"x": 10.6, "y": 25.6, "width": 10.0, "height": 0.4, "radius": 0.0, "stroke": false, "fill": false}, - "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", "fontSize": 12, - "alignment": 2, "textColor": "darkred", "backColor": "white"} + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 14, "alignment": 2, "textColor": "darkred", + "backColor": "white"} }, "rfc": { - "rectangulo": {"x": 10.6, "y": 25.1, "width": 10.0, "height": 0.4, + "rectangulo": {"x": 10.6, "y": 25.0, "width": 10.0, "height": 0.4, "radius": 0.0, "stroke": false, "fill": false}, - "estilo": {"name": "rfc", "fontName": "Helvetica-Bold", "fontSize": 11, - "alignment": 2, "textColor": "darkred", "backColor": "white"} + "estilo": {"name": "rfc", "fontName": "Helvetica-Bold", + "fontSize": 12, "alignment": 2, "textColor": "darkred", + "backColor": "white"} + }, + "regimenfiscal": { + "rectangulo": {"x": 10.6, "y": 24.4, "width": 10.0, "height": 0.4, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "regimenfiscal", "fontName": "Helvetica-Bold", + "fontSize": 7, "alignment": 2, "textColor": "darkred", + "backColor": "white"} + }, + "logo": { + "rectangulo": {"x": 1.0, "y": 24.2, "width": 2.5, "height": 2.5} + } + }, + "receptor": { + "titulo": { + "valor": "Receptor", + "rectangulo": {"x": 1.5, "y": 20.8, "width": 2.8, "height": 0.9, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 9, "alignment": 1, "textColor": "darkred", + "backColor": "linen"} + }, + "nombre": { + "rectangulo": {"x": 2.0, "y": 23.2, "width": 15.0, "height": 0.4, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 10, "alignment": 0, "textColor": "black", + "backColor": "white"} + }, + "rfc": { + "rectangulo": {"x": 2.0, "y": 22.5, "width": 10.0, "height": 0.4, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "rfc", "fontName": "Helvetica-Bold", + "fontSize": 9, "alignment": 0, "textColor": "black", + "backColor": "white"} + }, + "usocfdi": { + "rectangulo": {"x": 2.0, "y": 20.7, "width": 15.0, "height": 0.4, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "usocfdi", "fontName": "Helvetica", + "fontSize": 8, "alignment": 0, "textColor": "black", + "backColor": "white"} + } + }, + "comprobante": { + "titulo": { + "valor": "Datos CFDI", + "rectangulo": {"x": 14.0, "y": 20.8, "width": 2.8, "height": 0.9, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 9, "alignment": 1, "textColor": "darkred", + "backColor": "linen"} + }, + "t_folio": { + "valor": "Folio:", + "rectangulo": {"x": 14.2, "y": 23.2, "width": 1.0, "height": 0.8, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 8, "alignment": 0, "textColor": "black", + "backColor": "white"} + }, + "folio": { + "rectangulo": {"x": 15.1, "y": 23.2, "width": 3.0, "height": 0.4, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 8, "alignment": 0, "textColor": "red", + "backColor": "white"} + }, + "t_tipo": { + "valor": "Tipo:", + "rectangulo": {"x": 18.2, "y": 23.2, "width": 1.0, "height": 0.8, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 8, "alignment": 0, "textColor": "black", + "backColor": "white"} + }, + "tipodecomprobante": { + "rectangulo": {"x": 19.0, "y": 23.2, "width": 1.5, "height": 0.8, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 8, "alignment": 0, "textColor": "red", + "backColor": "white"} + }, + "t_uuid": { + "valor": "Folio Fiscal:", + "rectangulo": {"x": 14.2, "y": 22.7, "width": 3.0, "height": 0.4, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 0, "textColor": "black", + "backColor": "white"} + }, + "uuid": { + "rectangulo": {"x": 15.6, "y": 22.7, "width": 6.5, "height": 0.4, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 0, "textColor": "red", + "backColor": "white"} + }, + "t_fecha": { + "valor": "Fecha Expedición:", + "rectangulo": {"x": 14.2, "y": 22.1, "width": 2.2, "height": 0.3, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 2, "textColor": "black", + "backColor": "white"} + }, + "fecha": { + "rectangulo": {"x": 16.5, "y": 22.1, "width": 3.0, "height": 0.3, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 0, "textColor": "black", + "backColor": "white"} + }, + "t_fecha_timbrado": { + "valor": "Fecha Timbrado:", + "rectangulo": {"x": 14.2, "y": 21.8, "width": 2.2, "height": 0.3, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 2, "textColor": "black", + "backColor": "white"} + }, + "fechatimbrado": { + "rectangulo": {"x": 16.5, "y": 21.8, "width": 3.0, "height": 0.3, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 0, "textColor": "black", + "backColor": "white"} + }, + "t_serie_emisor": { + "valor": "Serie CSD Emisor:", + "rectangulo": {"x": 14.2, "y": 21.4, "width": 2.2, "height": 0.3, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 2, "textColor": "black", + "backColor": "white"} + }, + "nocertificado": { + "rectangulo": {"x": 16.5, "y": 21.4, "width": 3.0, "height": 0.3, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 0, "textColor": "black", + "backColor": "white"} + }, + "t_serie_sat": { + "valor": "Serie CSD SAT:", + "rectangulo": {"x": 14.2, "y": 21.1, "width": 2.2, "height": 0.3, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 2, "textColor": "black", + "backColor": "white"} + }, + "nocertificadosat": { + "rectangulo": {"x": 16.5, "y": 21.1, "width": 3.0, "height": 0.3, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 0, "textColor": "black", + "backColor": "white"} + }, + "lugarexpedicion": { + "rectangulo": {"x": 14.2, "y": 20.7, "width": 5.5, "height": 0.4, + "radius": 0.0, "stroke": false, "fill": false}, + "estilo": {"name": "nombre", "fontName": "Helvetica-Bold", + "fontSize": 7, "alignment": 1, "textColor": "black", + "backColor": "white"} } } }, "conceptos": { }, "comprobante": { + "totalenletras": { + "estilo": {"name": "enletras", "fontName": "Helvetica-Bold", + "fontSize": 7, "alignment": 1, "textColor": "black", + "spaceBefore": 0.1} + }, + "formadepago": { + "estilo": {"name": "formadepago", "fontName": "Helvetica", + "fontSize": 7, "alignment": 0, "textColor": "black"} + }, + "metododepago": { + "estilo": {"name": "metododepago", "fontName": "Helvetica", + "fontSize": 7, "alignment": 0, "textColor": "black"} + }, + "moneda": { + "estilo": {"name": "moneda", "fontName": "Helvetica", + "fontSize": 7, "alignment": 0, "textColor": "black"} + }, + "tipocambio": { + "estilo": {"name": "tipocambio", "fontName": "Helvetica", + "fontSize": 7, "alignment": 0, "textColor": "black"} + }, + "leyenda": { + "estilo": {"name": "leyenda", "fontName": "Helvetica-Bold", + "fontSize": 6, "alignment": 1, "textColor": "black", + "spaceBefore": 0.2} + } } }