Generate PDF from cfdi pay

This commit is contained in:
Mauricio Baeza 2018-08-30 19:24:33 -05:00
parent 9dc2c72de7
commit fd75da65fc
4 changed files with 171 additions and 8 deletions

View File

@ -320,6 +320,9 @@ def get_template_ods(name, default='plantilla_factura.ods'):
if is_file(path):
return path
if 'pagos' in name:
default='plantilla_pagos.ods'
path = _join(PATH_TEMPLATES, default)
if is_file(path):
return path
@ -954,6 +957,9 @@ class LIBO(object):
self._set_cell('{total_cantidades}', str(self._total_cantidades))
if self._pagos:
return
cell_title = self._set_cell('{subtotal.titulo}', 'SubTotal')
value = data['subtotal']
cell_value = self._set_cell('{subtotal}', value, value=True)
@ -1150,16 +1156,114 @@ class LIBO(object):
return
def _cfdipays(self, data):
related = data.pop('related', [])
for k, v in data.items():
if k.lower() in ('monto',):
self._set_cell('{pago.%s}' % k, v, value=True)
else:
self._set_cell('{pago.%s}' % k, v)
col1 = []
col2 = []
col3 = []
col4 = []
col5 = []
col6 = []
col7 = []
col8 = []
col9 = []
count = len(related)
for i, doc in enumerate(related):
uuid = doc['IdDocumento'].upper()
serie = doc['Serie']
folio = doc['Folio']
metodo_pago = doc['MetodoDePagoDR']
moneda = doc['MonedaDR']
parcialidad = doc['NumParcialidad']
saldo_anterior = doc['ImpSaldoAnt']
importe_pagado = doc['ImpPagado']
saldo_insoluto = doc['ImpSaldoInsoluto']
if i == 0:
cell_1 = self._set_cell('{doc.uuid}', uuid)
cell_2 = self._set_cell('{doc.serie}', serie)
cell_3 = self._set_cell('{doc.folio}', folio)
cell_4 = self._set_cell('{doc.metodopago}', metodo_pago)
cell_5 = self._set_cell('{doc.moneda}', moneda)
cell_6 = self._set_cell('{doc.parcialidad}', parcialidad)
cell_7 = self._set_cell('{doc.saldoanterior}', saldo_anterior, value=True)
cell_8 = self._set_cell('{doc.importepagado}', importe_pagado, value=True)
cell_9 = self._set_cell('{doc.saldoinsoluto}', saldo_insoluto, value=True)
else:
col1.append((uuid,))
col2.append((serie,))
col3.append((folio,))
col4.append((metodo_pago,))
col5.append((moneda,))
col6.append((parcialidad,))
col7.append((float(saldo_anterior),))
col8.append((float(importe_pagado),))
col9.append((float(saldo_insoluto),))
if count == 1:
return
count -= 1
row1 = cell_1.getCellAddress().Row + 1
row2 = row1 + count - 1
self._sheet.getRows().insertByIndex(row1, count)
self._copy_paste_rows(cell_1, count)
# ~ style_7 = self._get_style(cell_7)
# ~ style_8 = self._get_style(cell_8)
# ~ style_9 = self._get_style(cell_9)
col = cell_1.getCellAddress().Column
target1 = self._sheet.getCellRangeByPosition(col, row1, col, row2)
col = cell_2.getCellAddress().Column
target2 = self._sheet.getCellRangeByPosition(col, row1, col, row2)
col = cell_3.getCellAddress().Column
target3 = self._sheet.getCellRangeByPosition(col, row1, col, row2)
col = cell_4.getCellAddress().Column
target4 = self._sheet.getCellRangeByPosition(col, row1, col, row2)
col = cell_5.getCellAddress().Column
target5 = self._sheet.getCellRangeByPosition(col, row1, col, row2)
col = cell_6.getCellAddress().Column
target6 = self._sheet.getCellRangeByPosition(col, row1, col, row2)
col = cell_7.getCellAddress().Column
target7 = self._sheet.getCellRangeByPosition(col, row1, col, row2)
col = cell_8.getCellAddress().Column
target8 = self._sheet.getCellRangeByPosition(col, row1, col, row2)
col = cell_9.getCellAddress().Column
target9 = self._sheet.getCellRangeByPosition(col, row1, col, row2)
target1.setFormulaArray(tuple(col1))
target2.setDataArray(tuple(col2))
target3.setFormulaArray(tuple(col3))
target4.setDataArray(tuple(col4))
target5.setDataArray(tuple(col5))
target6.setDataArray(tuple(col6))
target7.setDataArray(tuple(col7))
target8.setDataArray(tuple(col8))
target9.setDataArray(tuple(col9))
return
def _render(self, data):
self._set_search()
self._es_pre = data.pop('es_pre', False)
self._is_ticket = data.pop('is_ticket', False)
self._currency = data['totales']['moneda']
self._pagos = data.pop('pagos', False)
self._comprobante(data['comprobante'])
self._emisor(data['emisor'])
self._receptor(data['receptor'])
self._conceptos(data['conceptos'])
if self._pagos:
self._cfdipays(data['pays'])
if 'nomina' in data and data['nomina']:
self._nomina(data['nomina'])
else:
@ -1167,6 +1271,7 @@ class LIBO(object):
self._timbre(data['timbre'])
self._donataria(data['donataria'])
self._ine(data['ine'])
self._cancelado(data['cancelada'])
self._clean()
return
@ -1444,13 +1549,17 @@ def to_pdf(data, emisor_rfc, ods=False):
if 'nomina' in data and data['nomina']:
version = '{}_{}'.format(data['nomina']['version'], version)
pagos = ''
if data.get('pagos', False):
pagos = '_pagos_'
if APP_LIBO:
app = LIBO()
if app.is_running:
donativo = ''
if data['donativo']:
donativo = '_donativo'
name = '{}_{}{}.ods'.format(rfc.lower(), version, donativo)
name = '{}_{}{}{}.ods'.format(rfc.lower(), pagos, version, donativo)
path = get_template_ods(name)
if path:
return app.pdf(path, data, ods)
@ -1553,6 +1662,7 @@ def _comprobante(doc, options):
'I': 'ingreso',
'E': 'egreso',
'T': 'traslado',
'P': 'pago',
}
data['tipodecomprobante'] = tipos.get(data['tipodecomprobante'])
data['lugarexpedicion'] = \
@ -1854,6 +1964,27 @@ def _nomina(doc, data, values, version_cfdi):
return info
def _cfdipays(doc, data, version):
node = doc.find('{}Complemento/{}Pagos'.format(PRE[version], PRE['pagos']))
if node is None:
return {}
info = CaseInsensitiveDict(node.attrib.copy())
related = []
for n1 in node:
info.update(CaseInsensitiveDict(n1.attrib.copy()))
for n2 in n1:
related.append(CaseInsensitiveDict(n2.attrib.copy()))
info['related'] = related
data['comprobante']['totalenletras'] = to_letters(
float(info['monto']), info['monedap'])
data['comprobante']['moneda'] = info['monedap']
return info
def get_data_from_xml(invoice, values):
data = {'cancelada': invoice.cancelada, 'donativo': False}
if hasattr(invoice, 'donativo'):
@ -1878,6 +2009,9 @@ def get_data_from_xml(invoice, values):
data['comprobante'].update(data['timbre'])
data['nomina'] = _nomina(doc, data, values, version)
data['pagos'] = values.get('pagos', False)
if data['pagos']:
data['pays'] = _cfdipays(doc, data, version)
return data

