forked from elmau/empresa-libre
Merge branch 'pagos' into develop
Soporte para complemento de pagos
This commit is contained in:
commit
b202827ee0
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,3 +1,17 @@
|
|||
v 1.12.0 [31-ago-2018]
|
||||
----------------------
|
||||
- Soporte para facturas (complemento) de pago.
|
||||
|
||||
* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal.
|
||||
|
||||
```
|
||||
git pull origin master
|
||||
|
||||
cd source/app/models
|
||||
|
||||
python main.py -m
|
||||
```
|
||||
|
||||
v 1.11.1 [21-ago-2018]
|
||||
----------------------
|
||||
- Fix - Quitar columna en tabla facturaspagos.
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ~ Empresa Libre
|
||||
# ~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
# ~ the Free Software Foundation, either version 3 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 General Public License for more details.
|
||||
# ~
|
||||
# ~ You should have received a copy of the GNU General Public License
|
||||
# ~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import datetime
|
||||
from xml.etree import ElementTree as ET
|
||||
|
@ -6,8 +22,6 @@ from xml.dom.minidom import parseString
|
|||
|
||||
from logbook import Logger
|
||||
|
||||
#~ from settings import DEBUG
|
||||
|
||||
|
||||
log = Logger('XML')
|
||||
CFDI_ACTUAL = 'cfdi33'
|
||||
|
@ -64,6 +78,12 @@ SAT = {
|
|||
'xmlns': 'http://www.sat.gob.mx/iedu',
|
||||
'schema': ' http://www.sat.gob.mx/iedu http://www.sat.gob.mx/sitio_internet/cfd/ine/iedu.xsd',
|
||||
},
|
||||
'pagos': {
|
||||
'version': '1.0',
|
||||
'prefix': 'pago10',
|
||||
'xmlns': 'http://www.sat.gob.mx/Pagos',
|
||||
'schema': ' http://www.sat.gob.mx/Pagos http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos10.xsd',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,6 +99,7 @@ class CFDI(object):
|
|||
self._donativo = False
|
||||
self._ine = False
|
||||
self._edu = False
|
||||
self._pagos = False
|
||||
self._is_nomina = False
|
||||
self.error = ''
|
||||
|
||||
|
@ -129,6 +150,7 @@ class CFDI(object):
|
|||
if datos['complementos']:
|
||||
if 'ine' in datos['complementos']:
|
||||
self._ine = True
|
||||
self._pagos = bool(datos['complementos'].get('pagos', False))
|
||||
|
||||
if 'nomina' in datos:
|
||||
self._is_nomina = True
|
||||
|
@ -174,9 +196,15 @@ class CFDI(object):
|
|||
attributes[name] = SAT['nomina']['xmlns']
|
||||
schema_nomina = SAT['nomina']['schema']
|
||||
|
||||
schema_pagos = ''
|
||||
if self._pagos:
|
||||
name = 'xmlns:{}'.format(SAT['pagos']['prefix'])
|
||||
attributes[name] = SAT['pagos']['xmlns']
|
||||
schema_pagos = SAT['pagos']['schema']
|
||||
|
||||
attributes['xsi:schemaLocation'] = self._sat_cfdi['schema'] + \
|
||||
schema_locales + schema_donativo + schema_ine + schema_edu + \
|
||||
schema_nomina
|
||||
schema_nomina + schema_pagos
|
||||
attributes.update(datos)
|
||||
|
||||
if not 'Version' in attributes:
|
||||
|
@ -403,6 +431,17 @@ class CFDI(object):
|
|||
atributos.update(datos['ine'])
|
||||
ET.SubElement(self._complemento, 'ine:INE', atributos)
|
||||
|
||||
if 'pagos' in datos:
|
||||
datos = datos.pop('pagos')
|
||||
relacionados = datos.pop('relacionados')
|
||||
pre = SAT['pagos']['prefix']
|
||||
attributes = {'Version': SAT['pagos']['version']}
|
||||
pagos = ET.SubElement(
|
||||
self._complemento, '{}:Pagos'.format(pre), attributes)
|
||||
node_pago = ET.SubElement(pagos, '{}:Pago'.format(pre), datos)
|
||||
for row in relacionados:
|
||||
ET.SubElement(node_pago, '{}:DoctoRelacionado'.format(pre), row)
|
||||
|
||||
if 'ce' in datos:
|
||||
pre = 'cce11'
|
||||
datos = datos.pop('ce')
|
||||
|
|
|
@ -514,3 +514,31 @@ class AppDocumentos(object):
|
|||
'attachment; filename={}'.format(file_name))
|
||||
resp.content_type = content_type
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
# ~ Revisado
|
||||
class AppInvoicePay(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_invoicepay(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
class AppCfdiPay(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self._db = db
|
||||
|
||||
def on_get(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.get_cfdipay(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
def on_post(self, req, resp):
|
||||
values = req.params
|
||||
req.context['result'] = self._db.cfdipay(values)
|
||||
resp.status = falcon.HTTP_200
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@ from controllers.main import (AppEmpresas,
|
|||
AppLogin, AppLogout, AppAdmin, AppEmisor, AppConfig,
|
||||
AppMain, AppValues, AppPartners, AppProducts, AppInvoices, AppFolios,
|
||||
AppDocumentos, AppFiles, AppPreInvoices, AppCuentasBanco,
|
||||
AppMovimientosBanco, AppTickets, AppStudents, AppEmployees, AppNomina
|
||||
AppMovimientosBanco, AppTickets, AppStudents, AppEmployees, AppNomina,
|
||||
AppInvoicePay, AppCfdiPay
|
||||
)
|
||||
|
||||
|
||||
|
@ -55,6 +56,8 @@ api.add_route('/movbanco', AppMovimientosBanco(db))
|
|||
api.add_route('/students', AppStudents(db))
|
||||
api.add_route('/employees', AppEmployees(db))
|
||||
api.add_route('/nomina', AppNomina(db))
|
||||
api.add_route('/invoicepay', AppInvoicePay(db))
|
||||
api.add_route('/cfdipay', AppCfdiPay(db))
|
||||
|
||||
|
||||
# ~ Activa si usas waitress y NO estas usando servidor web
|
||||
|
|
|
@ -412,3 +412,13 @@ class StorageEngine(object):
|
|||
|
||||
def importar_bdfl(self):
|
||||
return main.importar_bdfl()
|
||||
|
||||
# ~ Revisado
|
||||
def get_invoicepay(self, values):
|
||||
return main.FacturasPagos.get_values(values)
|
||||
|
||||
def get_cfdipay(self, values):
|
||||
return main.CfdiPagos.get_values(values)
|
||||
|
||||
def cfdipay(self, values):
|
||||
return main.CfdiPagos.post(values)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ~ Empresa Libre
|
||||
# ~ Copyright (C) 2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
# ~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
|
@ -34,7 +34,8 @@ from controllers import util
|
|||
from settings import log, DEBUG, VERSION, PATH_CP, COMPANIES, PRE, CURRENT_CFDI, \
|
||||
INIT_VALUES, DEFAULT_PASSWORD, DECIMALES, IMPUESTOS, DEFAULT_SAT_PRODUCTO, \
|
||||
CANCEL_SIGNATURE, PUBLIC, DEFAULT_SERIE_TICKET, CURRENT_CFDI_NOMINA, \
|
||||
DEFAULT_SAT_NOMINA, DECIMALES_TAX, TITLE_APP, MV, DECIMALES_PRECIOS
|
||||
DEFAULT_SAT_NOMINA, DECIMALES_TAX, TITLE_APP, MV, DECIMALES_PRECIOS, \
|
||||
DEFAULT_SERIE_CFDIPAY, DEFAULT_TYPE_CFDIPAY
|
||||
|
||||
|
||||
FORMAT = '{0:.2f}'
|
||||
|
@ -213,6 +214,10 @@ def get_doc(type_doc, id, rfc):
|
|||
data, file_name = util.get_log('nomina')
|
||||
elif type_doc == 'nompdf':
|
||||
data, file_name = CfdiNomina.get_pdf(id, rfc)
|
||||
elif type_doc == 'xmlpago':
|
||||
data, file_name = CfdiPagos.get_file_xml(id)
|
||||
elif type_doc == 'pdfpago':
|
||||
data, file_name = CfdiPagos.get_file_pdf(id)
|
||||
|
||||
return data, file_name, content_type
|
||||
|
||||
|
@ -891,10 +896,15 @@ class Certificado(BaseModel):
|
|||
rfc = TextField(default='')
|
||||
desde = DateTimeField(null=True)
|
||||
hasta = DateTimeField(null=True)
|
||||
es_fiel = BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return self.serie
|
||||
|
||||
@classmethod
|
||||
def get_cert(cls, is_fiel=False):
|
||||
return Certificado.get(Certificado.es_fiel==is_fiel)
|
||||
|
||||
@classmethod
|
||||
def get_data(cls):
|
||||
obj = cls.get_(cls)
|
||||
|
@ -1933,11 +1943,13 @@ class MovimientosBanco(BaseModel):
|
|||
.select(
|
||||
MovimientosBanco.id,
|
||||
MovimientosBanco.fecha,
|
||||
SATFormaPago.name.alias('way_payment'),
|
||||
MovimientosBanco.numero_operacion,
|
||||
MovimientosBanco.descripcion,
|
||||
MovimientosBanco.retiro,
|
||||
MovimientosBanco.deposito,
|
||||
MovimientosBanco.saldo)
|
||||
.join(SATFormaPago).switch(MovimientosBanco)
|
||||
.where(filtros)
|
||||
.dicts()
|
||||
)
|
||||
|
@ -1945,21 +1957,6 @@ class MovimientosBanco(BaseModel):
|
|||
return {'ok': True, 'rows': rows}
|
||||
|
||||
|
||||
class CfdiPagos(BaseModel):
|
||||
movimiento = ForeignKeyField(MovimientosBanco)
|
||||
fecha = DateTimeField(default=util.now, formats=['%Y-%m-%d %H:%M:%S'])
|
||||
fecha_timbrado = DateTimeField(null=True)
|
||||
xml = TextField(default='')
|
||||
uuid = UUIDField(null=True)
|
||||
estatus = TextField(default='Guardado')
|
||||
estatus_sat = TextField(default='')
|
||||
notas = TextField(default='')
|
||||
cancelado = BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
order_by = ('movimiento',)
|
||||
|
||||
|
||||
class SATUsoCfdi(BaseModel):
|
||||
key = TextField(index=True, unique=True)
|
||||
name = TextField(default='', index=True)
|
||||
|
@ -5220,6 +5217,366 @@ class FacturasPagos(BaseModel):
|
|||
cls._actualizar_saldo_cliente(cls, fac.cliente, importe * -1)
|
||||
return
|
||||
|
||||
def _get_related(self, values):
|
||||
id = int(values['id'])
|
||||
filters = (FacturasPagos.movimiento==id)
|
||||
|
||||
rows = tuple(FacturasPagos
|
||||
.select(
|
||||
Facturas.id,
|
||||
Facturas.serie,
|
||||
Facturas.folio,
|
||||
Facturas.uuid,
|
||||
Facturas.fecha,
|
||||
Facturas.tipo_comprobante,
|
||||
Facturas.estatus,
|
||||
Socios.nombre.alias('cliente'),
|
||||
Facturas.total,
|
||||
FacturasPagos.saldo,
|
||||
FacturasPagos.importe,
|
||||
)
|
||||
.join(Facturas).switch(FacturasPagos)
|
||||
.join(Socios, on=(Facturas.cliente==Socios.id))
|
||||
.where(filters)
|
||||
.dicts()
|
||||
)
|
||||
|
||||
return {'ok': True, 'rows': rows}
|
||||
|
||||
@classmethod
|
||||
def get_values(cls, values):
|
||||
opt = values.pop('opt')
|
||||
return getattr(cls, '_get_{}'.format(opt))(cls, values)
|
||||
|
||||
|
||||
class CfdiPagos(BaseModel):
|
||||
movimiento = ForeignKeyField(MovimientosBanco)
|
||||
socio = ForeignKeyField(Socios)
|
||||
serie = TextField(default='')
|
||||
folio = IntegerField(default=0)
|
||||
fecha = DateTimeField(default=util.now, formats=['%Y-%m-%d %H:%M:%S'])
|
||||
fecha_timbrado = DateTimeField(null=True)
|
||||
tipo_comprobante = TextField(default=DEFAULT_TYPE_CFDIPAY)
|
||||
lugar_expedicion = TextField(default='')
|
||||
regimen_fiscal = TextField(default='')
|
||||
tipo_relacion = TextField(default='')
|
||||
uuid_relacionado = UUIDField(null=True)
|
||||
xml = TextField(default='')
|
||||
uuid = UUIDField(null=True)
|
||||
estatus = TextField(default='Guardada')
|
||||
estatus_sat = TextField(default='')
|
||||
notas = TextField(default='')
|
||||
error = TextField(default='')
|
||||
cancelada = BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
order_by = ('movimiento',)
|
||||
|
||||
@classmethod
|
||||
def post(cls, values):
|
||||
opt = values.pop('opt')
|
||||
return getattr(cls, '_{}'.format(opt))(cls, values)
|
||||
|
||||
def _get_folio(self, serie):
|
||||
folio = int(Configuracion.get_('txt_config_cfdipay_folio') or '0')
|
||||
start = (CfdiPagos
|
||||
.select(fn.Max(CfdiPagos.folio).alias('mf'))
|
||||
.where(CfdiPagos.serie==serie)
|
||||
.order_by(SQL('mf'))
|
||||
.scalar())
|
||||
|
||||
if start is None:
|
||||
next_folio = 1
|
||||
else:
|
||||
next_folio = start + 1
|
||||
|
||||
if folio > next_folio:
|
||||
next_folio = folio
|
||||
|
||||
return next_folio
|
||||
|
||||
def _new(self, values):
|
||||
id_mov = int(values['id_mov'])
|
||||
|
||||
filters = (FacturasPagos.movimiento==id_mov)
|
||||
related = FacturasPagos.select().where(filters)
|
||||
if not related:
|
||||
msg = 'El pago no tiene facturas relacionadas'
|
||||
data = {'ok': False, 'msg': msg}
|
||||
return data
|
||||
|
||||
partner = tuple(set([f.factura.cliente.id for f in related]))
|
||||
if len(partner) > 1:
|
||||
msg = 'Facturas relacionadas a diferentes clientes'
|
||||
data = {'ok': False, 'msg': msg}
|
||||
return data
|
||||
|
||||
partner = partner[0]
|
||||
partner_name = related[0].factura.cliente.nombre
|
||||
regimen_fiscal = related[0].factura.regimen_fiscal
|
||||
|
||||
filters = (
|
||||
(CfdiPagos.movimiento==id_mov) &
|
||||
(CfdiPagos.cancelado==False)
|
||||
)
|
||||
previous = CfdiPagos.select().where(filters)
|
||||
if previous:
|
||||
previous = previous[0]
|
||||
if previous.uuid:
|
||||
msg = 'Hay una factura activa, es necesario cancelarla primero'
|
||||
data = {'ok': False, 'msg': msg}
|
||||
return data
|
||||
else:
|
||||
data = {'ok': True, 'new': False}
|
||||
return data
|
||||
|
||||
emisor = Emisor.select()[0]
|
||||
serie = Configuracion.get_('txt_config_cfdipay_serie') or DEFAULT_SERIE_CFDIPAY
|
||||
fields = {}
|
||||
fields['movimiento'] = id_mov
|
||||
fields['socio'] = partner
|
||||
fields['serie'] = serie
|
||||
fields['folio'] = self._get_folio(self, serie)
|
||||
fields['lugar_expedicion'] = emisor.cp_expedicion or emisor.codigo_postal
|
||||
fields['regimen_fiscal'] = regimen_fiscal
|
||||
|
||||
with database_proxy.atomic() as txn:
|
||||
obj = CfdiPagos.create(**fields)
|
||||
|
||||
row = {
|
||||
'id': obj.id,
|
||||
'serie': obj.serie,
|
||||
'folio': obj.folio,
|
||||
'uuid': obj.uuid,
|
||||
'fecha': obj.fecha,
|
||||
'tipo_comprobante': obj.tipo_comprobante,
|
||||
'estatus': obj.estatus,
|
||||
'cliente': partner_name,
|
||||
}
|
||||
data = {'ok': True, 'row': row, 'new': True}
|
||||
return data
|
||||
|
||||
def _get_related_xml(self, id_mov, currency):
|
||||
filters = (FacturasPagos.movimiento==id_mov)
|
||||
related = tuple(FacturasPagos.select(
|
||||
Facturas.uuid.alias('IdDocumento'),
|
||||
Facturas.serie.alias('Serie'),
|
||||
Facturas.folio.alias('Folio'),
|
||||
Facturas.moneda.alias('MonedaDR'),
|
||||
# ~ Facturas.tipo_cambio.alias('TipoCambioDR'),
|
||||
# ~ Facturas.metodo_pago.alias('MetodoDePagoDR'),
|
||||
FacturasPagos.numero.alias('NumParcialidad'),
|
||||
FacturasPagos.saldo_anterior.alias('ImpSaldoAnt'),
|
||||
FacturasPagos.importe.alias('ImpPagado'),
|
||||
FacturasPagos.saldo.alias('ImpSaldoInsoluto'),
|
||||
).join(Facturas).switch(FacturasPagos)
|
||||
.where(filters)
|
||||
.dicts())
|
||||
|
||||
for r in related:
|
||||
# ~ print('\n\nMONEDA', currency, r['MonedaDR'])
|
||||
r['IdDocumento'] = str(r['IdDocumento'])
|
||||
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'])
|
||||
|
||||
return related
|
||||
|
||||
def _generate_xml(self, invoice, auth):
|
||||
emisor = Emisor.select()[0]
|
||||
cert = Certificado.get_cert()
|
||||
|
||||
cfdi = {}
|
||||
related = {}
|
||||
cfdi['Serie'] = invoice.serie
|
||||
cfdi['Folio'] = str(invoice.folio)
|
||||
cfdi['Fecha'] = invoice.fecha.isoformat()[:19]
|
||||
cfdi['NoCertificado'] = cert.serie
|
||||
cfdi['Certificado'] = cert.cer_txt
|
||||
cfdi['SubTotal'] = '0'
|
||||
cfdi['Moneda'] = 'XXX'
|
||||
cfdi['Total'] = '0'
|
||||
cfdi['TipoDeComprobante'] = invoice.tipo_comprobante
|
||||
cfdi['LugarExpedicion'] = invoice.lugar_expedicion
|
||||
|
||||
if invoice.tipo_relacion:
|
||||
related = {
|
||||
'tipo': invoice.tipo_relacion,
|
||||
'cfdis': (invoice.uuid_relacionado,),
|
||||
}
|
||||
|
||||
emisor = {
|
||||
'Rfc': emisor.rfc,
|
||||
'Nombre': emisor.nombre,
|
||||
'RegimenFiscal': invoice.regimen_fiscal,
|
||||
}
|
||||
|
||||
receptor = {
|
||||
'Rfc': invoice.socio.rfc,
|
||||
'Nombre': invoice.socio.nombre,
|
||||
'UsoCFDI': 'P01',
|
||||
}
|
||||
if invoice.socio.tipo_persona == 4:
|
||||
if invoice.socio.pais:
|
||||
receptor['ResidenciaFiscal'] = invoice.socio.pais
|
||||
if invoice.socio.id_fiscal:
|
||||
receptor['NumRegIdTrib'] = invoice.socio.id_fiscal
|
||||
|
||||
conceptos = ({
|
||||
'ClaveProdServ': '84111506',
|
||||
'Cantidad': '1',
|
||||
'ClaveUnidad': 'ACT',
|
||||
'Descripcion': 'Pago',
|
||||
'ValorUnitario': '0',
|
||||
'Importe': '0',
|
||||
},)
|
||||
|
||||
impuestos = {}
|
||||
|
||||
mov = invoice.movimiento
|
||||
currency = mov.cuenta.moneda.key
|
||||
related_docs = self._get_related_xml(self, invoice.movimiento, currency)
|
||||
pagos = {
|
||||
'FechaPago': mov.fecha.isoformat()[:19],
|
||||
'FormaDePagoP': mov.forma_pago.key,
|
||||
'MonedaP': currency,
|
||||
'Monto': FORMAT.format(mov.deposito),
|
||||
'relacionados': related_docs,
|
||||
}
|
||||
|
||||
complementos = {'pagos': pagos}
|
||||
data = {
|
||||
'comprobante': cfdi,
|
||||
'relacionados': related,
|
||||
'emisor': emisor,
|
||||
'receptor': receptor,
|
||||
'conceptos': conceptos,
|
||||
'impuestos': impuestos,
|
||||
'donativo': {},
|
||||
'edu': False,
|
||||
'complementos': complementos,
|
||||
}
|
||||
return util.make_xml(data, cert, auth)
|
||||
|
||||
def _stamp(self, values):
|
||||
id_mov = int(values['id_mov'])
|
||||
|
||||
auth = Emisor.get_auth()
|
||||
filters = (
|
||||
(CfdiPagos.movimiento==id_mov) &
|
||||
(CfdiPagos.uuid.is_null(True))
|
||||
)
|
||||
obj = CfdiPagos.get(filters)
|
||||
obj.xml = self._generate_xml(self, obj, auth)
|
||||
obj.estatus = 'Generada'
|
||||
obj.save()
|
||||
msg = 'Factura timbrada correctamente'
|
||||
result = util.timbra_xml(obj.xml, auth)
|
||||
if result['ok']:
|
||||
obj.xml = result['xml']
|
||||
obj.uuid = result['uuid']
|
||||
obj.fecha_timbrado = result['fecha']
|
||||
obj.estatus = 'Timbrada'
|
||||
obj.error = ''
|
||||
row = {'uuid': obj.uuid, 'estatus': 'Timbrada'}
|
||||
else:
|
||||
msg = result['error']
|
||||
obj.estatus = 'Error'
|
||||
obj.error = msg
|
||||
row = {'estatus': 'Error'}
|
||||
|
||||
obj.save()
|
||||
|
||||
result = {
|
||||
'ok': result['ok'],
|
||||
'msg': msg,
|
||||
'id': obj.id,
|
||||
'row': row,
|
||||
}
|
||||
return result
|
||||
|
||||
def _get_related(self, values):
|
||||
id_mov = int(values['id_mov'])
|
||||
filters = (
|
||||
(CfdiPagos.movimiento==id_mov)
|
||||
)
|
||||
rows = tuple(CfdiPagos.select(
|
||||
CfdiPagos.id,
|
||||
CfdiPagos.serie,
|
||||
CfdiPagos.folio,
|
||||
CfdiPagos.uuid,
|
||||
CfdiPagos.fecha,
|
||||
CfdiPagos.tipo_comprobante,
|
||||
CfdiPagos.estatus,
|
||||
Socios.nombre.alias('cliente'),
|
||||
).join(Socios).switch(CfdiPagos)
|
||||
.where(filters).dicts())
|
||||
return {'ok': True, 'rows': rows}
|
||||
|
||||
@classmethod
|
||||
def get_file_xml(cls, id):
|
||||
obj = CfdiPagos.get(CfdiPagos.id==id)
|
||||
folio = str(obj.folio).zfill(6)
|
||||
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:
|
||||
emisor = Emisor.select()[0]
|
||||
except IndexError:
|
||||
return b'', 'sin_datos_de_emisor.pdf'
|
||||
|
||||
obj = CfdiPagos.get(CfdiPagos.id==id)
|
||||
folio = str(obj.folio).zfill(6)
|
||||
name = '{}{}_{}.pdf'.format(obj.serie, folio, obj.socio.rfc)
|
||||
|
||||
if obj.uuid is None:
|
||||
return b'', name
|
||||
|
||||
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 doc, name
|
||||
|
||||
@classmethod
|
||||
def get_values(cls, values):
|
||||
opt = values.pop('opt')
|
||||
return getattr(cls, '_get_{}'.format(opt))(cls, values)
|
||||
|
||||
|
||||
class PreFacturasImpuestos(BaseModel):
|
||||
factura = ForeignKeyField(PreFacturas)
|
||||
|
@ -7487,6 +7844,35 @@ def _migrate_tables():
|
|||
if 'cancelado' in columns:
|
||||
migrations.append(migrator.drop_column('facturaspagos', 'cancelado'))
|
||||
|
||||
columns = [c.name for c in database_proxy.get_columns('certificado')]
|
||||
if not 'es_fiel' in columns:
|
||||
es_fiel = BooleanField(default=False)
|
||||
migrations.append(migrator.add_column('certificado', 'es_fiel', es_fiel))
|
||||
|
||||
columns = [c.name for c in database_proxy.get_columns('cfdipagos')]
|
||||
if not 'serie' in columns:
|
||||
socio = ForeignKeyField(Socios, null=True, to_field=Socios.id)
|
||||
serie = TextField(default='')
|
||||
folio = IntegerField(default=0)
|
||||
lugar_expedicion = TextField(default='')
|
||||
regimen_fiscal = TextField(default='')
|
||||
tipo_comprobante = TextField(default=DEFAULT_TYPE_CFDIPAY)
|
||||
error = TextField(default='')
|
||||
tipo_relacion = TextField(default='')
|
||||
uuid_relacionado = UUIDField(null=True)
|
||||
cancelada = BooleanField(default=False)
|
||||
migrations.append(migrator.add_column('cfdipagos', 'serie', serie))
|
||||
migrations.append(migrator.add_column('cfdipagos', 'folio', folio))
|
||||
migrations.append(migrator.add_column('cfdipagos', 'lugar_expedicion', lugar_expedicion))
|
||||
migrations.append(migrator.add_column('cfdipagos', 'regimen_fiscal', regimen_fiscal))
|
||||
migrations.append(migrator.add_column('cfdipagos', 'tipo_comprobante', tipo_comprobante))
|
||||
migrations.append(migrator.add_column('cfdipagos', 'error', error))
|
||||
migrations.append(migrator.add_column('cfdipagos', 'tipo_relacion', tipo_relacion))
|
||||
migrations.append(migrator.add_column('cfdipagos', 'uuid_relacionado', uuid_relacionado))
|
||||
migrations.append(migrator.add_column('cfdipagos', 'socio_id', socio))
|
||||
migrations.append(migrator.drop_column('cfdipagos', 'cancelado'))
|
||||
migrations.append(migrator.add_column('cfdipagos', 'cancelada', cancelada))
|
||||
|
||||
if migrations:
|
||||
with database_proxy.atomic() as txn:
|
||||
migrate(*migrations)
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ~ Empresa Libre
|
||||
# ~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
# ~
|
||||
# ~ This program is free software: you can redistribute it and/or modify
|
||||
# ~ it under the terms of the GNU General Public License as published by
|
||||
# ~ the Free Software Foundation, either version 3 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 General Public License for more details.
|
||||
# ~
|
||||
# ~ You should have received a copy of the GNU General Public License
|
||||
# ~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logbook
|
||||
import os
|
||||
|
@ -31,7 +47,7 @@ except ImportError:
|
|||
|
||||
|
||||
DEBUG = DEBUG
|
||||
VERSION = '1.11.1'
|
||||
VERSION = '1.12.0'
|
||||
EMAIL_SUPPORT = ('soporte@empresalibre.net',)
|
||||
TITLE_APP = '{} v{}'.format(TITLE_APP, VERSION)
|
||||
|
||||
|
@ -116,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'
|
||||
|
@ -138,6 +155,8 @@ IMPUESTOS = {
|
|||
}
|
||||
DEFAULT_SAT_PRODUCTO = '01010101'
|
||||
DEFAULT_SERIE_TICKET = 'T'
|
||||
DEFAULT_SERIE_CFDIPAY = 'FP'
|
||||
DEFAULT_TYPE_CFDIPAY = 'P'
|
||||
DIR_FACTURAS = 'facturas'
|
||||
USAR_TOKEN = False
|
||||
CANCEL_SIGNATURE = False
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
//~ Empresa Libre
|
||||
//~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
//~
|
||||
//~ This program is free software: you can redistribute it and/or modify
|
||||
//~ it under the terms of the GNU General Public License as published by
|
||||
//~ the Free Software Foundation, either version 3 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 General Public License for more details.
|
||||
//~
|
||||
//~ You should have received a copy of the GNU General Public License
|
||||
//~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
var msg = ''
|
||||
var msg_importe = ''
|
||||
|
||||
|
@ -7,6 +24,7 @@ var bancos_controllers = {
|
|||
$$('lst_cuentas_banco').attachEvent('onChange', lst_cuentas_banco_change)
|
||||
$$('cmd_agregar_retiro').attachEvent('onItemClick', cmd_agregar_retiro_click)
|
||||
$$('cmd_agregar_deposito').attachEvent('onItemClick', cmd_agregar_deposito_click)
|
||||
$$('cmd_complemento_pago').attachEvent('onItemClick', cmd_complemento_pago_click)
|
||||
$$('cmd_guardar_retiro').attachEvent('onItemClick', cmd_guardar_retiro_click)
|
||||
$$('cmd_guardar_deposito').attachEvent('onItemClick', cmd_guardar_deposito_click)
|
||||
$$('cmd_cancelar_movimiento').attachEvent('onItemClick', cmd_cancelar_movimiento_click)
|
||||
|
@ -20,6 +38,11 @@ var bancos_controllers = {
|
|||
$$('filter_cuenta_year').attachEvent('onChange', filter_cuenta_change)
|
||||
$$('filter_cuenta_month').attachEvent('onChange', filter_cuenta_change)
|
||||
$$('filter_cuenta_dates').attachEvent('onChange', filter_cuenta_dates_change)
|
||||
|
||||
$$('cmd_pay_stamp').attachEvent('onItemClick', cmd_pay_stamp_click)
|
||||
$$('cmd_pay_cancel').attachEvent('onItemClick', cmd_pay_cancel_click)
|
||||
$$('grid_cfdi_pay').attachEvent('onItemClick', grid_cfdi_pay_click)
|
||||
|
||||
set_year_month()
|
||||
}
|
||||
}
|
||||
|
@ -666,8 +689,202 @@ function filter_cuenta_change(){
|
|||
get_estado_cuenta()
|
||||
}
|
||||
|
||||
|
||||
function filter_cuenta_dates_change(range){
|
||||
if(range.start != null && range.end != null){
|
||||
get_estado_cuenta(range)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function set_data_pay(row){
|
||||
var form = $$('form_bank_pay')
|
||||
var dt = row.fecha.split(' ')
|
||||
var grid = $$('grid_pay_related')
|
||||
grid.clearAll()
|
||||
|
||||
set_way_payment('pay_way_payment')
|
||||
var wp = table_waypayment.findOne({'value': row.way_payment})
|
||||
|
||||
form.setValues({
|
||||
id_mov: row.id,
|
||||
pay_date: dt[0],
|
||||
pay_time: dt[1],
|
||||
pay_reference: row.numero_operacion,
|
||||
pay_way_payment: wp.id,
|
||||
pay_import: row.deposito,
|
||||
pay_description: row.descripcion
|
||||
})
|
||||
|
||||
webix.ajax().get('/invoicepay', {'opt': 'related', 'id': row.id}, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
var values = data.json()
|
||||
if(values.ok){
|
||||
grid.parse(values.rows, 'json')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
$$('grid_cfdi_pay').clearAll()
|
||||
webix.ajax().get('/cfdipay', {'opt': 'related', 'id_mov': row.id}, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
var values = data.json()
|
||||
if(values.ok){
|
||||
$$('grid_cfdi_pay').parse(values.rows, 'json')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function cmd_complemento_pago_click(){
|
||||
var grid = $$('grid_cuentabanco')
|
||||
|
||||
var row = grid.getSelectedItem()
|
||||
if(row == undefined){
|
||||
msg_error('Selecciona un movimiento de depósito')
|
||||
return
|
||||
}
|
||||
if(row.descripcion == 'Saldo inicial'){
|
||||
msg_error('No es posible generar un pago del Saldo Inicial')
|
||||
return
|
||||
}
|
||||
if(row.deposito == 0){
|
||||
msg_error('Selecciona un movimiento de depósito')
|
||||
return
|
||||
}
|
||||
|
||||
set_data_pay(row)
|
||||
$$('multi_bancos').setValue('bank_pay')
|
||||
}
|
||||
|
||||
|
||||
function validate_cfdi_pay(form){
|
||||
if(!form.validate()) {
|
||||
msg_error('Valores inválidos')
|
||||
return false
|
||||
}
|
||||
|
||||
var grid = $$('grid_pay_related')
|
||||
if(grid.count() == 0){
|
||||
msg_error('El depósito no tiene facturas relacionadas')
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
function update_grid_cfdi_pay(row){
|
||||
var g = $$('grid_cfdi_pay')
|
||||
|
||||
g.add(result.row)
|
||||
if (g.count() == 1){
|
||||
g.adjustColumn('index')
|
||||
g.adjustColumn('serie')
|
||||
g.adjustColumn('folio')
|
||||
g.adjustColumn('fecha')
|
||||
g.adjustColumn('cliente')
|
||||
g.adjustColumn('xml')
|
||||
g.adjustColumn('pdf')
|
||||
g.adjustColumn('email')
|
||||
}
|
||||
}
|
||||
|
||||
function send_stamp_cfdi_pay(id_mov){
|
||||
var g = $$('grid_cfdi_pay')
|
||||
var data = {'opt': 'stamp', 'id_mov': id_mov}
|
||||
|
||||
webix.ajax().sync().post('cfdipay', data, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
result = data.json();
|
||||
if(result.ok){
|
||||
g.updateItem(result.id, result.row)
|
||||
msg_ok(result.msg)
|
||||
}else{
|
||||
msg_error(result.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function save_cfdi_pay(form){
|
||||
var values = form.getValues()
|
||||
var data = {'opt': 'new', 'id_mov': values.id_mov}
|
||||
|
||||
webix.ajax().sync().post('cfdipay', data, {
|
||||
error:function(text, data, XmlHttpRequest){
|
||||
msg = 'Ocurrio un error, consulta a soporte técnico'
|
||||
msg_error(msg)
|
||||
},
|
||||
success:function(text, data, XmlHttpRequest){
|
||||
result = data.json();
|
||||
if(result.ok){
|
||||
if(result.new){
|
||||
msg_ok('Factura guardada correctamente<BR>Enviando a timbrar...')
|
||||
update_grid_cfdi_pay(result.row)
|
||||
}else{
|
||||
msg_ok('Enviando a timbrar...')
|
||||
}
|
||||
send_stamp_cfdi_pay(values.id_mov)
|
||||
}else{
|
||||
msg_error(result.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_pay_stamp_click(){
|
||||
var form = $$('form_bank_pay')
|
||||
var title = 'Timbrar Factura de Pago'
|
||||
msg = '¿Estás seguro de enviar a timbrar este pago?'
|
||||
|
||||
if (!validate_cfdi_pay(form)){
|
||||
return
|
||||
}
|
||||
|
||||
webix.confirm({
|
||||
title: title,
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
save_cfdi_pay(form)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_pay_cancel_click(){
|
||||
}
|
||||
|
||||
|
||||
function grid_cfdi_pay_click(id, e, node){
|
||||
var row = this.getItem(id)
|
||||
|
||||
if(id.column == 'xml'){
|
||||
location = '/doc/xmlpago/' + row.id
|
||||
}else if(id.column == 'pdf'){
|
||||
window.open('/doc/pdfpago/' + row.id, '_blank')
|
||||
}else if(id.column == 'email'){
|
||||
//~ enviar_correo(row)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ function configuracion_inicial(){
|
|||
add_config({'key': 'decimales_precios', 'value': values.decimales_precios})
|
||||
})
|
||||
|
||||
get_way_payment()
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
//~ Empresa Libre
|
||||
//~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
//~
|
||||
//~ This program is free software: you can redistribute it and/or modify
|
||||
//~ it under the terms of the GNU General Public License as published by
|
||||
//~ the Free Software Foundation, either version 3 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 General Public License for more details.
|
||||
//~
|
||||
//~ You should have received a copy of the GNU General Public License
|
||||
//~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
var PUBLICO = "Público en general";
|
||||
var RFC_PUBLICO = "XAXX010101000";
|
||||
var RFC_EXTRANJERO = "XEXX010101000";
|
||||
|
@ -16,6 +33,7 @@ var table_totals = db.addCollection('totals', {unique: ['tax']})
|
|||
var table_series = db.addCollection('series')
|
||||
var table_usocfdi = db.addCollection('usocfdi')
|
||||
var table_relaciones = db.addCollection('relaciones')
|
||||
var table_waypayment = db.addCollection('waypayment')
|
||||
|
||||
var msg = ''
|
||||
|
||||
|
@ -408,6 +426,21 @@ function get_forma_pago(control){
|
|||
}
|
||||
|
||||
|
||||
function get_way_payment(){
|
||||
webix.ajax().get('/values/formapago', {key: true}, function(text, data){
|
||||
var values = data.json()
|
||||
table_waypayment.clear()
|
||||
table_waypayment.insert(values)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function set_way_payment(control){
|
||||
var values = table_waypayment.chain().data()
|
||||
$$(control).getList().parse(values)
|
||||
}
|
||||
|
||||
|
||||
function validate_regexp(value, pattern){
|
||||
re = new RegExp(pattern, 'i');
|
||||
if(value.match(re)){
|
||||
|
@ -443,3 +476,7 @@ function pause(milliseconds) {
|
|||
var dt = new Date();
|
||||
while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
|
||||
}
|
||||
|
||||
|
||||
//~ Revisado
|
||||
|
||||
|
|
|
@ -233,18 +233,38 @@ var emisor_otros_datos= [
|
|||
]
|
||||
|
||||
|
||||
var emisor_certificado = [
|
||||
var col_sello = {rows: [
|
||||
{template: 'Certificado actual', type: 'section'},
|
||||
{view: 'form', id: 'form_cert', rows: [
|
||||
{cols: [{view: 'text', id: 'cert_rfc', name: 'cert_rfc',
|
||||
label: 'RFC: ', readonly: true, placeholder: 'Ninguno'}, {}]},
|
||||
label: 'RFC: ', readonly: true, placeholder: 'Ninguno'}]},
|
||||
{cols: [{view: 'text', id: 'cert_serie', name: 'cert_serie',
|
||||
label: 'Serie: ', readonly: true, placeholder: 'Ninguno'}, {}]},
|
||||
label: 'Serie: ', readonly: true, placeholder: 'Ninguno'}]},
|
||||
{cols: [{view: 'text', id: 'cert_desde', name: 'cert_desde',
|
||||
label: 'Vigente desde: ', readonly: true}, {}]},
|
||||
label: 'Vigente desde: ', readonly: true}]},
|
||||
{cols: [{view: 'text', id: 'cert_hasta', name: 'cert_hasta',
|
||||
label: 'Vigente hasta: ', readonly: true}, {}]},
|
||||
]},
|
||||
label: 'Vigente hasta: ', readonly: true}]},
|
||||
]}
|
||||
]}
|
||||
|
||||
|
||||
var col_fiel = {rows: [
|
||||
{template: 'Fiel actual', type: 'section'},
|
||||
{view: 'form', id: 'form_fiel', rows: [
|
||||
{cols: [{view: 'text', id: 'fiel_rfc', name: 'fiel_rfc',
|
||||
label: 'RFC: ', readonly: true, placeholder: 'Ninguno'}]},
|
||||
{cols: [{view: 'text', id: 'fiel_serie', name: 'fiel_serie',
|
||||
label: 'Serie: ', readonly: true, placeholder: 'Ninguno'}]},
|
||||
{cols: [{view: 'text', id: 'fiel_desde', name: 'fiel_desde',
|
||||
label: 'Vigente desde: ', readonly: true}]},
|
||||
{cols: [{view: 'text', id: 'fiel_hasta', name: 'fiel_hasta',
|
||||
label: 'Vigente hasta: ', readonly: true}]},
|
||||
]}
|
||||
]}
|
||||
|
||||
|
||||
var emisor_certificado = [
|
||||
{cols: [col_sello, col_fiel]},
|
||||
{template: 'Cargar Certificado', type: 'section'},
|
||||
{view: 'form', id: 'form_upload', rows: [
|
||||
{cols: [{},
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
//~ Empresa Libre
|
||||
//~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
//~
|
||||
//~ This program is free software: you can redistribute it and/or modify
|
||||
//~ it under the terms of the GNU General Public License as published by
|
||||
//~ the Free Software Foundation, either version 3 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 General Public License for more details.
|
||||
//~
|
||||
//~ You should have received a copy of the GNU General Public License
|
||||
//~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
var toolbar_banco = [
|
||||
|
@ -26,6 +41,9 @@ var toolbar_movimientos_banco = [
|
|||
{view: 'button', id: 'cmd_agregar_deposito', label: 'Depósito',
|
||||
type: 'iconButton', autowidth: true, icon: 'plus'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_complemento_pago', label: 'Factura de Pago',
|
||||
type: 'iconButton', autowidth: true, icon: 'file-code-o'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_cancelar_movimiento', label: 'Cancelar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ban'},
|
||||
]
|
||||
|
@ -35,6 +53,7 @@ var grid_cuentabanco_cols = [
|
|||
{id: 'id', header:'ID', hidden: true},
|
||||
{id: 'fecha', header: 'Fecha', width: 150},
|
||||
{id: 'numero_operacion', header: 'Referencia'},
|
||||
{id: 'way_payment', header: 'Forma de Pago', hidden: true},
|
||||
{id: 'descripcion', header: ['Descripción', {content: 'textFilter'}],
|
||||
fillspace:true},
|
||||
{id: 'retiro', header: ['Retiro', {content: 'numberFilter'}],
|
||||
|
@ -95,6 +114,49 @@ var grid_cfdi_este_deposito_cols = [
|
|||
]
|
||||
|
||||
|
||||
var grid_cfdi_pay_cols = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
||||
footer: {content: 'countRows', colspan: 3, css: 'right'}},
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: 'serie', header: ["Serie"], adjust: "data", sort: 'string'},
|
||||
{id: 'folio', header: ['Folio'], adjust: 'data',
|
||||
sort: 'int', css: 'right', footer: {text: 'Facturas', colspan: 3}},
|
||||
{id: "uuid", header: ["UUID"], adjust: "data",
|
||||
sort:"string", hidden:true},
|
||||
{id: "fecha", header: ["Fecha y Hora"],
|
||||
adjust: "data", sort: "string"},
|
||||
{id: "tipo_comprobante", header: ["Tipo"],
|
||||
adjust: 'header', sort: 'string'},
|
||||
{id: "estatus", header: ["Estatus"],
|
||||
adjust: "data", sort:"string"},
|
||||
{id: 'cliente', header: ['Razón Social'], fillspace: true},
|
||||
{id: 'xml', header: 'XML', adjust: 'data', template: get_icon('xml')},
|
||||
{id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')},
|
||||
{id: 'email', header: '', adjust: 'data', template: get_icon('email')}
|
||||
]
|
||||
|
||||
|
||||
var grid_pay_related_cols = [
|
||||
{id: 'index', header: '#', adjust: 'data', css: 'right'},
|
||||
{id: 'id', header: 'ID', hidden: true},
|
||||
{id: 'serie', header: 'Serie', adjust: 'data'},
|
||||
{id: 'folio', header: 'Folio', adjust: 'data', css: 'right'},
|
||||
{id: 'uuid', header: 'UUID', width: 250, hidden: true},
|
||||
{id: 'fecha', header: 'Fecha y Hora', width: 150, sort: 'date'},
|
||||
{id: 'tipo_comprobante', header: 'Tipo', adjust: 'data'},
|
||||
{id: 'estatus', header: 'Estatus', adjust: 'header'},
|
||||
{id: 'cliente', header: ['Razón Social'], fillspace: true},
|
||||
{id: 'total', header: ['Total'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: 'saldo', header: ['Saldo'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right', css: 'right',
|
||||
footer: 'Importe Depósito'},
|
||||
{id: 'importe', header: ['Este pago'], width: 125, sort: 'int',
|
||||
format: webix.i18n.priceFormat, css: 'right',
|
||||
footer: {content: 'summColumn', css: 'right'}},
|
||||
]
|
||||
|
||||
|
||||
var grid_cfdi_por_pagar = {
|
||||
view: 'datatable',
|
||||
id: 'grid_cfdi_por_pagar',
|
||||
|
@ -139,6 +201,47 @@ var grid_cfdi_este_deposito = {
|
|||
}
|
||||
|
||||
|
||||
var grid_cfdi_pay = {
|
||||
view: 'datatable',
|
||||
id: 'grid_cfdi_pay',
|
||||
select: 'row',
|
||||
autoConfig: false,
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
columns: grid_cfdi_pay_cols,
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var grid_pay_related = {
|
||||
view: 'datatable',
|
||||
id: 'grid_pay_related',
|
||||
select: 'row',
|
||||
autoConfig: false,
|
||||
adjust: true,
|
||||
autoheight: true,
|
||||
resizeColumn: true,
|
||||
headermenu: true,
|
||||
footer: true,
|
||||
columns: grid_pay_related_cols,
|
||||
on:{
|
||||
'data->onStoreUpdated':function(){
|
||||
this.data.each(function(obj, i){
|
||||
obj.index = i + 1
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var toolbar_banco_retiro = [
|
||||
{view: 'label', label: 'Agregar retiro de banco'},
|
||||
{},
|
||||
|
@ -159,6 +262,19 @@ var toolbar_banco_deposito = [
|
|||
]
|
||||
|
||||
|
||||
var toolbar_bank_pay = [
|
||||
{view: 'label', label: 'Factura de pago'},
|
||||
{},
|
||||
{view: 'button', id: 'cmd_pay_stamp', label: 'Timbrar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ticket'},
|
||||
{view: 'button', id: 'cmd_pay_cancel', label: 'Cancelar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ban'},
|
||||
{},
|
||||
{view: 'icon', click: '$$("multi_bancos").setValue("banco_home")',
|
||||
icon: 'times-circle'}
|
||||
]
|
||||
|
||||
|
||||
var controls_banco_retiro = [
|
||||
{view: 'toolbar', elements: toolbar_banco_retiro},
|
||||
{cols: [
|
||||
|
@ -229,6 +345,41 @@ var controls_banco_deposito = [
|
|||
]
|
||||
|
||||
|
||||
var controls_bank_pay = [
|
||||
{view: 'toolbar', elements: toolbar_bank_pay},
|
||||
{view: 'label', label: '<b>Este depósito: </b>'},
|
||||
{cols: [
|
||||
{view: 'datepicker', id: 'pay_date', name: 'pay_date',
|
||||
label: 'Fecha', format: '%d-%M-%Y', labelAlign: 'right',
|
||||
required: true, invalidMessage: 'Selecciona una fecha',
|
||||
labelWidth: 125, readonly: true},
|
||||
{view: 'search', id: 'pay_time', name: 'pay_time', label: 'Hora',
|
||||
icon: 'clock-o', labelAlign: 'right', required: true,
|
||||
readonly: true,
|
||||
invalidMessage: 'Captura una hora'},
|
||||
{view: 'text', id: 'pay_reference', name: 'pay_reference',
|
||||
label: 'Referencia', labelAlign: 'right', readonly: true},
|
||||
]},
|
||||
{cols: [
|
||||
{view: 'richselect', id: 'pay_way_payment', readonly: true,
|
||||
name: 'pay_way_payment', label: 'Forma de Pago', required: true,
|
||||
options: [], labelWidth: 125, labelAlign: 'right'},
|
||||
{view: 'currency', type: 'text', id: 'pay_import', name: 'pay_import',
|
||||
label: 'Importe', labelAlign: 'right', required: true, readonly: true,
|
||||
invalidMessage: 'Captura un valor númerico', inputAlign: 'right'}
|
||||
]},
|
||||
{cols: [
|
||||
{view: 'textarea', id: 'pay_description', label: 'Descripción',
|
||||
name: 'pay_description', labelAlign: 'right', required: true,
|
||||
labelWidth: 125, height: 70, readonly: true},
|
||||
]},
|
||||
{view: 'label', label: '<b>Facturas de pago de este depósito: </b>'},
|
||||
grid_cfdi_pay,
|
||||
{view: 'label', label: '<b>Facturas relacionadas en este pago: </b>'},
|
||||
grid_pay_related
|
||||
]
|
||||
|
||||
|
||||
var form_banco_retiro = {
|
||||
type: 'space',
|
||||
responsive: true,
|
||||
|
@ -255,6 +406,19 @@ var form_banco_deposito = {
|
|||
}
|
||||
|
||||
|
||||
var form_bank_pay = {
|
||||
type: 'space',
|
||||
responsive: true,
|
||||
cols: [{
|
||||
view: 'form',
|
||||
id: 'form_bank_pay',
|
||||
complexData: true,
|
||||
scroll: true,
|
||||
elements: controls_bank_pay,
|
||||
}],
|
||||
}
|
||||
|
||||
|
||||
var multi_bancos = {
|
||||
id: 'multi_bancos',
|
||||
animate: true,
|
||||
|
@ -266,7 +430,8 @@ var multi_bancos = {
|
|||
grid_cuentabanco,
|
||||
]},
|
||||
{id: 'banco_retiro', rows: [form_banco_retiro]},
|
||||
{id: 'banco_deposito', rows: [form_banco_deposito]}
|
||||
{id: 'banco_deposito', rows: [form_banco_deposito]},
|
||||
{id: 'bank_pay', rows: [form_bank_pay]}
|
||||
],
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//~ Empresa Libre
|
||||
//~ Copyright (C) 2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
//~ Copyright (C) 2016-2018 Mauricio Baeza Servin (web@correolibre.net)
|
||||
//~
|
||||
//~ This program is free software: you can redistribute it and/or modify
|
||||
//~ it under the terms of the GNU General Public License as published by
|
||||
|
|
Binary file not shown.
|
@ -12,6 +12,7 @@
|
|||
<xsl:include href="donat11.xslt"/>
|
||||
<xsl:include href="ine11.xslt"/>
|
||||
<xsl:include href="iedu.xslt"/>
|
||||
<xsl:include href="pagos10.xslt"/>
|
||||
<!--
|
||||
<xsl:include href="ecc11.xslt"/>
|
||||
<xsl:include href="Divisas.xslt"/>
|
||||
|
@ -30,7 +31,6 @@
|
|||
<xsl:include href="obrasarteantiguedades.xslt"/>
|
||||
<xsl:include href="ventavehiculos11.xslt"/>
|
||||
<xsl:include href="terceros11.xslt"/>
|
||||
<xsl:include href="Pagos10.xslt"/>
|
||||
-->
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:pago10="http://www.sat.gob.mx/Pagos">
|
||||
|
||||
<xsl:template match="pago10:Pagos">
|
||||
<!--Manejador de Atributos Pagos-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Version" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia -->
|
||||
<xsl:for-each select="./pago10:Pago">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="pago10:Pago">
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@FechaPago" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@FormaDePagoP" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@MonedaP" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TipoCambioP" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Monto" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumOperacion" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@RfcEmisorCtaOrd" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NomBancoOrdExt" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@CtaOrdenante" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@RfcEmisorCtaBen" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@CtaBeneficiario" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TipoCadPago" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@CertPago" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@CadPago" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@SelloPago" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de pago10:DocumentoRelacionado-->
|
||||
<xsl:for-each select="./pago10:DoctoRelacionado">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="./pago10:Impuestos">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="pago10:DoctoRelacionado">
|
||||
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@IdDocumento" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Serie" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Folio" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@MonedaDR" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TipoCambioDR" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@MetodoDePagoDR" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumParcialidad" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@ImpSaldoAnt" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@ImpPagado" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@ImpSaldoInsoluto" />
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="pago10:Impuestos">
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalImpuestosRetenidos" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalImpuestosTrasladados" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:apply-templates select="./pago10:Retenciones"/>
|
||||
<xsl:apply-templates select="./pago10:Traslados"/>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="pago10:Retenciones">
|
||||
<xsl:for-each select="./pago10:Retencion">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="pago10:Traslados">
|
||||
<xsl:for-each select="./pago10:Traslado">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="pago10:Retencion">
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Impuesto" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Importe" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="pago10:Traslado">
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Impuesto" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoFactor" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TasaOCuota" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Importe" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
Loading…
Reference in New Issue