Facturar, generar y timbrar
This commit is contained in:
parent
e9ffa41697
commit
55190c5faa
|
@ -19,4 +19,6 @@ credenciales.conf
|
|||
*.sqlite
|
||||
*.sql
|
||||
rfc.db
|
||||
configpac.py
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,308 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import datetime
|
||||
from xml.etree import ElementTree as ET
|
||||
from xml.dom.minidom import parseString
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
#~ from settings import DEBUG
|
||||
|
||||
|
||||
log = Logger('XML')
|
||||
CFDI_ACTUAL = 'cfdi33'
|
||||
NOMINA_ACTUAL = 'nomina12'
|
||||
|
||||
SAT = {
|
||||
'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'cfdi32': {
|
||||
'version': '3.2',
|
||||
'prefix': 'cfdi',
|
||||
'xmlns': 'http://www.sat.gob.mx/cfd/3',
|
||||
'schema': 'http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd',
|
||||
},
|
||||
'cfdi33': {
|
||||
'version': '3.3',
|
||||
'prefix': 'cfdi',
|
||||
'xmlns': 'http://www.sat.gob.mx/cfd/3',
|
||||
'schema': 'http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd',
|
||||
},
|
||||
'nomina11': {
|
||||
'version': '1.1',
|
||||
'prefix': 'nomina',
|
||||
'xmlns': 'http://www.sat.gob.mx/nomina',
|
||||
'schema': 'http://www.sat.gob.mx/nomina http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina11.xsd',
|
||||
},
|
||||
'nomina12': {
|
||||
'version': '1.2',
|
||||
'prefix': 'nomina',
|
||||
'xmlns': 'http://www.sat.gob.mx/nomina12',
|
||||
'schema': 'http://www.sat.gob.mx/nomina12 http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina12.xsd',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class CFDI(object):
|
||||
|
||||
def __init__(self, version=CFDI_ACTUAL):
|
||||
self._sat_cfdi = SAT[version]
|
||||
self._xsi = SAT['xsi']
|
||||
self._pre = self._sat_cfdi['prefix']
|
||||
self._cfdi = None
|
||||
self.error = ''
|
||||
|
||||
def _now(self):
|
||||
return datetime.datetime.now().isoformat()[:19]
|
||||
|
||||
def get_xml(self, datos):
|
||||
if not self._validate(datos):
|
||||
return ''
|
||||
|
||||
self._comprobante(datos['comprobante'])
|
||||
self._emisor(datos['emisor'])
|
||||
self._receptor(datos['receptor'])
|
||||
self._conceptos(datos['conceptos'])
|
||||
self._impuestos(datos['impuestos'])
|
||||
if 'nomina' in datos:
|
||||
self._nomina(datos['nomina'])
|
||||
if 'complementos' in datos:
|
||||
self._complementos(datos['complementos'])
|
||||
return self._to_pretty_xml(ET.tostring(self._cfdi, encoding='utf-8'))
|
||||
|
||||
def add_sello(self, sello):
|
||||
self._cfdi.attrib['Sello'] = sello
|
||||
return self._to_pretty_xml(ET.tostring(self._cfdi, encoding='utf-8'))
|
||||
|
||||
def _to_pretty_xml(self, source):
|
||||
tree = parseString(source)
|
||||
xml = tree.toprettyxml(encoding='utf-8').decode('utf-8')
|
||||
return xml
|
||||
|
||||
def _validate(self, datos):
|
||||
if 'nomina' in datos:
|
||||
return self._validate_nomina(datos)
|
||||
return True
|
||||
|
||||
def _validate_nomina(self, datos):
|
||||
comprobante = datos['comprobante']
|
||||
|
||||
validators = (
|
||||
('MetodoDePago', 'NA'),
|
||||
('TipoCambio', '1'),
|
||||
('Moneda', 'MXN'),
|
||||
('TipoDeComprobante', 'egreso'),
|
||||
)
|
||||
for f, v in validators:
|
||||
if f in comprobante:
|
||||
if v != comprobante[f]:
|
||||
msg = 'El atributo: {}, debe ser: {}'.format(f, v)
|
||||
self.error = msg
|
||||
return False
|
||||
return True
|
||||
|
||||
def _comprobante(self, datos):
|
||||
attributes = {}
|
||||
attributes['xmlns:{}'.format(self._pre)] = self._sat_cfdi['xmlns']
|
||||
attributes['xmlns:xsi'] = self._xsi
|
||||
attributes['xsi:schemaLocation'] = self._sat_cfdi['schema']
|
||||
attributes.update(datos)
|
||||
|
||||
#~ if DEBUG:
|
||||
#~ attributes['Fecha'] = self._now()
|
||||
#~ attributes['NoCertificado'] = CERT_NUM
|
||||
|
||||
if not 'Version' in attributes:
|
||||
attributes['Version'] = self._sat_cfdi['version']
|
||||
if not 'Fecha' in attributes:
|
||||
attributes['Fecha'] = self._now()
|
||||
|
||||
self._cfdi = ET.Element('{}:Comprobante'.format(self._pre), attributes)
|
||||
return
|
||||
|
||||
def _emisor(self, datos):
|
||||
#~ if DEBUG:
|
||||
#~ datos['Rfc'] = RFC_TEST
|
||||
|
||||
node_name = '{}:Emisor'.format(self._pre)
|
||||
emisor = ET.SubElement(self._cfdi, node_name, datos)
|
||||
return
|
||||
|
||||
def _receptor(self, datos):
|
||||
node_name = '{}:Receptor'.format(self._pre)
|
||||
emisor = ET.SubElement(self._cfdi, node_name, datos)
|
||||
return
|
||||
|
||||
def _conceptos(self, datos):
|
||||
conceptos = ET.SubElement(self._cfdi, '{}:Conceptos'.format(self._pre))
|
||||
for row in datos:
|
||||
complemento = {}
|
||||
if 'complemento' in row:
|
||||
complemento = row.pop('complemento')
|
||||
|
||||
taxes = {}
|
||||
if 'impuestos' in row:
|
||||
taxes = row.pop('impuestos')
|
||||
node_name = '{}:Concepto'.format(self._pre)
|
||||
concepto = ET.SubElement(conceptos, node_name, row)
|
||||
|
||||
if taxes:
|
||||
node_name = '{}:Impuestos'.format(self._pre)
|
||||
impuestos = ET.SubElement(concepto, node_name)
|
||||
if 'traslados' in taxes and taxes['traslados']:
|
||||
node_name = '{}:Traslados'.format(self._pre)
|
||||
traslados = ET.SubElement(impuestos, node_name)
|
||||
for traslado in taxes['traslados']:
|
||||
ET.SubElement(
|
||||
traslados, '{}:Traslado'.format(self._pre), traslado)
|
||||
if 'retenciones' in taxes and taxes['retenciones']:
|
||||
node_name = '{}:Retenciones'.format(self._pre)
|
||||
retenciones = ET.SubElement(impuestos, node_name)
|
||||
for retencion in taxes['retenciones']:
|
||||
ET.SubElement(
|
||||
retenciones, '{}:Retencion'.format(self._pre), retencion)
|
||||
|
||||
if 'InformacionAduanera' in row:
|
||||
for field in fields:
|
||||
if field in row['InformacionAduanera']:
|
||||
attributes[field] = row['InformacionAduanera'][field]
|
||||
if attributes:
|
||||
node_name = '{}:InformacionAduanera'.format(self._pre)
|
||||
ET.SubElement(concepto, node_name, attributes)
|
||||
|
||||
if 'CuentaPredial' in row:
|
||||
attributes = {'numero': row['CuentaPredial']}
|
||||
node_name = '{}:CuentaPredial'.format(self._pre)
|
||||
ET.SubElement(concepto, node_name, attributes)
|
||||
|
||||
if 'autRVOE' in row:
|
||||
fields = (
|
||||
'version',
|
||||
'nombreAlumno',
|
||||
'CURP',
|
||||
'nivelEducativo',
|
||||
'autRVOE',
|
||||
)
|
||||
for field in fields:
|
||||
if field in row['autRVOE']:
|
||||
attributes[field] = row['autRVOE'][field]
|
||||
node_name = '{}:ComplementoConcepto'.format(self._pre)
|
||||
complemento = ET.SubElement(concepto, node_name)
|
||||
ET.SubElement(complemento, 'iedu:instEducativas', attributes)
|
||||
return
|
||||
|
||||
def _impuestos(self, datos):
|
||||
if not datos:
|
||||
node_name = '{}:Impuestos'.format(self._pre)
|
||||
ET.SubElement(self._cfdi, node_name)
|
||||
return
|
||||
|
||||
attributes = {}
|
||||
fields = ('TotalImpuestosTrasladados', 'TotalImpuestosRetenidos')
|
||||
for field in fields:
|
||||
if field in datos:
|
||||
attributes[field] = datos[field]
|
||||
node_name = '{}:Impuestos'.format(self._pre)
|
||||
impuestos = ET.SubElement(self._cfdi, node_name, attributes)
|
||||
|
||||
if 'retenciones' in datos and datos['retenciones']:
|
||||
retenciones = ET.SubElement(impuestos, '{}:Retenciones'.format(self._pre))
|
||||
for row in datos['retenciones']:
|
||||
ET.SubElement(retenciones, '{}:Retencion'.format(self._pre), row)
|
||||
|
||||
if 'traslados' in datos and datos['traslados']:
|
||||
traslados = ET.SubElement(impuestos, '{}:Traslados'.format(self._pre))
|
||||
for row in datos['traslados']:
|
||||
ET.SubElement(traslados, '{}:Traslado'.format(self._pre), row)
|
||||
return
|
||||
|
||||
def _nomina(self, datos):
|
||||
sat_nomina = SAT[NOMINA_ACTUAL]
|
||||
pre = sat_nomina['prefix']
|
||||
complemento = ET.SubElement(self._cfdi, '{}:Complemento'.format(self._pre))
|
||||
|
||||
emisor = datos.pop('Emisor', None)
|
||||
receptor = datos.pop('Receptor', None)
|
||||
percepciones = datos.pop('Percepciones', None)
|
||||
deducciones = datos.pop('Deducciones', None)
|
||||
|
||||
attributes = {}
|
||||
attributes['xmlns:{}'.format(pre)] = sat_nomina['xmlns']
|
||||
attributes['xsi:schemaLocation'] = sat_nomina['schema']
|
||||
attributes.update(datos)
|
||||
|
||||
if not 'Version' in attributes:
|
||||
attributes['Version'] = sat_nomina['version']
|
||||
|
||||
nomina = ET.SubElement(complemento, '{}:Nomina'.format(pre), attributes)
|
||||
if emisor:
|
||||
ET.SubElement(nomina, '{}:Emisor'.format(pre), emisor)
|
||||
if receptor:
|
||||
ET.SubElement(nomina, '{}:Receptor'.format(pre), receptor)
|
||||
if percepciones:
|
||||
detalle = percepciones.pop('detalle', None)
|
||||
percepciones = ET.SubElement(nomina, '{}:Percepciones'.format(pre), percepciones)
|
||||
for row in detalle:
|
||||
ET.SubElement(percepciones, '{}:Percepcion'.format(pre), row)
|
||||
if deducciones:
|
||||
detalle = deducciones.pop('detalle', None)
|
||||
deducciones = ET.SubElement(nomina, '{}:Deducciones'.format(pre), deducciones)
|
||||
for row in detalle:
|
||||
ET.SubElement(deducciones, '{}:Deduccion'.format(pre), row)
|
||||
return
|
||||
|
||||
def _complementos(self, datos):
|
||||
complemento = ET.SubElement(self._cfdi, '{}:Complemento'.format(self._pre))
|
||||
if 'ce' in datos:
|
||||
pre = 'cce11'
|
||||
datos = datos.pop('ce')
|
||||
emisor = datos.pop('emisor')
|
||||
propietario = datos.pop('propietario')
|
||||
receptor = datos.pop('receptor')
|
||||
destinatario = datos.pop('destinatario')
|
||||
conceptos = datos.pop('conceptos')
|
||||
|
||||
attributes = {}
|
||||
attributes['xmlns:{}'.format(pre)] = \
|
||||
'http://www.sat.gob.mx/ComercioExterior11'
|
||||
attributes['xsi:schemaLocation'] = \
|
||||
'http://www.sat.gob.mx/ComercioExterior11 ' \
|
||||
'http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd'
|
||||
attributes.update(datos)
|
||||
ce = ET.SubElement(
|
||||
complemento, '{}:ComercioExterior'.format(pre), attributes)
|
||||
|
||||
attributes = {}
|
||||
if 'Curp' in emisor:
|
||||
attributes = {'Curp': emisor.pop('Curp')}
|
||||
node = ET.SubElement(ce, '{}:Emisor'.format(pre), attributes)
|
||||
ET.SubElement(node, '{}:Domicilio'.format(pre), emisor)
|
||||
|
||||
if propietario:
|
||||
ET.SubElement(ce, '{}:Propietario'.format(pre), propietario)
|
||||
|
||||
attributes = {}
|
||||
if 'NumRegIdTrib' in receptor:
|
||||
attributes = {'NumRegIdTrib': receptor.pop('NumRegIdTrib')}
|
||||
node = ET.SubElement(ce, '{}:Receptor'.format(pre), attributes)
|
||||
ET.SubElement(node, '{}:Domicilio'.format(pre), receptor)
|
||||
|
||||
attributes = {}
|
||||
if 'NumRegIdTrib' in destinatario:
|
||||
attributes = {'NumRegIdTrib': destinatario.pop('NumRegIdTrib')}
|
||||
if 'Nombre' in destinatario:
|
||||
attributes.update({'Nombre': destinatario.pop('Nombre')})
|
||||
node = ET.SubElement(ce, '{}:Destinatario'.format(pre), attributes)
|
||||
ET.SubElement(node, '{}:Domicilio'.format(pre), destinatario)
|
||||
|
||||
node = ET.SubElement(ce, '{}:Mercancias'.format(pre))
|
||||
fields = ('Marca', 'Modelo', 'SubModelo', 'NumeroSerie')
|
||||
for row in conceptos:
|
||||
detalle = {}
|
||||
for f in fields:
|
||||
if f in row:
|
||||
detalle[f] = row.pop(f)
|
||||
concepto = ET.SubElement(node, '{}:Mercancia'.format(pre), row)
|
||||
if detalle:
|
||||
ET.SubElement(
|
||||
concepto, '{}:DescripcionesEspecificas'.format(pre), detalle)
|
||||
return
|
|
@ -0,0 +1,609 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
#~ import re
|
||||
#~ from xml.etree import ElementTree as ET
|
||||
#~ from requests import Request, Session, exceptions
|
||||
import datetime
|
||||
import hashlib
|
||||
import os
|
||||
import requests
|
||||
import time
|
||||
from lxml import etree
|
||||
from xml.dom.minidom import parseString
|
||||
from xml.sax.saxutils import escape, unescape
|
||||
from uuid import UUID
|
||||
|
||||
from logbook import Logger
|
||||
from zeep import Client
|
||||
from zeep.plugins import HistoryPlugin
|
||||
from zeep.cache import SqliteCache
|
||||
from zeep.transports import Transport
|
||||
from zeep.exceptions import Fault, TransportError
|
||||
|
||||
from .configpac import DEBUG, TIMEOUT, AUTH, URL
|
||||
|
||||
|
||||
log = Logger('PAC')
|
||||
#~ node = client.create_message(client.service, SERVICE, **args)
|
||||
#~ print(etree.tostring(node, pretty_print=True).decode())
|
||||
|
||||
|
||||
class Ecodex(object):
|
||||
|
||||
def __init__(self):
|
||||
self.codes = URL['codes']
|
||||
self.error = ''
|
||||
self.message = ''
|
||||
self._transport = Transport(cache=SqliteCache(), timeout=TIMEOUT)
|
||||
self._plugins = None
|
||||
self._history = None
|
||||
if DEBUG:
|
||||
self._history = HistoryPlugin()
|
||||
self._plugins = [self._history]
|
||||
|
||||
def _get_token(self, rfc):
|
||||
client = Client(URL['seguridad'],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.ObtenerToken(rfc, self._get_epoch())
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
log.error(self.error)
|
||||
return ''
|
||||
|
||||
s = '{}|{}'.format(AUTH['ID'], result.Token)
|
||||
return hashlib.sha1(s.encode()).hexdigest()
|
||||
|
||||
def _get_token_rest(self, rfc):
|
||||
data = {
|
||||
'rfc': rfc,
|
||||
'grant_type': 'authorization_token',
|
||||
}
|
||||
headers = {'Content-type': 'application/x-www-form-urlencoded'}
|
||||
result = requests.post(URL['token'], data=data, headers=headers)
|
||||
data = result.json()
|
||||
s = '{}|{}'.format(AUTH['ID'], data['service_token'])
|
||||
return hashlib.sha1(s.encode()).hexdigest(), data['access_token']
|
||||
|
||||
def _validate_xml(self, xml):
|
||||
NS_CFDI = {'cfdi': 'http://www.sat.gob.mx/cfd/3'}
|
||||
if os.path.isfile(xml):
|
||||
tree = etree.parse(xml).getroot()
|
||||
else:
|
||||
tree = etree.fromstring(xml.encode())
|
||||
|
||||
fecha = tree.get('Fecha')
|
||||
rfc = tree.xpath('string(//cfdi:Emisor/@Rfc)', namespaces=NS_CFDI)
|
||||
data = {
|
||||
'ComprobanteXML': etree.tostring(tree).decode(),
|
||||
'RFC': rfc,
|
||||
'Token': self._get_token(rfc),
|
||||
'TransaccionID': self._get_epoch(fecha),
|
||||
}
|
||||
return data
|
||||
|
||||
def _get_by_hash(self, sh, rfc):
|
||||
token, access_token = self._get_token_rest(rfc)
|
||||
url = URL['hash'].format(sh)
|
||||
headers = {
|
||||
'Authorization': 'Bearer {}'.format(access_token),
|
||||
'X-Auth-Token': token,
|
||||
}
|
||||
result = requests.get(url, headers=headers)
|
||||
if result.status_code == 200:
|
||||
print (result.json())
|
||||
return
|
||||
|
||||
def timbra_xml(self, xml):
|
||||
data = self._validate_xml(xml)
|
||||
client = Client(URL['timbra'],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.TimbraXML(**data)
|
||||
except Fault as e:
|
||||
error = str(e)
|
||||
if self.codes['HASH'] in error:
|
||||
sh = error.split(' ')[3]
|
||||
return self._get_by_hash(sh[:40], data['RFC'])
|
||||
self.error = error
|
||||
return ''
|
||||
|
||||
tree = parseString(result.ComprobanteXML.DatosXML)
|
||||
xml = tree.toprettyxml(encoding='utf-8').decode('utf-8')
|
||||
return xml
|
||||
|
||||
def _get_epoch(self, date=None):
|
||||
if isinstance(date, str):
|
||||
f = '%Y-%m-%dT%H:%M:%S'
|
||||
e = int(time.mktime(time.strptime(date, f)))
|
||||
else:
|
||||
date = datetime.datetime.now()
|
||||
e = int(time.mktime(date.timetuple()))
|
||||
return e
|
||||
|
||||
def estatus_cuenta(self, rfc):
|
||||
#~ Codigos:
|
||||
#~ 100 = Cuenta encontrada
|
||||
#~ 101 = RFC no dado de alta en el sistema ECODEX
|
||||
token = self._get_token(rfc)
|
||||
if not token:
|
||||
return {}
|
||||
|
||||
data = {
|
||||
'RFC': rfc,
|
||||
'Token': token,
|
||||
'TransaccionID': self._get_epoch()
|
||||
}
|
||||
client = Client(URL['clients'],
|
||||
transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.EstatusCuenta(**data)
|
||||
except Fault as e:
|
||||
log.error(str(e))
|
||||
return
|
||||
#~ print (result)
|
||||
return result.Estatus
|
||||
|
||||
|
||||
class Finkok(object):
|
||||
|
||||
def __init__(self):
|
||||
self.codes = URL['codes']
|
||||
self.error = ''
|
||||
self.message = ''
|
||||
self._transport = Transport(cache=SqliteCache(), timeout=TIMEOUT)
|
||||
self._plugins = None
|
||||
self._history = None
|
||||
self.uuid = ''
|
||||
self.fecha = None
|
||||
if DEBUG:
|
||||
self._history = HistoryPlugin()
|
||||
self._plugins = [self._history]
|
||||
|
||||
def _debug(self):
|
||||
if not DEBUG:
|
||||
return
|
||||
print('SEND', self._history.last_sent)
|
||||
print('RESULT', self._history.last_received)
|
||||
return
|
||||
|
||||
def _check_result(self, method, result):
|
||||
#~ print ('CODE', result.CodEstatus)
|
||||
#~ print ('INCIDENCIAS', result.Incidencias)
|
||||
self.message = ''
|
||||
MSG = {
|
||||
'OK': 'Comprobante timbrado satisfactoriamente',
|
||||
'307': 'Comprobante timbrado previamente',
|
||||
}
|
||||
status = result.CodEstatus
|
||||
if status is None and result.Incidencias:
|
||||
for i in result.Incidencias['Incidencia']:
|
||||
self.error += 'Error: {}\n{}'.format(
|
||||
i['CodigoError'], i['MensajeIncidencia'])
|
||||
return ''
|
||||
|
||||
if method == 'timbra' and status in (MSG['OK'], MSG['307']):
|
||||
#~ print ('UUID', result.UUID)
|
||||
#~ print ('FECHA', result.Fecha)
|
||||
if status == MSG['307']:
|
||||
self.message = MSG['307']
|
||||
tree = parseString(result.xml)
|
||||
response = tree.toprettyxml(encoding='utf-8').decode('utf-8')
|
||||
self.uuid = result.UUID
|
||||
self.fecha = result.Fecha
|
||||
|
||||
return response
|
||||
|
||||
def _load_file(self, path):
|
||||
try:
|
||||
with open(path, 'rb') as f:
|
||||
data = f.read()
|
||||
except Exception as e:
|
||||
self.error = str(e)
|
||||
return
|
||||
return data
|
||||
|
||||
def _validate_xml(self, file_xml):
|
||||
if os.path.isfile(file_xml):
|
||||
try:
|
||||
with open(file_xml, 'rb') as f:
|
||||
xml = f.read()
|
||||
except Exception as e:
|
||||
self.error = str(e)
|
||||
return False, ''
|
||||
else:
|
||||
xml = file_xml.encode('utf-8')
|
||||
return True, xml
|
||||
|
||||
def _validate_uuid(self, uuid):
|
||||
try:
|
||||
UUID(uuid)
|
||||
return True
|
||||
except ValueError:
|
||||
self.error = 'UUID no válido: {}'.format(uuid)
|
||||
return False
|
||||
|
||||
def timbra_xml(self, file_xml):
|
||||
self.error = ''
|
||||
method = 'timbra'
|
||||
ok, xml = self._validate_xml(file_xml)
|
||||
if not ok:
|
||||
return ''
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': AUTH['USER'],
|
||||
'password': AUTH['PASS'],
|
||||
'xml': xml,
|
||||
}
|
||||
if URL['quick_stamp']:
|
||||
try:
|
||||
result = client.service.quick_stamp(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return
|
||||
else:
|
||||
try:
|
||||
result = client.service.stamp(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return
|
||||
|
||||
return self._check_result(method, result)
|
||||
|
||||
def _get_xml(self, uuid):
|
||||
if not self._validate_uuid(uuid):
|
||||
return ''
|
||||
|
||||
method = 'util'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': AUTH['USER'],
|
||||
'password': AUTH['PASS'],
|
||||
'uuid': uuid,
|
||||
'taxpayer_id': self.rfc,
|
||||
'invoice_type': 'I',
|
||||
}
|
||||
try:
|
||||
result = client.service.get_xml(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
except TransportError as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
if result.error:
|
||||
self.error = result.error
|
||||
return ''
|
||||
|
||||
tree = parseString(result.xml)
|
||||
xml = tree.toprettyxml(encoding='utf-8').decode('utf-8')
|
||||
return xml
|
||||
|
||||
def recupera_xml(self, file_xml='', uuid=''):
|
||||
self.error = ''
|
||||
if uuid:
|
||||
return self._get_xml(uuid)
|
||||
|
||||
method = 'timbra'
|
||||
ok, xml = self._validate_xml(file_xml)
|
||||
if not ok:
|
||||
return ''
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.stamped(xml, AUTH['USER'], AUTH['PASS'])
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return self._check_result(method, result)
|
||||
|
||||
def estatus_xml(self, uuid):
|
||||
method = 'timbra'
|
||||
if not self._validate_uuid(uuid):
|
||||
return ''
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.query_pending(AUTH['USER'], AUTH['PASS'], uuid)
|
||||
#~ print (result.date)
|
||||
#~ tree = parseString(unescape(result.xml))
|
||||
#~ response = tree.toprettyxml(encoding='utf-8').decode('utf-8')
|
||||
return result.status
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
def cancel_xml(self, rfc, uuids, path_cer, path_key):
|
||||
for u in uuids:
|
||||
if not self._validate_uuid(u):
|
||||
return ''
|
||||
|
||||
cer = self._load_file(path_cer)
|
||||
key = self._load_file(path_key)
|
||||
method = 'cancel'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
uuid_type = client.get_type('ns1:UUIDS')
|
||||
sa = client.get_type('ns0:stringArray')
|
||||
|
||||
args = {
|
||||
'UUIDS': uuid_type(uuids=sa(string=uuids)),
|
||||
'username': AUTH['USER'],
|
||||
'password': AUTH['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'cer': cer,
|
||||
'key': key,
|
||||
'store_pending': True,
|
||||
}
|
||||
try:
|
||||
result = client.service.cancel(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
if result.CodEstatus and self.codes['205'] in result.CodEstatus:
|
||||
self.error = result.CodEstatus
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def cancel_signature(self, file_xml):
|
||||
method = 'cancel'
|
||||
if os.path.isfile(file_xml):
|
||||
root = etree.parse(file_xml).getroot()
|
||||
else:
|
||||
root = etree.fromstring(file_xml)
|
||||
|
||||
xml = etree.tostring(root)
|
||||
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': AUTH['USER'],
|
||||
'password': AUTH['PASS'],
|
||||
'xml': xml,
|
||||
'store_pending': True,
|
||||
}
|
||||
|
||||
result = client.service.cancel_signature(**args)
|
||||
return result
|
||||
|
||||
def get_acuse(self, rfc, uuids, type_acuse='C'):
|
||||
for u in uuids:
|
||||
if not self._validate_uuid(u):
|
||||
return ''
|
||||
|
||||
method = 'cancel'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': AUTH['USER'],
|
||||
'password': AUTH['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'uuid': '',
|
||||
'type': type_acuse,
|
||||
}
|
||||
try:
|
||||
result = []
|
||||
for u in uuids:
|
||||
args['uuid'] = u
|
||||
r = client.service.get_receipt(**args)
|
||||
result.append(r)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def estatus_cancel(self, uuids):
|
||||
for u in uuids:
|
||||
if not self._validate_uuid(u):
|
||||
return ''
|
||||
|
||||
method = 'cancel'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
|
||||
args = {
|
||||
'username': AUTH['USER'],
|
||||
'password': AUTH['PASS'],
|
||||
'uuid': '',
|
||||
}
|
||||
try:
|
||||
result = []
|
||||
for u in uuids:
|
||||
args['uuid'] = u
|
||||
r = client.service.query_pending_cancellation(**args)
|
||||
result.append(r)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def add_token(self, rfc, email):
|
||||
"""
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
"""
|
||||
method = 'util'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'username': AUTH['USER'],
|
||||
'password': AUTH['PASS'],
|
||||
'name': rfc,
|
||||
'token_username': email,
|
||||
'taxpayer_id': rfc,
|
||||
'status': True,
|
||||
}
|
||||
result = client.service.add_token(**args)
|
||||
return result
|
||||
|
||||
def get_date(self):
|
||||
method = 'util'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
try:
|
||||
result = client.service.datetime(AUTH['USER'], AUTH['PASS'])
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
if result.error:
|
||||
self.error = result.error
|
||||
return
|
||||
|
||||
return result.datetime
|
||||
|
||||
def add_client(self, rfc, type_user=False):
|
||||
"""
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
type_user: False == 'P' == Prepago or True == 'O' == On demand
|
||||
"""
|
||||
tu = {False: 'P', True: 'O'}
|
||||
method = 'client'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'reseller_username': AUTH['USER'],
|
||||
'reseller_password': AUTH['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'type_user': tu[type_user],
|
||||
'added': datetime.datetime.now().isoformat()[:19],
|
||||
}
|
||||
try:
|
||||
result = client.service.add(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def edit_client(self, rfc, status=True):
|
||||
"""
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
status = 'A' or 'S'
|
||||
"""
|
||||
sv = {False: 'S', True: 'A'}
|
||||
method = 'client'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'reseller_username': AUTH['USER'],
|
||||
'reseller_password': AUTH['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'status': sv[status],
|
||||
}
|
||||
try:
|
||||
result = client.service.edit(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def get_client(self, rfc):
|
||||
"""
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
"""
|
||||
method = 'client'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'reseller_username': AUTH['USER'],
|
||||
'reseller_password': AUTH['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
}
|
||||
|
||||
try:
|
||||
result = client.service.get(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
except TransportError as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
def assign_client(self, rfc, credit):
|
||||
"""
|
||||
Se requiere cuenta de reseller para usar este método
|
||||
"""
|
||||
method = 'client'
|
||||
client = Client(
|
||||
URL[method], transport=self._transport, plugins=self._plugins)
|
||||
args = {
|
||||
'username': AUTH['USER'],
|
||||
'password': AUTH['PASS'],
|
||||
'taxpayer_id': rfc,
|
||||
'credit': credit,
|
||||
}
|
||||
try:
|
||||
result = client.service.assign(**args)
|
||||
except Fault as e:
|
||||
self.error = str(e)
|
||||
return ''
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _get_data_sat(path):
|
||||
BF = 'string(//*[local-name()="{}"]/@{})'
|
||||
NS_CFDI = {'cfdi': 'http://www.sat.gob.mx/cfd/3'}
|
||||
|
||||
try:
|
||||
if os.path.isfile(path):
|
||||
tree = etree.parse(path).getroot()
|
||||
else:
|
||||
tree = etree.fromstring(path)
|
||||
|
||||
data = {}
|
||||
emisor = escape(
|
||||
tree.xpath('string(//cfdi:Emisor/@rfc)', namespaces=NS_CFDI) or
|
||||
tree.xpath('string(//cfdi:Emisor/@Rfc)', namespaces=NS_CFDI)
|
||||
)
|
||||
receptor = escape(
|
||||
tree.xpath('string(//cfdi:Receptor/@rfc)', namespaces=NS_CFDI) or
|
||||
tree.xpath('string(//cfdi:Receptor/@Rfc)', namespaces=NS_CFDI)
|
||||
)
|
||||
data['total'] = tree.get('total') or tree.get('Total')
|
||||
data['emisor'] = emisor
|
||||
data['receptor'] = receptor
|
||||
data['uuid'] = tree.xpath(BF.format('TimbreFiscalDigital', 'UUID'))
|
||||
except Exception as e:
|
||||
print (e)
|
||||
return {}
|
||||
|
||||
return '?re={emisor}&rr={receptor}&tt={total}&id={uuid}'.format(**data)
|
||||
|
||||
|
||||
def get_status_sat(xml):
|
||||
data = _get_data_sat(xml)
|
||||
if not data:
|
||||
return
|
||||
|
||||
URL = 'https://consultaqr.facturaelectronica.sat.gob.mx/ConsultaCFDIService.svc?wsdl'
|
||||
client = Client(URL, transport=Transport(cache=SqliteCache()))
|
||||
try:
|
||||
result = client.service.Consulta(expresionImpresa=data)
|
||||
except Exception as e:
|
||||
return 'Error: {}'.format(str(e))
|
||||
|
||||
return result.Estado
|
||||
|
||||
|
||||
def main():
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -15,7 +15,8 @@ import uuid
|
|||
|
||||
from dateutil import parser
|
||||
|
||||
from settings import DEBUG, log, template_lookup, COMPANIES, DB_SAT
|
||||
from settings import DEBUG, log, template_lookup, COMPANIES, DB_SAT, \
|
||||
PATH_XSLT, PATH_XSLTPROC, PATH_OPENSSL
|
||||
|
||||
|
||||
#~ def _get_hash(password):
|
||||
|
@ -30,6 +31,10 @@ def _call(args):
|
|||
return subprocess.check_output(args, shell=True).decode()
|
||||
|
||||
|
||||
def _get_md5(data):
|
||||
return hashlib.md5(data.encode()).hexdigest()
|
||||
|
||||
|
||||
def _save_temp(data, modo='wb'):
|
||||
path = tempfile.mkstemp()[1]
|
||||
with open(path, modo) as f:
|
||||
|
@ -37,6 +42,18 @@ def _save_temp(data, modo='wb'):
|
|||
return path
|
||||
|
||||
|
||||
def _join(*paths):
|
||||
return os.path.join(*paths)
|
||||
|
||||
|
||||
def _kill(path):
|
||||
try:
|
||||
os.remove(path)
|
||||
except:
|
||||
pass
|
||||
return
|
||||
|
||||
|
||||
def get_pass():
|
||||
password = getpass.getpass('Introduce la contraseña: ')
|
||||
pass2 = getpass.getpass('Confirma la contraseña: ')
|
||||
|
@ -312,7 +329,7 @@ class Certificado(object):
|
|||
|
||||
args = 'openssl pkcs8 -inform DER -in "{}" -passin pass:{} | ' \
|
||||
'openssl rsa -des3 -passout pass:{}'.format(
|
||||
self._path_key, password, hashlib.md5(rfc.encode()).hexdigest())
|
||||
self._path_key, password, _get_md5(rfc))
|
||||
key_enc = _call(args)
|
||||
|
||||
data['key'] = self._key
|
||||
|
@ -327,7 +344,7 @@ class Certificado(object):
|
|||
return {}
|
||||
|
||||
data = self._get_info_cer(rfc)
|
||||
llave = self._get_info_key(password, rfc)
|
||||
llave = self._get_info_key(password, data['rfc'])
|
||||
if not llave:
|
||||
return {}
|
||||
|
||||
|
@ -336,3 +353,49 @@ class Certificado(object):
|
|||
self._kill(self._path_key)
|
||||
self._kill(self._path_cer)
|
||||
return data
|
||||
|
||||
|
||||
def make_xml(data, certificado):
|
||||
from .cfdi_xml import CFDI
|
||||
|
||||
if DEBUG:
|
||||
data['emisor']['Rfc'] = certificado.rfc
|
||||
data['emisor']['RegimenFiscal'] = '603'
|
||||
|
||||
cfdi = CFDI()
|
||||
xml = cfdi.get_xml(data)
|
||||
|
||||
data = {
|
||||
'xsltproc': PATH_XSLTPROC,
|
||||
'xslt': _join(PATH_XSLT, 'cadena.xslt'),
|
||||
'xml': _save_temp(xml, 'w'),
|
||||
'openssl': PATH_OPENSSL,
|
||||
'key': _save_temp(certificado.key_enc, 'w'),
|
||||
'pass': _get_md5(certificado.rfc)
|
||||
}
|
||||
args = '"{xsltproc}" "{xslt}" "{xml}" | ' \
|
||||
'"{openssl}" dgst -sha256 -sign "{key}" -passin pass:{pass} | ' \
|
||||
'"{openssl}" enc -base64 -A'.format(**data)
|
||||
sello = _call(args)
|
||||
|
||||
_kill(data['xml'])
|
||||
_kill(data['key'])
|
||||
|
||||
return cfdi.add_sello(sello)
|
||||
|
||||
|
||||
def timbra_xml(xml):
|
||||
from .pac import Finkok as PAC
|
||||
|
||||
result = {'ok': True, 'error': ''}
|
||||
pac = PAC()
|
||||
xml = pac.timbra_xml(xml)
|
||||
if not xml:
|
||||
result['ok'] = False
|
||||
result['error'] = pac.error
|
||||
return result
|
||||
|
||||
result['xml'] = xml
|
||||
result['uuid'] = pac.uuid
|
||||
result['fecha'] = pac.fecha
|
||||
return result
|
||||
|
|
|
@ -16,6 +16,8 @@ if __name__ == '__main__':
|
|||
from controllers import util
|
||||
from settings import log, VERSION, PATH_CP
|
||||
|
||||
FORMAT = '{0:.2f}'
|
||||
|
||||
|
||||
database_proxy = Proxy()
|
||||
class BaseModel(Model):
|
||||
|
@ -947,6 +949,7 @@ class Facturas(BaseModel):
|
|||
obj = Facturas.get(Facturas.id==id)
|
||||
if obj.uuid:
|
||||
return False
|
||||
|
||||
q = FacturasDetalle.delete().where(FacturasDetalle.factura==obj)
|
||||
q.execute()
|
||||
q = FacturasImpuestos.delete().where(FacturasImpuestos.factura==obj)
|
||||
|
@ -1108,21 +1111,21 @@ class Facturas(BaseModel):
|
|||
|
||||
receptor = {
|
||||
'Rfc': invoice.cliente.rfc,
|
||||
'Nombre': invoice.cliente.name,
|
||||
'Nombre': invoice.cliente.nombre,
|
||||
'UsoCFDI': invoice.uso_cfdi,
|
||||
}
|
||||
|
||||
conceptos = []
|
||||
rows = Details.select().where(Details.invoice==invoice)
|
||||
rows = FacturasDetalle.select().where(FacturasDetalle.factura==invoice)
|
||||
for row in rows:
|
||||
concepto = {
|
||||
'ClaveProdServ': row.product.key_sat,
|
||||
'NoIdentificacion': row.product.key,
|
||||
'Cantidad': FORMAT.format(row.cant),
|
||||
'ClaveUnidad': row.product.unit.key,
|
||||
'Unidad': row.product.unit.name,
|
||||
'Descripcion': row.product.description,
|
||||
'ValorUnitario': FORMAT.format(row.price),
|
||||
'ClaveProdServ': row.producto.clave_sat,
|
||||
'NoIdentificacion': row.producto.clave,
|
||||
'Cantidad': FORMAT.format(row.cantidad),
|
||||
'ClaveUnidad': row.producto.unidad.key,
|
||||
'Unidad': row.producto.unidad.name,
|
||||
'Descripcion': row.producto.descripcion,
|
||||
'ValorUnitario': FORMAT.format(row.valor_unitario),
|
||||
'Importe': FORMAT.format(row.importe),
|
||||
}
|
||||
|
||||
|
@ -1130,25 +1133,21 @@ class Facturas(BaseModel):
|
|||
traslados = []
|
||||
retenciones = []
|
||||
|
||||
impuestos = (ProductsTaxes
|
||||
.select()
|
||||
.where(ProductsTaxes.product==row.product))
|
||||
|
||||
for impuesto in impuestos:
|
||||
if impuesto.tax.tipo == 'E':
|
||||
for impuesto in row.producto.impuestos:
|
||||
if impuesto.tipo == 'E':
|
||||
continue
|
||||
import_tax = round(impuesto.tax.tasa * row.importe, 2)
|
||||
import_tax = round(impuesto.tasa * row.importe, 2)
|
||||
tipo_factor = 'Tasa'
|
||||
if impuesto.tax.factor != 'T':
|
||||
if impuesto.factor != 'T':
|
||||
tipo_factor = 'Cuota'
|
||||
tax = {
|
||||
"Base": FORMAT.format(row.importe),
|
||||
"Impuesto": impuesto.tax.key,
|
||||
"Impuesto": impuesto.key,
|
||||
"TipoFactor": tipo_factor,
|
||||
"TasaOCuota": str(impuesto.tax.tasa),
|
||||
"TasaOCuota": str(impuesto.tasa),
|
||||
"Importe": FORMAT.format(import_tax),
|
||||
}
|
||||
if impuesto.tax.tipo == 'T':
|
||||
if impuesto.tipo == 'T':
|
||||
traslados.append(tax)
|
||||
else:
|
||||
retenciones.append(tax)
|
||||
|
@ -1168,24 +1167,24 @@ class Facturas(BaseModel):
|
|||
impuestos['TotalImpuestosRetenidos'] = \
|
||||
FORMAT.format(invoice.total_retenciones)
|
||||
|
||||
taxes = (InvoicesTaxes
|
||||
taxes = (FacturasImpuestos
|
||||
.select()
|
||||
.where(InvoicesTaxes.invoice==invoice))
|
||||
.where(FacturasImpuestos.factura==invoice))
|
||||
for tax in taxes:
|
||||
tipo_factor = 'Tasa'
|
||||
if tax.tax.factor != 'T':
|
||||
if tax.impuesto.factor != 'T':
|
||||
tipo_factor = 'Cuota'
|
||||
if tax.tax.tipo == 'T':
|
||||
if tax.impuesto.tipo == 'T':
|
||||
traslado = {
|
||||
"Impuesto": tax.tax.key,
|
||||
"Impuesto": tax.impuesto.key,
|
||||
"TipoFactor": tipo_factor,
|
||||
"TasaOCuota": str(tax.tax.tasa),
|
||||
"TasaOCuota": str(tax.impuesto.tasa),
|
||||
"Importe": FORMAT.format(tax.importe),
|
||||
}
|
||||
traslados.append(traslado)
|
||||
else:
|
||||
retencion = {
|
||||
"Impuesto": tax.tax.key,
|
||||
"Impuesto": tax.impuesto.key,
|
||||
"Importe": FORMAT.format(tax.importe),
|
||||
}
|
||||
retenciones.append(retencion)
|
||||
|
@ -1209,21 +1208,24 @@ class Facturas(BaseModel):
|
|||
obj.estatus = 'Generada'
|
||||
obj.save()
|
||||
|
||||
#~ error = False
|
||||
#~ result = util.timbra_xml(obj.xml)
|
||||
#~ if result['ok']:
|
||||
#~ obj.xml = result['xml']
|
||||
#~ obj.uuid = result['uuid']
|
||||
#~ obj.fecha_timbrado = result['fecha']
|
||||
#~ obj.estatus = 'Timbrada'
|
||||
#~ obj.save()
|
||||
#~ else:
|
||||
#~ error = True
|
||||
#~ msg = result['error']
|
||||
#~ obj.estatus = 'Error'
|
||||
#~ obj.error = msg
|
||||
#~ obj.save()
|
||||
return
|
||||
error = False
|
||||
msg = 'Factura timbrada correctamente'
|
||||
result = util.timbra_xml(obj.xml)
|
||||
if result['ok']:
|
||||
obj.xml = result['xml']
|
||||
obj.uuid = result['uuid']
|
||||
obj.fecha_timbrado = result['fecha']
|
||||
obj.estatus = 'Timbrada'
|
||||
obj.save()
|
||||
row = {'uuid': obj.uuid, 'estatus': 'Timbrada'}
|
||||
else:
|
||||
error = True
|
||||
msg = result['error']
|
||||
obj.estatus = 'Error'
|
||||
obj.error = msg
|
||||
row = {'estatus': 'Error'}
|
||||
obj.save()
|
||||
return {'ok': result['ok'], 'msg': msg, 'row': row}
|
||||
|
||||
|
||||
class FacturasDetalle(BaseModel):
|
||||
|
|
|
@ -20,6 +20,9 @@ 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'))
|
||||
DB_SAT = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'sat.db'))
|
||||
|
||||
PATH_XSLT = os.path.abspath(os.path.join(BASE_DIR, '..', 'xslt'))
|
||||
PATH_BIN = os.path.abspath(os.path.join(BASE_DIR, '..', 'bin'))
|
||||
|
||||
template_lookup = TemplateLookup(directories=[PATH_TEMPLATES],
|
||||
input_encoding='utf-8',
|
||||
output_encoding='utf-8')
|
||||
|
@ -50,3 +53,9 @@ else:
|
|||
|
||||
log = Logger(LOG_NAME)
|
||||
|
||||
|
||||
PATH_XSLTPROC = 'xsltproc'
|
||||
PATH_OPENSSL = 'openssl'
|
||||
if 'win' in sys.platform:
|
||||
PATH_XSLTPROC = os.path.join(PATH_BIN, 'xsltproc.exe')
|
||||
PATH_OPENSSL = os.path.join(PATH_BIN, 'openssl.exe')
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
|
@ -111,7 +111,7 @@ function cmd_edit_invoice_click(id, e, node){
|
|||
function delete_invoice(id){
|
||||
webix.ajax().del('/invoices', {id: id}, function(text, xml, xhr){
|
||||
if(xhr.status == 200){
|
||||
$$('grid_invoices').remove(id)
|
||||
gi.remove(id)
|
||||
msg_sucess('Factura eliminada correctamente')
|
||||
}else{
|
||||
msg_error('No se pudo eliminar')
|
||||
|
@ -120,16 +120,15 @@ function delete_invoice(id){
|
|||
}
|
||||
|
||||
|
||||
|
||||
function cmd_delete_invoice_click(id, e, node){
|
||||
|
||||
var row = $$('grid_invoices').getSelectedItem()
|
||||
var row = gi.getSelectedItem()
|
||||
if (row == undefined){
|
||||
msg_error('Selecciona una factura')
|
||||
return
|
||||
}
|
||||
|
||||
if(!row['uuid']==null){
|
||||
if(row.uuid){
|
||||
msg_error('Solo se pueden eliminar facturas sin timbrar')
|
||||
return
|
||||
}
|
||||
|
@ -221,9 +220,9 @@ function validate_invoice(values){
|
|||
|
||||
function update_grid_invoices(values){
|
||||
if(values.new){
|
||||
$$('grid_invoices').add(values.row)
|
||||
gi.add(values.row)
|
||||
}else{
|
||||
$$("grid_invoices").updateItem(values.row['id'], values.row)
|
||||
gi.updateItem(values.row['id'], values.row)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,6 +231,7 @@ function send_timbrar(id){
|
|||
var values = data.json()
|
||||
if(values.ok){
|
||||
msg_sucess(values.msg)
|
||||
gi.updateItem(id, values.row)
|
||||
}else{
|
||||
webix.alert({
|
||||
title: 'Error al Timbrar',
|
||||
|
@ -256,11 +256,12 @@ function save_invoice(data){
|
|||
success:function(text, data, XmlHttpRequest){
|
||||
values = data.json();
|
||||
if(values.ok){
|
||||
msg_sucess('Factura guardada correctamente. Enviando a timbrar')
|
||||
update_grid_invoices(values)
|
||||
send_timbrar(values.row['id'])
|
||||
result = true
|
||||
}else{
|
||||
webix.message({type:'error', text:values.msg})
|
||||
msg_error(values.msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -602,3 +603,40 @@ function grid_details_header_click(id){
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function cmd_refacturar_click(){
|
||||
show('Refacturar')
|
||||
}
|
||||
|
||||
|
||||
function cmd_invoice_timbrar_click(){
|
||||
if(gi.count() == 0){
|
||||
return
|
||||
}
|
||||
|
||||
var row = gi.getSelectedItem()
|
||||
if (row == undefined){
|
||||
msg_error('Selecciona una factura')
|
||||
return
|
||||
}
|
||||
|
||||
if(row.uuid){
|
||||
msg_error('La factura ya esta timbrada')
|
||||
return
|
||||
}
|
||||
|
||||
msg = '¿Estás seguro de enviar a timbrar esta factura?'
|
||||
webix.confirm({
|
||||
title: 'Timbrar Factura',
|
||||
ok: 'Si',
|
||||
cancel: 'No',
|
||||
type: 'confirm-error',
|
||||
text: msg,
|
||||
callback:function(result){
|
||||
if(result){
|
||||
send_timbrar(row.id)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
var gi = null
|
||||
|
||||
|
||||
var controllers = {
|
||||
|
@ -29,9 +30,9 @@ var controllers = {
|
|||
$$("chk_automatica").attachEvent("onChange", chk_automatica_change)
|
||||
$$("valor_unitario").attachEvent("onChange", valor_unitario_change)
|
||||
//~ Invoices
|
||||
$$("cmd_new_invoice").attachEvent("onItemClick", cmd_new_invoice_click)
|
||||
$$("cmd_edit_invoice").attachEvent("onItemClick", cmd_edit_invoice_click)
|
||||
$$("cmd_delete_invoice").attachEvent("onItemClick", cmd_delete_invoice_click)
|
||||
$$('cmd_new_invoice').attachEvent("onItemClick", cmd_new_invoice_click)
|
||||
$$('cmd_refacturar').attachEvent("onItemClick", cmd_refacturar_click)
|
||||
$$('cmd_delete_invoice').attachEvent("onItemClick", cmd_delete_invoice_click)
|
||||
$$('cmd_timbrar').attachEvent('onItemClick', cmd_timbrar_click)
|
||||
$$('cmd_close_invoice').attachEvent('onItemClick', cmd_close_invoice_click)
|
||||
$$('search_client_id').attachEvent('onKeyPress', search_client_id_key_press)
|
||||
|
@ -42,6 +43,7 @@ var controllers = {
|
|||
$$('grid_details').attachEvent('onHeaderClick', grid_details_header_click)
|
||||
$$('grid_details').attachEvent('onBeforeEditStart', grid_details_before_edit_start)
|
||||
$$('grid_details').attachEvent('onBeforeEditStop', grid_details_before_edit_stop)
|
||||
$$('cmd_invoice_timbrar').attachEvent('onItemClick', cmd_invoice_timbrar_click)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,6 +138,7 @@ function multi_change(prevID, nextID){
|
|||
if(active == 'invoices_home'){
|
||||
get_invoices()
|
||||
}
|
||||
gi = $$('grid_invoices')
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -3,28 +3,46 @@
|
|||
var toolbar_invoices = [
|
||||
{view: "button", id: "cmd_new_invoice", label: "Nueva", type: "iconButton",
|
||||
autowidth: true, icon: "plus"},
|
||||
{view: "button", id: "cmd_edit_invoice", label: "Editar", type: "iconButton",
|
||||
{view: "button", id: "cmd_refacturar", label: "Refacturar", type: "iconButton",
|
||||
autowidth: true, icon: "pencil"},
|
||||
{},
|
||||
{view: "button", id: "cmd_delete_invoice", label: "Eliminar", type: "iconButton",
|
||||
autowidth: true, icon: "minus"},
|
||||
]
|
||||
|
||||
|
||||
var toolbar_invoices_util = [
|
||||
{view: 'button', id: 'cmd_invoice_timbrar', label: 'Timbrar',
|
||||
type: 'iconButton', autowidth: true, icon: 'ticket'},
|
||||
]
|
||||
|
||||
|
||||
function doc_xml(obj){
|
||||
var node = "<img src='/static/img/file-xml.png' height='20' width='20' style='margin: 5px 0px'/>"
|
||||
return node
|
||||
}
|
||||
|
||||
|
||||
function doc_pdf(obj){
|
||||
var node = "<img src='/static/img/file-pdf.png' height='20' width='20' style='margin: 5px 0px'/>"
|
||||
return node
|
||||
}
|
||||
|
||||
|
||||
function get_icon(tipo){
|
||||
var node = "<img src='/static/img/file-" + tipo + ".png' height='20' width='20' style='margin: 5px 0px'/>"
|
||||
return node
|
||||
}
|
||||
|
||||
|
||||
var grid_invoices_cols = [
|
||||
{id: "id", header:"ID", hidden:true},
|
||||
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data",
|
||||
sort:"string"},
|
||||
{id: "folio", header: ["Folio", {content: "numberFilter"}], adjust: "data",
|
||||
sort:"int", css: "cell_right"},
|
||||
{id: 'xml', header: '', adjust: 'data', template: doc_xml},
|
||||
{id: "uuid", header: ["UUID", {content: "textFilter"}], adjust: "data",
|
||||
sort:"string"},
|
||||
sort:"string", hidden:true},
|
||||
{id: "fecha", header: ["Fecha y Hora"], adjust: "data", sort:"string"},
|
||||
{id: "tipo_comprobante", header: ["Tipo", {content: "selectFilter"}],
|
||||
adjust: 'header', sort: 'string'},
|
||||
|
@ -34,13 +52,17 @@ var grid_invoices_cols = [
|
|||
sort: 'int', format: webix.i18n.priceFormat, css: 'right'},
|
||||
{id: "cliente", header: ["Razón Social", {content: "selectFilter"}],
|
||||
fillspace:true, sort:"string"},
|
||||
{id: 'xml', header: 'XML', adjust: 'data', template: get_icon('xml')},
|
||||
{id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')},
|
||||
{id: 'zip', header: 'ZIP', adjust: 'data', template: get_icon('zip')},
|
||||
{id: 'email', header: '', adjust: 'data', template: get_icon('email')}
|
||||
]
|
||||
|
||||
|
||||
var grid_invoices = {
|
||||
view: "datatable",
|
||||
id: "grid_invoices",
|
||||
select: "row",
|
||||
view: 'datatable',
|
||||
id: 'grid_invoices',
|
||||
select: 'row',
|
||||
adjust: true,
|
||||
footer: true,
|
||||
resizeColumn: true,
|
||||
|
@ -296,15 +318,16 @@ var form_invoice = {
|
|||
|
||||
|
||||
var multi_invoices = {
|
||||
id: "multi_invoices",
|
||||
id: 'multi_invoices',
|
||||
view: 'multiview',
|
||||
animate: true,
|
||||
cells:[
|
||||
{id: "invoices_home", rows:[
|
||||
{view: "toolbar", elements: toolbar_invoices},
|
||||
{id: 'invoices_home', rows:[
|
||||
{view: 'toolbar', elements: toolbar_invoices},
|
||||
{view: 'toolbar', elements: toolbar_invoices_util},
|
||||
grid_invoices,
|
||||
]},
|
||||
{id: "invoices_new", rows:[form_invoice, {}]}
|
||||
{id: 'invoices_new', rows:[form_invoice, {}]}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,345 @@
|
|||
<?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:cfdi="http://www.sat.gob.mx/cfd/3" xmlns:cce11="http://www.sat.gob.mx/ComercioExterior11" xmlns:donat="http://www.sat.gob.mx/donat" xmlns:divisas="http://www.sat.gob.mx/divisas" xmlns:implocal="http://www.sat.gob.mx/implocal" xmlns:leyendasFisc="http://www.sat.gob.mx/leyendasFiscales" xmlns:pfic="http://www.sat.gob.mx/pfic" xmlns:tpe="http://www.sat.gob.mx/TuristaPasajeroExtranjero" xmlns:nomina12="http://www.sat.gob.mx/nomina12" xmlns:registrofiscal="http://www.sat.gob.mx/registrofiscal" xmlns:pagoenespecie="http://www.sat.gob.mx/pagoenespecie" xmlns:aerolineas="http://www.sat.gob.mx/aerolineas" xmlns:valesdedespensa="http://www.sat.gob.mx/valesdedespensa" xmlns:consumodecombustibles="http://www.sat.gob.mx/consumodecombustibles" xmlns:notariospublicos="http://www.sat.gob.mx/notariospublicos" xmlns:vehiculousado="http://www.sat.gob.mx/vehiculousado" xmlns:servicioparcial="http://www.sat.gob.mx/servicioparcialconstruccion" xmlns:decreto="http://www.sat.gob.mx/renovacionysustitucionvehiculos" xmlns:destruccion="http://www.sat.gob.mx/certificadodestruccion" xmlns:obrasarte="http://www.sat.gob.mx/arteantiguedades" xmlns:ine="http://www.sat.gob.mx/ine" xmlns:iedu="http://www.sat.gob.mx/iedu" xmlns:ventavehiculos="http://www.sat.gob.mx/ventavehiculos" xmlns:terceros="http://www.sat.gob.mx/terceros" xmlns:pago10="http://www.sat.gob.mx/Pagos">
|
||||
|
||||
<!-- Con el siguiente método se establece que la salida deberá ser en texto -->
|
||||
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="no"/>
|
||||
|
||||
<xsl:include href="utilerias.xslt"/>
|
||||
<xsl:include href="comercioexterior11.xslt"/>
|
||||
<xsl:include href="leyendasFisc.xslt"/>
|
||||
<xsl:include href="nomina12.xslt"/>
|
||||
|
||||
<!--
|
||||
<xsl:include href="ecc11.xslt"/>
|
||||
<xsl:include href="donat11.xslt"/>
|
||||
<xsl:include href="Divisas.xslt"/>
|
||||
<xsl:include href="implocal.xslt"/>
|
||||
<xsl:include href="pfic.xslt"/>
|
||||
<xsl:include href="TuristaPasajeroExtranjero.xslt"/>
|
||||
<xsl:include href="cfdiregistrofiscal.xslt"/>
|
||||
<xsl:include href="pagoenespecie.xslt"/>
|
||||
<xsl:include href="aerolineas.xslt"/>
|
||||
<xsl:include href="valesdedespensa.xslt"/>
|
||||
<xsl:include href="consumodecombustibles.xslt"/>
|
||||
<xsl:include href="notariospublicos.xslt"/>
|
||||
<xsl:include href="vehiculousado.xslt"/>
|
||||
<xsl:include href="servicioparcialconstruccion.xslt"/>
|
||||
<xsl:include href="renovacionysustitucionvehiculos.xslt"/>
|
||||
<xsl:include href="certificadodedestruccion.xslt"/>
|
||||
<xsl:include href="obrasarteantiguedades.xslt"/>
|
||||
<xsl:include href="ine11.xslt"/>
|
||||
<xsl:include href="iedu.xslt"/>
|
||||
<xsl:include href="ventavehiculos11.xslt"/>
|
||||
<xsl:include href="terceros11.xslt"/>
|
||||
<xsl:include href="Pagos10.xslt"/>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Aquí iniciamos el procesamiento de la cadena original con su | inicial y el terminador || -->
|
||||
<xsl:template match="/">|<xsl:apply-templates select="/cfdi:Comprobante"/>||</xsl:template>
|
||||
<!-- Aquí iniciamos el procesamiento de los datos incluidos en el comprobante -->
|
||||
<xsl:template match="cfdi:Comprobante">
|
||||
<!-- Iniciamos el tratamiento de los atributos de comprobante -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Version"/>
|
||||
</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="./@Fecha"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@FormaPago"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@NoCertificado"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@CondicionesDePago"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@SubTotal"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Descuento"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Moneda"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TipoCambio"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Total"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoDeComprobante"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@MetodoPago"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@LugarExpedicion"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Confirmacion"/>
|
||||
</xsl:call-template>
|
||||
<!--
|
||||
Llamadas para procesar al los sub nodos del comprobante
|
||||
-->
|
||||
<xsl:apply-templates select="./cfdi:CfdiRelacionados"/>
|
||||
<xsl:apply-templates select="./cfdi:Emisor"/>
|
||||
<xsl:apply-templates select="./cfdi:Receptor"/>
|
||||
<xsl:apply-templates select="./cfdi:Conceptos"/>
|
||||
<xsl:apply-templates select="./cfdi:Impuestos"/>
|
||||
<xsl:for-each select="./cfdi:Complemento">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo CFDIRelacionados -->
|
||||
<xsl:template match="cfdi:CfdiRelacionados">
|
||||
<!-- Iniciamos el tratamiento de los atributos del CFDIRelacionados -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoRelacion"/>
|
||||
</xsl:call-template>
|
||||
<xsl:for-each select="./cfdi:CfdiRelacionado">
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@UUID"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo Emisor -->
|
||||
<xsl:template match="cfdi:Emisor">
|
||||
<!-- Iniciamos el tratamiento de los atributos del Emisor -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Rfc"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Nombre"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@RegimenFiscal"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo Receptor -->
|
||||
<xsl:template match="cfdi:Receptor">
|
||||
<!-- Iniciamos el tratamiento de los atributos del Receptor -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Rfc"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Nombre"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@ResidenciaFiscal"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumRegIdTrib"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@UsoCFDI"/>
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo Conceptos -->
|
||||
<xsl:template match="cfdi:Conceptos">
|
||||
<!-- Llamada para procesar los distintos nodos tipo Concepto -->
|
||||
<xsl:for-each select="./cfdi:Concepto">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<!--Manejador de nodos tipo Concepto-->
|
||||
<xsl:template match="cfdi:Concepto">
|
||||
<!-- Iniciamos el tratamiento de los atributos del Concepto -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ClaveProdServ"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NoIdentificacion"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Cantidad"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ClaveUnidad"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Unidad"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Descripcion"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ValorUnitario"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Importe"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Descuento"/>
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Manejo de sub nodos de información Traslado de Conceptos:Concepto:Impuestos:Traslados-->
|
||||
<xsl:for-each select="./cfdi:Impuestos/cfdi:Traslados/cfdi:Traslado">
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Base"/>
|
||||
</xsl:call-template>
|
||||
<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="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TasaOCuota"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Importe"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
|
||||
<!-- Manejo de sub nodos de Retencion por cada una de los Conceptos:Concepto:Impuestos:Retenciones-->
|
||||
<xsl:for-each select="./cfdi:Impuestos/cfdi:Retenciones/cfdi:Retencion">
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Base"/>
|
||||
</xsl:call-template>
|
||||
<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:for-each>
|
||||
|
||||
<!-- Manejo de los distintos sub nodos de información aduanera de forma indistinta a su grado de dependencia -->
|
||||
<xsl:for-each select="./cfdi:InformacionAduanera">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
<!-- Llamada al manejador de nodos de CuentaPredial en caso de existir -->
|
||||
<xsl:if test="./cfdi:CuentaPredial">
|
||||
<xsl:apply-templates select="./cfdi:CuentaPredial"/>
|
||||
</xsl:if>
|
||||
|
||||
<!-- Llamada al manejador de nodos de ComplementoConcepto en caso de existir -->
|
||||
<xsl:if test="./cfdi:ComplementoConcepto">
|
||||
<xsl:apply-templates select="./cfdi:ComplementoConcepto"/>
|
||||
</xsl:if>
|
||||
|
||||
<!-- Llamada al manejador de nodos de Parte en caso de existir -->
|
||||
<xsl:for-each select=".//cfdi:Parte">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo Información Aduanera -->
|
||||
<xsl:template match="cfdi:InformacionAduanera">
|
||||
<!-- Manejo de los atributos de la información aduanera -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@NumeroPedimento"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo Información CuentaPredial -->
|
||||
<xsl:template match="cfdi:CuentaPredial">
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Numero"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo ComplementoConcepto -->
|
||||
<xsl:template match="cfdi:ComplementoConcepto">
|
||||
<xsl:for-each select="./*">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo Parte -->
|
||||
<xsl:template match="cfdi:Parte">
|
||||
<!-- Iniciamos el tratamiento de los atributos de Parte-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ClaveProdServ"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NoIdentificacion"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Cantidad"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Unidad"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Descripcion"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@ValorUnitario"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Importe"/>
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Manejador de nodos tipo InformacionAduanera-->
|
||||
<xsl:for-each select=".//cfdi:InformacionAduanera">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo Complemento -->
|
||||
<xsl:template match="cfdi:Complemento">
|
||||
<xsl:for-each select="./*">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de nodos tipo Domicilio fiscal -->
|
||||
<xsl:template match="cfdi:Impuestos">
|
||||
<!-- Manejo de sub nodos de Retencion por cada una de los Impuestos:Retenciones-->
|
||||
<xsl:for-each select="./cfdi:Retenciones/cfdi: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:for-each>
|
||||
<!-- Iniciamos el tratamiento de los atributos de TotalImpuestosRetenidos-->
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalImpuestosRetenidos"/>
|
||||
</xsl:call-template>
|
||||
<!-- Manejo de sub nodos de información Traslado de Impuestos:Traslados-->
|
||||
<xsl:for-each select="./cfdi:Traslados/cfdi: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:for-each>
|
||||
<!-- Iniciamos el tratamiento de los atributos de TotalImpuestosTrasladados-->
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalImpuestosTrasladados"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,181 @@
|
|||
<?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:cce11="http://www.sat.gob.mx/ComercioExterior11">
|
||||
|
||||
<xsl:template match="cce11:ComercioExterior">
|
||||
<!--Manejador de nodos tipo ComercioExterior-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Version" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@MotivoTraslado" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoOperacion" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@ClaveDePedimento" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@CertificadoOrigen" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumCertificadoOrigen" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumeroExportadorConfiable" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Incoterm" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Subdivision" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Observaciones" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TipoCambioUSD" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalUSD" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia -->
|
||||
<xsl:apply-templates select="./cce11:Emisor" />
|
||||
<xsl:for-each select="./cce11:Propietario">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
<xsl:apply-templates select="./cce11:Receptor" />
|
||||
<xsl:for-each select="./cce11:Destinatario">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
<xsl:apply-templates select="./cce11:Mercancias" />
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="cce11:Emisor">
|
||||
<!-- Iniciamos el tratamiento de los atributos de cce11:Emisor-->
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Curp" />
|
||||
</xsl:call-template>
|
||||
|
||||
<xsl:apply-templates select="./cce11:Domicilio" />
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="cce11:Propietario">
|
||||
<!-- Tratamiento de los atributos de cce11:Propietario-->
|
||||
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@NumRegIdTrib" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ResidenciaFiscal" />
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="cce11:Receptor">
|
||||
<!-- Tratamiento de los atributos de cce11:Receptor-->
|
||||
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumRegIdTrib" />
|
||||
</xsl:call-template>
|
||||
<xsl:apply-templates select="./cce11:Domicilio" />
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="cce11:Destinatario">
|
||||
<!-- Tratamiento de los atributos de cce11:Destinatario-->
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumRegIdTrib" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Nombre" />
|
||||
</xsl:call-template>
|
||||
<!-- Manejo de los nodos dependientes -->
|
||||
<xsl:for-each select="./cce11:Domicilio">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="cce11:Mercancias">
|
||||
<!-- Iniciamos el manejo de los nodos dependientes -->
|
||||
<xsl:for-each select="./cce11:Mercancia">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="cce11:Domicilio">
|
||||
<!-- Iniciamos el tratamiento de los atributos de cce11:Domicilio-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Calle" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumeroExterior" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumeroInterior" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Colonia" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Localidad" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Referencia" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Municipio" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Estado" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Pais" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@CodigoPostal" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="cce11:Mercancia">
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@NoIdentificacion" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@FraccionArancelaria" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@CantidadAduana" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@UnidadAduana" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@ValorUnitarioAduana" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ValorDolares" />
|
||||
</xsl:call-template>
|
||||
<xsl:for-each select="./cce11:DescripcionesEspecificas">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="cce11:DescripcionesEspecificas">
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Marca" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Modelo" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@SubModelo" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumeroSerie" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsl:stylesheet version="1.1" 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:leyendasFisc="http://www.sat.gob.mx/leyendasFiscales">
|
||||
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="no"/>
|
||||
<!-- Manejador de nodos tipo leyendasFiscales -->
|
||||
<xsl:template match="leyendasFisc:LeyendasFiscales">
|
||||
<!--Iniciamos el tratamiento de los atributos del complemento LeyendasFiscales -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@version"/>
|
||||
</xsl:call-template>
|
||||
<!-- Manejo de los atributos de las leyendas Fiscales-->
|
||||
<xsl:for-each select="./leyendasFisc:Leyenda">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<!-- Manejador de nodos tipo Información de las leyendas -->
|
||||
<xsl:template match="leyendasFisc:Leyenda">
|
||||
<!-- Manejo de los atributos de la leyenda -->
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@disposicionFiscal"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@norma"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@textoLeyenda"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,412 @@
|
|||
<?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:nomina12="http://www.sat.gob.mx/nomina12">
|
||||
|
||||
<xsl:template match="nomina12:Nomina">
|
||||
<!--Manejador de nodos tipo Nomina-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Version" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoNomina" />
|
||||
</xsl:call-template>
|
||||
<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="./@FechaInicialPago" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@FechaFinalPago" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@NumDiasPagados" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalPercepciones" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalDeducciones" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalOtrosPagos" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia -->
|
||||
<xsl:for-each select="./nomina12:Emisor">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
<xsl:for-each select="./nomina12:Receptor">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
<xsl:for-each select="./nomina12:Percepciones">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
<xsl:for-each select="./nomina12:Deducciones">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
<xsl:for-each select="./nomina12:OtrosPagos">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
<xsl:for-each select="./nomina12:Incapacidades">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="nomina12:Emisor">
|
||||
<!--Manejador de nodos tipo nomina12:Emisor-->
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Curp" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@RegistroPatronal" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@RfcPatronOrigen" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:EntidadSNCF-->
|
||||
<xsl:for-each select="./nomina12:EntidadSNCF">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia EntidadSNCF-->
|
||||
<xsl:template match="nomina12:EntidadSNCF">
|
||||
<!-- Iniciamos el manejo de los nodos dependientes -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@OrigenRecurso" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@MontoRecursoPropio" />
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="nomina12:Receptor">
|
||||
<!--Manejador de nodos tipo nomina12:Receptor-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Curp" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@NumSeguridadSocial" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@FechaInicioRelLaboral" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Antigüedad" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoContrato" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Sindicalizado" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TipoJornada" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoRegimen" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@NumEmpleado" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Departamento" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Puesto" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@RiesgoPuesto" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@PeriodicidadPago" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@Banco" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@CuentaBancaria" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@SalarioBaseCotApor" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@SalarioDiarioIntegrado" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ClaveEntFed" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:SubContratacion-->
|
||||
<xsl:for-each select="./nomina12:SubContratacion">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia SubContratacion-->
|
||||
<xsl:template match="nomina12:SubContratacion">
|
||||
<!-- Iniciamos el manejo de los nodos dependientes -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@RfcLabora" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@PorcentajeTiempo" />
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="nomina12:Percepciones">
|
||||
<!--Manejador de nodos tipo nomina12:Percepciones-->
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalSueldos" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalSeparacionIndemnizacion" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalJubilacionPensionRetiro" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TotalGravado" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TotalExento" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:Percepcion-->
|
||||
<xsl:for-each select="./nomina12:Percepcion">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:JubilacionPensionRetiro-->
|
||||
<xsl:for-each select="./nomina12:JubilacionPensionRetiro">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:SeparacionIndemnizacion-->
|
||||
<xsl:for-each select="./nomina12:SeparacionIndemnizacion">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia Percepcion-->
|
||||
<xsl:template match="nomina12:Percepcion">
|
||||
<!--Manejador de nodos tipo nomina12:Percepcion-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoPercepcion" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Clave" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Concepto" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ImporteGravado" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ImporteExento" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:AccionesOTitulos-->
|
||||
<xsl:for-each select="./nomina12:AccionesOTitulos">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:HorasExtra-->
|
||||
<xsl:for-each select="./nomina12:HorasExtra">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia AccionesOTitulos-->
|
||||
<xsl:template match="nomina12:AccionesOTitulos">
|
||||
<!-- Iniciamos el manejo de los nodos dependientes -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ValorMercado" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@PrecioAlOtorgarse" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia HorasExtra-->
|
||||
<xsl:template match="nomina12:HorasExtra">
|
||||
<!-- Iniciamos el manejo de los nodos dependientes -->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Dias" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoHoras" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@HorasExtra" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@ImportePagado" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia JubilacionPensionRetiro-->
|
||||
<xsl:template match="nomina12:JubilacionPensionRetiro">
|
||||
<!--Manejador de nodos tipo nomina12:JubilacionPensionRetiro-->
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalUnaExhibicion" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalParcialidad" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@MontoDiario" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@IngresoAcumulable" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@IngresoNoAcumulable" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia SeparacionIndemnizacion-->
|
||||
<xsl:template match="nomina12:SeparacionIndemnizacion">
|
||||
<!--Manejador de nodos tipo nomina12:JubilacionPensionRetiro-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TotalPagado" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@NumAñosServicio" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@UltimoSueldoMensOrd" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@IngresoAcumulable" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@IngresoNoAcumulable" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="nomina12:Deducciones">
|
||||
<!--Manejador de nodos tipo nomina12:Deducciones-->
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalOtrasDeducciones" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@TotalImpuestosRetenidos" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:Deduccion-->
|
||||
<xsl:for-each select="./nomina12:Deduccion">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia Deduccion-->
|
||||
<xsl:template match="nomina12:Deduccion">
|
||||
<!--Manejador de nodos tipo nomina12:Deduccion-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoDeduccion" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Clave" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Concepto" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Importe" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="nomina12:OtrosPagos">
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:OtroPago-->
|
||||
<xsl:for-each select="./nomina12:OtroPago">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia OtroPago-->
|
||||
<xsl:template match="nomina12:OtroPago">
|
||||
<!--Manejador de nodos tipo nomina12:OtroPago-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoOtroPago" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Clave" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Concepto" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Importe" />
|
||||
</xsl:call-template>
|
||||
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:SubsidioAlEmpleo-->
|
||||
<xsl:for-each select="./nomina12:SubsidioAlEmpleo">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:CompensacionSaldosAFavor-->
|
||||
<xsl:for-each select="./nomina12:CompensacionSaldosAFavor">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia SubsidioAlEmpleo-->
|
||||
<xsl:template match="nomina12:SubsidioAlEmpleo">
|
||||
<!--Manejador de nodos tipo nomina12:SubsidioAlEmpleo-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@SubsidioCausado" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia CompensacionSaldosAFavor-->
|
||||
<xsl:template match="nomina12:CompensacionSaldosAFavor">
|
||||
<!--Manejador de nodos tipo nomina12:CompensacionSaldosAFavor-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@SaldoAFavor" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@Año" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@RemanenteSalFav" />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="nomina12:Incapacidades">
|
||||
<!-- Iniciamos el tratamiento de los atributos de nomina12:Incapacidades-->
|
||||
<xsl:for-each select="./nomina12:Incapacidad">
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Iniciamos el manejo de los elementos hijo en la secuencia Incapacidad-->
|
||||
<xsl:template match="nomina12:Incapacidad">
|
||||
<!--Manejador de nodos tipo nomina12:Incapacidad-->
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@DiasIncapacidad" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Requerido">
|
||||
<xsl:with-param name="valor" select="./@TipoIncapacidad" />
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="Opcional">
|
||||
<xsl:with-param name="valor" select="./@ImporteMonetario" />
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsl:stylesheet version="1.1" 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">
|
||||
|
||||
<!-- Manejador de datos requeridos -->
|
||||
<xsl:template name="Requerido">
|
||||
<xsl:param name="valor"/>|<xsl:call-template name="ManejaEspacios">
|
||||
<xsl:with-param name="s" select="$valor"/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Manejador de datos opcionales -->
|
||||
<xsl:template name="Opcional">
|
||||
<xsl:param name="valor"/>
|
||||
<xsl:if test="$valor">|<xsl:call-template name="ManejaEspacios"><xsl:with-param name="s" select="$valor"/></xsl:call-template></xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Normalizador de espacios en blanco -->
|
||||
<xsl:template name="ManejaEspacios">
|
||||
<xsl:param name="s"/>
|
||||
<xsl:value-of select="normalize-space(string($s))"/>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
Loading…
Reference in New Issue