View File

@ -5364,7 +5364,7 @@ class CfdiPagos(BaseModel):
Facturas.folio.alias('Folio'),
Facturas.moneda.alias('MonedaDR'),
# ~ Facturas.tipo_cambio.alias('TipoCambioDR'),
Facturas.metodo_pago.alias('MetodoDePagoDR'),
# ~ Facturas.metodo_pago.alias('MetodoDePagoDR'),
FacturasPagos.numero.alias('NumParcialidad'),
FacturasPagos.saldo_anterior.alias('ImpSaldoAnt'),
FacturasPagos.importe.alias('ImpPagado'),
@ -5379,6 +5379,7 @@ class CfdiPagos(BaseModel):
r['Folio'] = str(r['Folio'])
r['NumParcialidad'] = str(r['NumParcialidad'])
# ~ r['TipoCambioDR'] = FORMAT.format(r['TipoCambioDR'])
r['MetodoDePagoDR'] = 'PDD'
r['ImpSaldoAnt'] = FORMAT.format(r['ImpSaldoAnt'])
r['ImpPagado'] = FORMAT.format(r['ImpPagado'])
r['ImpSaldoInsoluto'] = FORMAT.format(r['ImpSaldoInsoluto'])
@ -5523,6 +5524,32 @@ class CfdiPagos(BaseModel):
name = '{}{}_{}.xml'.format(obj.serie, folio, obj.socio.rfc)
return obj.xml, name
def _get_not_in_xml(self, invoice, emisor):
values = {}
values['notas'] = invoice.notas
values['fechadof'] = None
obj = SATRegimenes.get(SATRegimenes.key==invoice.regimen_fiscal)
values['regimenfiscal'] = str(obj)
obj = SATUsoCfdi.get(SATUsoCfdi.key=='P01')
values['usocfdi'] = str(obj)
values['moneda'] = 'XXX'
if invoice.tipo_relacion:
obj = SATTipoRelacion.get(SATTipoRelacion.key==invoice.tipo_relacion)
values['tiporelacion'] = str(obj)
receptor = Socios.select().where(Socios.id==invoice.socio.id).dicts()[0]
values['receptor'] = {}
for k, v in receptor.items():
values['receptor'][k] = v
values['pagos'] = True
return values
@classmethod
def get_file_pdf(cls, id):
try:
@ -5537,12 +5564,13 @@ class CfdiPagos(BaseModel):
if obj.uuid is None:
return b'', name
# ~ values = cls._get_not_in_xml(cls, obj, emisor)
data = util.get_data_from_xml(obj, {})
print(data)
# ~ doc = util.to_pdf(data, emisor.rfc)
values = cls._get_not_in_xml(cls, obj, emisor)
data = util.get_data_from_xml(obj, values)
obj = SATFormaPago.get(SATFormaPago.key==data['pays']['FormaDePagoP'])
data['pays']['formadepago'] = '{} ({})'.format(obj.name, obj.key)
doc = util.to_pdf(data, emisor.rfc)
return b'', name
return doc, name
@classmethod
def get_values(cls, values):

View File

@ -132,7 +132,8 @@ PRE = {
'NOMINA': {
'1.1': '{http://www.sat.gob.mx/nomina}',
'1.2': '{http://www.sat.gob.mx/nomina12}',
}
},
'pagos': '{http://www.sat.gob.mx/Pagos}',
}
CURRENT_CFDI = '3.3'

Binary file not shown.