Merge branch 'develop'

Timbrado de Nómina
Complemento EDU
This commit is contained in:
Mauricio Baeza 2018-01-30 22:01:48 -06:00
commit 21eafd9e4a
28 changed files with 13955 additions and 131 deletions

View File

@ -33,9 +33,9 @@ SAT = {
'xmlns': 'http://www.sat.gob.mx/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', 'schema': 'http://www.sat.gob.mx/nomina http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina11.xsd',
}, },
'nomina12': { 'nomina': {
'version': '1.2', 'version': '1.2',
'prefix': 'nomina', 'prefix': 'nomina12',
'xmlns': 'http://www.sat.gob.mx/nomina12', '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', 'schema': 'http://www.sat.gob.mx/nomina12 http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina12.xsd',
}, },
@ -79,6 +79,7 @@ class CFDI(object):
self._donativo = False self._donativo = False
self._ine = False self._ine = False
self._edu = False self._edu = False
self._is_nomina = False
self.error = '' self.error = ''
def _now(self): def _now(self):
@ -115,37 +116,25 @@ class CFDI(object):
return xml return xml
def _validate(self, datos): def _validate(self, datos):
if datos['impuestos']['total_locales_trasladados'] or \ if datos['impuestos']:
datos['impuestos']['total_locales_retenciones']: if datos['impuestos']['total_locales_trasladados'] or \
self._impuestos_locales = True datos['impuestos']['total_locales_retenciones']:
self._impuestos_locales = True
if datos['donativo']: if datos['donativo']:
self._donativo = True self._donativo = True
if 'ine' in datos['complementos']: if datos['complementos']:
self._ine = True if 'ine' in datos['complementos']:
self._ine = True
self._edu = datos['edu']
if 'nomina' in datos: if 'nomina' in datos:
self._is_nomina = True
return self._validate_nomina(datos) return self._validate_nomina(datos)
return True return True
def _validate_nomina(self, datos): 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 return True
def _comprobante(self, datos): def _comprobante(self, datos):
@ -177,8 +166,15 @@ class CFDI(object):
attributes[name] = SAT['edu']['xmlns'] attributes[name] = SAT['edu']['xmlns']
schema_edu = SAT['edu']['schema'] schema_edu = SAT['edu']['schema']
schema_nomina = ''
if self._nomina:
name = 'xmlns:{}'.format(SAT['nomina']['prefix'])
attributes[name] = SAT['nomina']['xmlns']
schema_nomina = SAT['nomina']['schema']
attributes['xsi:schemaLocation'] = self._sat_cfdi['schema'] + \ attributes['xsi:schemaLocation'] = self._sat_cfdi['schema'] + \
schema_locales + schema_donativo + schema_ine + schema_edu schema_locales + schema_donativo + schema_ine + schema_edu + \
schema_nomina
attributes.update(datos) attributes.update(datos)
if not 'Version' in attributes: if not 'Version' in attributes:
@ -269,6 +265,9 @@ class CFDI(object):
return return
def _impuestos(self, datos): def _impuestos(self, datos):
if self._is_nomina:
return
if not datos: if not datos:
node_name = '{}:Impuestos'.format(self._pre) node_name = '{}:Impuestos'.format(self._pre)
ET.SubElement(self._cfdi, node_name) ET.SubElement(self._cfdi, node_name)
@ -294,38 +293,62 @@ class CFDI(object):
return return
def _nomina(self, datos): def _nomina(self, datos):
sat_nomina = SAT[NOMINA_ACTUAL] pre = SAT['nomina']['prefix']
pre = sat_nomina['prefix']
complemento = ET.SubElement(self._cfdi, '{}:Complemento'.format(self._pre))
emisor = datos.pop('Emisor', None) if self._complemento is None:
receptor = datos.pop('Receptor', None) self._complemento = ET.SubElement(
percepciones = datos.pop('Percepciones', None) self._cfdi, '{}:Complemento'.format(self._pre))
deducciones = datos.pop('Deducciones', None)
attributes = {} emisor = datos.pop('emisor', None)
attributes['xmlns:{}'.format(pre)] = sat_nomina['xmlns'] receptor = datos.pop('receptor', None)
attributes['xsi:schemaLocation'] = sat_nomina['schema'] percepciones = datos.pop('percepciones', None)
attributes.update(datos) deducciones = datos.pop('deducciones', None)
otros_pagos = datos.pop('otros_pagos', ())
incapacidades = datos.pop('incapacidades', ())
if not 'Version' in attributes: nomina = ET.SubElement(
attributes['Version'] = sat_nomina['version'] self._complemento, '{}:Nomina'.format(pre), datos['nomina'])
nomina = ET.SubElement(complemento, '{}:Nomina'.format(pre), attributes)
if emisor: if emisor:
ET.SubElement(nomina, '{}:Emisor'.format(pre), emisor) ET.SubElement(nomina, '{}:Emisor'.format(pre), emisor)
if receptor: if receptor:
ET.SubElement(nomina, '{}:Receptor'.format(pre), receptor) node = ET.SubElement(nomina, '{}:Receptor'.format(pre), receptor)
if percepciones: if percepciones:
detalle = percepciones.pop('detalle', None) details = percepciones.pop('details', None)
percepciones = ET.SubElement(nomina, '{}:Percepciones'.format(pre), percepciones) hours_extra = percepciones.pop('hours_extra', None)
for row in detalle: separacion = percepciones.pop('separacion', None)
ET.SubElement(percepciones, '{}:Percepcion'.format(pre), row) if details:
node = ET.SubElement(nomina, '{}:Percepciones'.format(pre), percepciones)
for row in details:
nodep = ET.SubElement(node, '{}:Percepcion'.format(pre), row)
if row['TipoPercepcion'] == '019' and hours_extra:
for he in hours_extra:
ET.SubElement(nodep, '{}:HorasExtra'.format(pre), he)
hours_extra = None
if separacion:
ET.SubElement(node, '{}:SeparacionIndemnizacion'.format(pre), separacion)
if deducciones: if deducciones:
detalle = deducciones.pop('detalle', None) details = deducciones.pop('details', None)
deducciones = ET.SubElement(nomina, '{}:Deducciones'.format(pre), deducciones) if details:
for row in detalle: deducciones = ET.SubElement(nomina, '{}:Deducciones'.format(pre), deducciones)
ET.SubElement(deducciones, '{}:Deduccion'.format(pre), row) for row in details:
ET.SubElement(deducciones, '{}:Deduccion'.format(pre), row)
if otros_pagos:
node = ET.SubElement(nomina, '{}:OtrosPagos'.format(pre))
for row in otros_pagos:
subsidio = row.pop('subsidio', None)
subnode = ET.SubElement(node, '{}:OtroPago'.format(pre), row)
if subsidio:
ET.SubElement(subnode, '{}:SubsidioAlEmpleo'.format(pre), subsidio)
if incapacidades:
node = ET.SubElement(nomina, '{}:Incapacidades'.format(pre))
for row in incapacidades:
ET.SubElement(node, '{}:Incapacidad'.format(pre), row)
return return
def _locales(self, datos): def _locales(self, datos):

View File

@ -0,0 +1,470 @@
#!/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',
},
'nomina': {
'version': '1.2',
'prefix': 'nomina12',
'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',
},
'locales': {
'version': '1.0',
'prefix': 'implocal',
'xmlns': 'http://www.sat.gob.mx/implocal',
'schema': ' http://www.sat.gob.mx/implocal http://www.sat.gob.mx/sitio_internet/cfd/implocal/implocal.xsd',
},
'donativo': {
'version': '1.1',
'prefix': 'donat',
'xmlns': 'http://www.sat.gob.mx/donat',
'schema': ' http://www.sat.gob.mx/donat http://www.sat.gob.mx/sitio_internet/cfd/donat/donat11.xsd',
'leyenda': 'Este comprobante ampara un donativo, el cual será destinado por la donataria a los fines propios de su objeto social. En el caso de que los bienes donados hayan sido deducidos previamente para los efectos del impuesto sobre la renta, este donativo no es deducible. La reproducción no autorizada de este comprobante constituye un delito en los términos de las disposiciones fiscales.',
},
'ine': {
'version': '1.1',
'prefix': 'ine',
'xmlns': 'http://www.sat.gob.mx/ine',
'schema': ' http://www.sat.gob.mx/ine http://www.sat.gob.mx/sitio_internet/cfd/ine/ine11.xsd',
},
'edu': {
'version': '1.0',
'prefix': 'iedu',
'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',
},
}
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._complemento = None
self._impuestos_locales = False
self._donativo = False
self._ine = False
<<<<<<< HEAD
self._edu = False
=======
self._is_nomina = False
>>>>>>> nomina
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._relacionados(datos['relacionados'])
self._emisor(datos['emisor'])
self._receptor(datos['receptor'])
self._conceptos(datos['conceptos'])
self._impuestos(datos['impuestos'])
self._locales(datos['impuestos'])
self._donatarias(datos['donativo'])
self._complementos(datos['complementos'])
if 'nomina' in datos:
self._nomina(datos['nomina'])
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 datos['impuestos']:
if datos['impuestos']['total_locales_trasladados'] or \
datos['impuestos']['total_locales_retenciones']:
self._impuestos_locales = True
if datos['donativo']:
self._donativo = True
if datos['complementos']:
if 'ine' in datos['complementos']:
self._ine = True
self._edu = datos['edu']
if 'nomina' in datos:
self._is_nomina = True
return self._validate_nomina(datos)
return True
def _validate_nomina(self, datos):
return True
def _comprobante(self, datos):
attributes = {}
attributes['xmlns:{}'.format(self._pre)] = self._sat_cfdi['xmlns']
attributes['xmlns:xsi'] = self._xsi
schema_locales = ''
if self._impuestos_locales:
name = 'xmlns:{}'.format(SAT['locales']['prefix'])
attributes[name] = SAT['locales']['xmlns']
schema_locales = SAT['locales']['schema']
schema_donativo = ''
if self._donativo:
name = 'xmlns:{}'.format(SAT['donativo']['prefix'])
attributes[name] = SAT['donativo']['xmlns']
schema_donativo = SAT['donativo']['schema']
schema_ine = ''
if self._ine:
name = 'xmlns:{}'.format(SAT['ine']['prefix'])
attributes[name] = SAT['ine']['xmlns']
schema_ine = SAT['ine']['schema']
<<<<<<< HEAD
schema_edu = ''
if self._edu:
name = 'xmlns:{}'.format(SAT['edu']['prefix'])
attributes[name] = SAT['edu']['xmlns']
schema_edu = SAT['edu']['schema']
attributes['xsi:schemaLocation'] = self._sat_cfdi['schema'] + \
schema_locales + schema_donativo + schema_ine + schema_edu
=======
schema_nomina = ''
if self._nomina:
name = 'xmlns:{}'.format(SAT['nomina']['prefix'])
attributes[name] = SAT['nomina']['xmlns']
schema_nomina = SAT['nomina']['schema']
attributes['xsi:schemaLocation'] = self._sat_cfdi['schema'] + \
schema_locales + schema_donativo + schema_ine + schema_nomina
>>>>>>> nomina
attributes.update(datos)
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 _relacionados(self, datos):
if not datos or not datos['tipo'] or not datos['cfdis']:
return
node_name = '{}:CfdiRelacionados'.format(self._pre)
value = {'TipoRelacion': datos['tipo']}
node = ET.SubElement(self._cfdi, node_name, value)
for uuid in datos['cfdis']:
node_name = '{}:CfdiRelacionado'.format(self._pre)
value = {'UUID': uuid}
ET.SubElement(node, node_name, value)
return
def _emisor(self, datos):
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):
from xml.sax.saxutils import escape, unescape
conceptos = ET.SubElement(self._cfdi, '{}:Conceptos'.format(self._pre))
for row in reversed(datos):
# ~ print (row['Descripcion'])
# ~ xml = escape(xml.encode('ascii', 'xmlcharrefreplace').decode('utf-8'), False)
# ~ row['Descripcion'] = escape(row['Descripcion'].replace('\n', '&#10;'), False)
# ~ row['Descripcion'] = row['Descripcion'].replace('\n', '&#xA;')
# ~ print (row['Descripcion'])
complemento = {}
if 'complemento' in row:
complemento = row.pop('complemento')
cuenta_predial = row.pop('CuentaPredial', '')
pedimento = row.pop('Pedimento', '')
student = row.pop('student', '')
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 pedimento:
attributes = {'NumeroPedimento': pedimento}
node_name = '{}:InformacionAduanera'.format(self._pre)
ET.SubElement(concepto, node_name, attributes)
if cuenta_predial:
attributes = {'Numero': cuenta_predial}
node_name = '{}:CuentaPredial'.format(self._pre)
ET.SubElement(concepto, node_name, attributes)
if student:
node_name = '{}:ComplementoConcepto'.format(self._pre)
complemento = ET.SubElement(concepto, node_name)
ET.SubElement(complemento, 'iedu:instEducativas', student)
return
def _impuestos(self, datos):
if self._is_nomina:
return
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):
pre = SAT['nomina']['prefix']
if self._complemento is None:
self._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)
otros_pagos = datos.pop('otros_pagos', ())
incapacidades = datos.pop('incapacidades', ())
nomina = ET.SubElement(
self._complemento, '{}:Nomina'.format(pre), datos['nomina'])
if emisor:
ET.SubElement(nomina, '{}:Emisor'.format(pre), emisor)
if receptor:
node = ET.SubElement(nomina, '{}:Receptor'.format(pre), receptor)
if percepciones:
details = percepciones.pop('details', None)
hours_extra = percepciones.pop('hours_extra', None)
separacion = percepciones.pop('separacion', None)
if details:
node = ET.SubElement(nomina, '{}:Percepciones'.format(pre), percepciones)
for row in details:
nodep = ET.SubElement(node, '{}:Percepcion'.format(pre), row)
if row['TipoPercepcion'] == '019' and hours_extra:
for he in hours_extra:
ET.SubElement(nodep, '{}:HorasExtra'.format(pre), he)
hours_extra = None
if separacion:
ET.SubElement(node, '{}:SeparacionIndemnizacion'.format(pre), separacion)
if deducciones:
details = deducciones.pop('details', None)
if details:
deducciones = ET.SubElement(nomina, '{}:Deducciones'.format(pre), deducciones)
for row in details:
ET.SubElement(deducciones, '{}:Deduccion'.format(pre), row)
if otros_pagos:
node = ET.SubElement(nomina, '{}:OtrosPagos'.format(pre))
for row in otros_pagos:
subsidio = row.pop('subsidio', None)
subnode = ET.SubElement(node, '{}:OtroPago'.format(pre), row)
if subsidio:
ET.SubElement(subnode, '{}:SubsidioAlEmpleo'.format(pre), subsidio)
if incapacidades:
node = ET.SubElement(nomina, '{}:Incapacidades'.format(pre))
for row in incapacidades:
ET.SubElement(node, '{}:Incapacidad'.format(pre), row)
return
def _locales(self, datos):
if not self._impuestos_locales:
return
if self._complemento is None:
self._complemento = ET.SubElement(
self._cfdi, '{}:Complemento'.format(self._pre))
attributes = {}
attributes['version'] = SAT['locales']['version']
if not datos['total_locales_trasladados']:
datos['total_locales_trasladados'] = '0.00'
attributes['TotaldeTraslados'] = datos['total_locales_trasladados']
if not datos['total_locales_retenciones']:
datos['total_locales_retenciones'] = '0.00'
attributes['TotaldeRetenciones'] = datos['total_locales_retenciones']
node = ET.SubElement(
self._complemento, 'implocal:ImpuestosLocales', attributes)
for retencion in datos['locales_retenciones']:
ET.SubElement(node, 'implocal:RetencionesLocales', retencion)
for traslado in datos['locales_trasladados']:
ET.SubElement(node, 'implocal:TrasladosLocales', traslado)
return
def _donatarias(self, datos):
if not datos:
return
if self._complemento is None:
self._complemento = ET.SubElement(
self._cfdi, '{}:Complemento'.format(self._pre))
attributes = {}
attributes['version'] = SAT['donativo']['version']
attributes['leyenda'] = SAT['donativo']['leyenda']
attributes.update(datos)
node = ET.SubElement(self._complemento, 'donat:Donatarias', attributes)
return
def _complementos(self, datos):
if not datos:
return
if self._complemento is None:
self._complemento = ET.SubElement(
self._cfdi, '{}:Complemento'.format(self._pre))
if 'ine' in datos:
atributos = {'Version': SAT['ine']['version']}
atributos.update(datos['ine'])
ET.SubElement(self._complemento, 'ine:INE', atributos)
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

View File

@ -426,6 +426,52 @@ class AppFolios(object):
resp.status = falcon.HTTP_204 resp.status = falcon.HTTP_204
class AppEmployees(object):
def __init__(self, db):
self._db = db
def on_get(self, req, resp):
values = req.params
req.context['result'] = self._db.get_employees(values)
resp.status = falcon.HTTP_200
def on_post(self, req, resp):
values = req.params
req.context['result'] = self._db.employees(values)
resp.status = falcon.HTTP_200
def on_delete(self, req, resp):
values = req.params
if self._db.delete('employee', values['id']):
resp.status = falcon.HTTP_200
else:
resp.status = falcon.HTTP_204
class AppNomina(object):
def __init__(self, db):
self._db = db
def on_get(self, req, resp):
values = req.params
req.context['result'] = self._db.get_nomina(values)
resp.status = falcon.HTTP_200
def on_post(self, req, resp):
values = req.params
req.context['result'] = self._db.nomina(values)
resp.status = falcon.HTTP_200
def on_delete(self, req, resp):
values = req.params
if self._db.delete('nomina', values['id']):
resp.status = falcon.HTTP_200
else:
resp.status = falcon.HTTP_204
class AppDocumentos(object): class AppDocumentos(object):
def __init__(self, db): def __init__(self, db):

View File

@ -174,8 +174,8 @@ class Finkok(object):
return return
def _check_result(self, method, result): def _check_result(self, method, result):
#~ print ('CODE', result.CodEstatus) # ~ print ('CODE', result.CodEstatus)
#~ print ('INCIDENCIAS', result.Incidencias) # ~ print ('INCIDENCIAS', result.Incidencias)
self.message = '' self.message = ''
MSG = { MSG = {
'OK': 'Comprobante timbrado satisfactoriamente', 'OK': 'Comprobante timbrado satisfactoriamente',
@ -184,8 +184,8 @@ class Finkok(object):
status = result.CodEstatus status = result.CodEstatus
if status is None and result.Incidencias: if status is None and result.Incidencias:
for i in result.Incidencias['Incidencia']: for i in result.Incidencias['Incidencia']:
self.error += 'Error: {}\n{}'.format( self.error += 'Error: {}\n{}\n{}'.format(
i['CodigoError'], i['MensajeIncidencia']) i['CodigoError'], i['MensajeIncidencia'], i['ExtraInfo'])
return '' return ''
if method == 'timbra' and status in (MSG['OK'], MSG['307']): if method == 'timbra' and status in (MSG['OK'], MSG['307']):

View File

@ -260,6 +260,14 @@ def get_file(path):
return open(path, 'rb') return open(path, 'rb')
def get_files(path, ext='xml'):
docs = []
for folder, _, files in os.walk(path):
pattern = re.compile('\.{}'.format(ext), re.IGNORECASE)
docs += [os.path.join(folder,f) for f in files if pattern.search(f)]
return tuple(docs)
def read_file(path, mode='rb'): def read_file(path, mode='rb'):
return open(path, mode).read() return open(path, mode).read()
@ -308,6 +316,10 @@ def loads(data):
return json.loads(data) return json.loads(data)
def import_json(path):
return loads(read_file(path, 'r'))
def clean(values): def clean(values):
for k, v in values.items(): for k, v in values.items():
if isinstance(v, str): if isinstance(v, str):
@ -748,8 +760,29 @@ class LIBO(object):
self._sheet.copyRange(nc.getCellAddress(), source.getRangeAddress()) self._sheet.copyRange(nc.getCellAddress(), source.getRangeAddress())
return return
def _copy_paste_rows(self, cell, count):
dispatch = self._create_instance('com.sun.star.frame.DispatchHelper')
row = cell.getCellAddress().Row
source = self._sheet.getRows().getByIndex(row)
self._template.getCurrentController().select(source)
frame = self._template.getCurrentController().getFrame()
dispatch.executeDispatch(frame, '.uno:Copy', '', 0, ())
target = self._sheet.getCellRangeByPosition(0, row + 1, 0, row + count)
self._template.getCurrentController().select(target)
dispatch.executeDispatch(frame, '.uno:Paste', '', 0, ())
return
def _conceptos(self, data): def _conceptos(self, data):
first = True first = True
col1 = []
col2 = []
col3 = []
col4 = []
col5 = []
col6 = []
count = len(data)-1
for concepto in data: for concepto in data:
key = concepto.get('noidentificacion', '') key = concepto.get('noidentificacion', '')
description = concepto['descripcion'] description = concepto['descripcion']
@ -767,16 +800,36 @@ class LIBO(object):
cell_6 = self._set_cell('{importe}', importe, value=True) cell_6 = self._set_cell('{importe}', importe, value=True)
if len(data) > 1: if len(data) > 1:
row = cell_1.getCellAddress().Row + 1 row = cell_1.getCellAddress().Row + 1
self._sheet.getRows().insertByIndex(row, len(data)-1) self._sheet.getRows().insertByIndex(row, count)
self._copy_paste_rows(cell_1, count)
row = cell_1.getCellAddress().Row
else: else:
self._copy_row(cell_1) col1.append((key,))
cell_1 = self._set_cell(v=key, cell=cell_1) col2.append((description,))
cell_2 = self._set_cell(v=description, cell=cell_2) col3.append((unidad,))
cell_3 = self._set_cell(v=unidad, cell=cell_3) col4.append((float(cantidad),))
cell_4 = self._set_cell(v=cantidad, cell=cell_4, value=True) col5.append((float(valor_unitario),))
cell_5 = self._set_cell(v=valor_unitario, cell=cell_5, value=True) col6.append((float(importe),))
cell_6 = self._set_cell(v=importe, cell=cell_6, value=True)
col = cell_1.getCellAddress().Column
target1 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
col = cell_2.getCellAddress().Column
target2 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
col = cell_3.getCellAddress().Column
target3 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
col = cell_4.getCellAddress().Column
target4 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
col = cell_5.getCellAddress().Column
target5 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
col = cell_6.getCellAddress().Column
target6 = self._sheet.getCellRangeByPosition(col, row+1, col, row+count)
target1.setFormulaArray(tuple(col1))
target2.setDataArray(tuple(col2))
target3.setFormulaArray(tuple(col3))
target4.setDataArray(tuple(col4))
target5.setDataArray(tuple(col5))
target6.setDataArray(tuple(col6))
return return
def _add_totales(self, data): def _add_totales(self, data):
@ -957,6 +1010,171 @@ class LIBO(object):
rows = [dict(zip(fields, r)) for r in data[1:]] rows = [dict(zip(fields, r)) for r in data[1:]]
return rows, '' return rows, ''
def employees(self, path):
options = {'AsTemplate': True, 'Hidden': True}
doc = self._doc_open(path, options)
if doc is None:
return ()
data, msg = self._get_data(doc, 'Empleados')
doc.close(True)
if len(data) == 1:
msg = 'Sin datos para importar'
return (), msg
fields = (
'num_empleado',
'rfc',
'curp',
'nombre',
'paterno',
'materno',
'fecha_ingreso',
'imss',
'tipo_contrato',
'es_sindicalizado',
'tipo_jornada',
'tipo_regimen',
'departamento',
'puesto',
'riesgo_puesto',
'periodicidad_pago',
'banco',
'cuenta_bancaria',
'clabe',
'salario_base',
'salario_diario',
'estado',
'codigo_postal',
'notas',
'correo',
)
rows = tuple([dict(zip(fields, r)) for r in data[1:]])
msg = 'Empleados importados correctamente'
return rows, msg
def _get_nomina(self, doc):
rows, msg = self._get_data(doc, 'Nomina')
if len(rows) == 2:
msg = 'Sin datos para importar'
return {}, msg
fields = (
'rfc',
'tipo_nomina',
'fecha_pago',
'fecha_inicial_pago',
'fecha_final_pago',
)
data = tuple([dict(zip(fields, r[1:])) for r in rows[2:]])
return data, ''
def _get_percepciones(self, doc, count):
rows, msg = self._get_data(doc, 'Percepciones')
if len(rows) == 2:
msg = 'Sin Percepciones'
return {}, msg
if len(rows[0][2:]) % 2:
msg = 'Las Percepciones deben ir en pares: Gravado y Exento'
return {}, msg
data = tuple([r[2:] for r in rows[:count+2]])
return data, ''
def _get_deducciones(self, doc, count):
rows, msg = self._get_data(doc, 'Deducciones')
if len(rows) == 2:
msg = 'Sin Deducciones'
return {}, msg
data = tuple([r[2:] for r in rows[:count+2]])
return data, ''
def _get_otros_pagos(self, doc, count):
rows, msg = self._get_data(doc, 'OtrosPagos')
if len(rows) == 2:
msg = 'Sin Otros Pagos'
return {}, msg
data = tuple([r[2:] for r in rows[:count+2]])
return data, ''
def _get_horas_extras(self, doc, count):
rows, msg = self._get_data(doc, 'HorasExtras')
if len(rows) == 2:
msg = 'Sin Horas Extras'
return {}, msg
if len(rows[1][1:]) % 4:
msg = 'Las Horas Extras deben ir grupos de 4 columnas'
return {}, msg
data = tuple([r[1:] for r in rows[:count+2]])
return data, ''
def _get_incapacidades(self, doc, count):
rows, msg = self._get_data(doc, 'Incapacidades')
if len(rows) == 2:
msg = 'Sin Incapacidades'
return {}, msg
if len(rows[1][1:]) % 3:
msg = 'Las Incapacidades deben ir grupos de 3 columnas'
return {}, msg
data = tuple([r[1:] for r in rows[:count+2]])
return data, ''
def nomina(self, path):
options = {'AsTemplate': True, 'Hidden': True}
doc = self._doc_open(path, options)
if doc is None:
msg = 'No se pudo abrir la plantilla'
return {}, msg
data = {}
nomina, msg = self._get_nomina(doc)
if msg:
doc.close(True)
return {}, msg
percepciones, msg = self._get_percepciones(doc, len(nomina))
if msg:
doc.close(True)
return {}, msg
deducciones, msg = self._get_deducciones(doc, len(nomina))
if msg:
doc.close(True)
return {}, msg
otros_pagos, msg = self._get_otros_pagos(doc, len(nomina))
if msg:
doc.close(True)
return {}, msg
horas_extras, msg = self._get_horas_extras(doc, len(nomina))
if msg:
doc.close(True)
return {}, msg
incapacidades, msg = self._get_incapacidades(doc, len(nomina))
if msg:
doc.close(True)
return {}, msg
doc.close(True)
data['nomina'] = nomina
data['percepciones'] = percepciones
data['deducciones'] = deducciones
data['otros_pagos'] = otros_pagos
data['horas_extras'] = horas_extras
data['incapacidades'] = incapacidades
return data, ''
def invoice(self, path): def invoice(self, path):
options = {'AsTemplate': True, 'Hidden': True} options = {'AsTemplate': True, 'Hidden': True}
doc = self._doc_open(path, options) doc = self._doc_open(path, options)
@ -1002,6 +1220,34 @@ def to_pdf(data, emisor_rfc, ods=False):
return read_file(path) return read_file(path)
def import_employees(rfc):
name = '{}_employees.ods'.format(rfc.lower())
path = _join(PATH_MEDIA, 'tmp', name)
if not is_file(path):
return ()
if APP_LIBO:
app = LIBO()
if app.is_running:
return app.employees(path)
return ()
def import_nomina(rfc):
name = '{}_nomina.ods'.format(rfc.lower())
path = _join(PATH_MEDIA, 'tmp', name)
if not is_file(path):
return ()
if APP_LIBO:
app = LIBO()
if app.is_running:
return app.nomina(path)
return ()
def parse_xml(xml): def parse_xml(xml):
return ET.fromstring(xml) return ET.fromstring(xml)
@ -1432,6 +1678,32 @@ def upload_file(rfc, opt, file_obj):
name = '{}_invoice.ods'.format(rfc.lower()) name = '{}_invoice.ods'.format(rfc.lower())
path = _join(PATH_MEDIA, 'tmp', name) path = _join(PATH_MEDIA, 'tmp', name)
elif opt == 'employees':
tmp = file_obj.filename.split('.')
ext = tmp[-1].lower()
if ext != 'ods':
msg = 'Extensión de archivo incorrecta, selecciona un archivo ODS'
return {'status': 'server', 'name': msg, 'ok': False}
name = '{}_employees.ods'.format(rfc.lower())
path = _join(PATH_MEDIA, 'tmp', name)
elif opt == 'nomina':
tmp = file_obj.filename.split('.')
ext = tmp[-1].lower()
if ext != 'ods':
msg = 'Extensión de archivo incorrecta, selecciona un archivo ODS'
return {'status': 'server', 'name': msg, 'ok': False}
name = '{}_nomina.ods'.format(rfc.lower())
path = _join(PATH_MEDIA, 'tmp', name)
elif opt == 'cfdixml':
tmp = file_obj.filename.split('.')
ext = tmp[-1].lower()
if ext != 'xml':
msg = 'Extensión de archivo incorrecta, selecciona un archivo XML'
return {'status': 'server', 'name': msg, 'ok': False}
return import_xml(file_obj.file.read())
if save_file(path, file_obj.file.read()): if save_file(path, file_obj.file.read()):
return {'status': 'server', 'name': file_obj.filename, 'ok': True} return {'status': 'server', 'name': file_obj.filename, 'ok': True}
@ -2686,3 +2958,43 @@ def import_invoice(rfc):
return (), 'No se encontro LibreOffice' return (), 'No se encontro LibreOffice'
def calc_to_date(value):
return datetime.date.fromordinal(int(value) + 693594)
def get_days(start, end):
return (end - start).days + 1
def log_file(name, msg='', kill=False):
path = _join(PATH_MEDIA, 'tmp', '{}.log'.format(name))
if kill:
_kill(path)
return
with open(path, 'a') as fh:
line = '{} : {}\n'.format(str(now()), msg)
fh.write(line)
return
def get_log(name):
data = ''
name = '{}.log'.format(name)
path = _join(PATH_MEDIA, 'tmp', name)
if is_file(path):
data = open(path).read()
return data, name
def import_xml(stream):
try:
xml = ET.fromstring(stream.decode())
except ET.ParseError:
return {'ok': False, 'status': 'error'}
print (xml)
return {'ok': True, 'status': 'server'}

View File

@ -16,7 +16,7 @@ from controllers.main import (AppEmpresas,
AppLogin, AppLogout, AppAdmin, AppEmisor, AppConfig, AppLogin, AppLogout, AppAdmin, AppEmisor, AppConfig,
AppMain, AppValues, AppPartners, AppProducts, AppInvoices, AppFolios, AppMain, AppValues, AppPartners, AppProducts, AppInvoices, AppFolios,
AppDocumentos, AppFiles, AppPreInvoices, AppCuentasBanco, AppDocumentos, AppFiles, AppPreInvoices, AppCuentasBanco,
AppMovimientosBanco, AppTickets, AppStudents AppMovimientosBanco, AppTickets, AppStudents, AppEmployees, AppNomina
) )
@ -53,6 +53,8 @@ api.add_route('/tickets', AppTickets(db))
api.add_route('/cuentasbanco', AppCuentasBanco(db)) api.add_route('/cuentasbanco', AppCuentasBanco(db))
api.add_route('/movbanco', AppMovimientosBanco(db)) api.add_route('/movbanco', AppMovimientosBanco(db))
api.add_route('/students', AppStudents(db)) api.add_route('/students', AppStudents(db))
api.add_route('/employees', AppEmployees(db))
api.add_route('/nomina', AppNomina(db))
# ~ Activa si usas waitress y NO estas usando servidor web # ~ Activa si usas waitress y NO estas usando servidor web

82
source/app/main.py.orig Normal file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env python3
import falcon
from falcon_multipart.middleware import MultipartMiddleware
from beaker.middleware import SessionMiddleware
from middleware import (
AuthMiddleware,
JSONTranslator,
ConnectionMiddleware,
static,
handle_404
)
from models.db import StorageEngine
from controllers.main import (AppEmpresas,
AppLogin, AppLogout, AppAdmin, AppEmisor, AppConfig,
AppMain, AppValues, AppPartners, AppProducts, AppInvoices, AppFolios,
AppDocumentos, AppFiles, AppPreInvoices, AppCuentasBanco,
<<<<<<< HEAD
AppMovimientosBanco, AppTickets, AppStudents
=======
AppMovimientosBanco, AppTickets, AppEmployees, AppNomina
>>>>>>> nomina
)
from settings import DEBUG, MV, PATH_SESSIONS
db = StorageEngine()
api = falcon.API(middleware=[
AuthMiddleware(),
JSONTranslator(),
ConnectionMiddleware(),
MultipartMiddleware(),
])
api.req_options.auto_parse_form_urlencoded = True
api.add_sink(handle_404, '')
api.add_route('/empresas', AppEmpresas(db))
api.add_route('/', AppLogin(db))
api.add_route('/logout', AppLogout(db))
api.add_route('/admin', AppAdmin(db))
api.add_route('/emisor', AppEmisor(db))
api.add_route('/folios', AppFolios(db))
api.add_route('/main', AppMain(db))
api.add_route('/values/{table}', AppValues(db))
api.add_route('/files/{table}', AppFiles(db))
api.add_route('/config', AppConfig(db))
api.add_route('/doc/{type_doc}/{id_doc}', AppDocumentos(db))
api.add_route('/partners', AppPartners(db))
api.add_route('/products', AppProducts(db))
api.add_route('/invoices', AppInvoices(db))
api.add_route('/preinvoices', AppPreInvoices(db))
api.add_route('/tickets', AppTickets(db))
api.add_route('/cuentasbanco', AppCuentasBanco(db))
api.add_route('/movbanco', AppMovimientosBanco(db))
<<<<<<< HEAD
api.add_route('/students', AppStudents(db))
=======
api.add_route('/employees', AppEmployees(db))
api.add_route('/nomina', AppNomina(db))
>>>>>>> nomina
# ~ Activa si usas waitress y NO estas usando servidor web
# ~ api.add_sink(static, '/static')
session_options = {
'session.type': 'file',
'session.cookie_expires': True,
'session.httponly': True,
'session.secure': True,
'session.data_dir': PATH_SESSIONS['data'],
'session.lock_dir': PATH_SESSIONS['lock'],
}
if DEBUG or MV:
session_options['session.secure'] = False
app = SessionMiddleware(api, session_options)

View File

@ -11,6 +11,17 @@ class StorageEngine(object):
def authenticate(self, args): def authenticate(self, args):
return main.authenticate(args) return main.authenticate(args)
def get_employees(self, values):
return main.Empleados.get_by(values)
def get_nomina(self, values):
return main.CfdiNomina.get_by(values)
def nomina(self, values):
opt = values.pop('opt')
if opt == 'cancel':
return main.CfdiNomina.cancel(int(values['id']))
def empresa_agregar(self, values): def empresa_agregar(self, values):
return main.empresa_agregar(values['alta_rfc'], False) return main.empresa_agregar(values['alta_rfc'], False)
@ -107,6 +118,9 @@ class StorageEngine(object):
def _get_filteryearsticket(self, values): def _get_filteryearsticket(self, values):
return main.Tickets.filter_years() return main.Tickets.filter_years()
def _get_filteryearsnomina(self, values):
return main.CfdiNomina.filter_years()
def _get_cuentayears(self, values): def _get_cuentayears(self, values):
return main.CuentasBanco.get_years() return main.CuentasBanco.get_years()
@ -257,6 +271,10 @@ class StorageEngine(object):
return main.NivelesEducativos.remove(id) return main.NivelesEducativos.remove(id)
if table == 'students': if table == 'students':
return main.Alumnos.remove(id) return main.Alumnos.remove(id)
if table == 'employee':
return main.Empleados.remove(id)
if table == 'nomina':
return main.CfdiNomina.remove(id)
return False return False
def _get_client(self, values): def _get_client(self, values):

View File

@ -0,0 +1,398 @@
#!/usr/bin/env python
from . import main
class StorageEngine(object):
def __init__(self):
pass
def authenticate(self, args):
return main.authenticate(args)
def get_employees(self, values):
return main.Empleados.get_by(values)
def get_nomina(self, values):
return main.CfdiNomina.get_by(values)
def nomina(self, values):
opt = values.pop('opt')
if opt == 'cancel':
return main.CfdiNomina.cancel(int(values['id']))
def empresa_agregar(self, values):
return main.empresa_agregar(values['alta_rfc'], False)
def empresa_borrar(self, values):
return main.empresa_borrar(values['rfc'])
def _get_empresas(self, values):
return main.get_empresas()
def get_values(self, table, values=None, session=None):
if table in ('allusuarios', 'usuarioupdate'):
return getattr(self, '_get_{}'.format(table))(values, session)
return getattr(self, '_get_{}'.format(table))(values)
def _get_schoolgroups(self, values):
return main.Grupos.get_by(values)
def _get_nivedusat(self, values):
return main.SATNivelesEducativos.get_by()
def _get_niveduall(self, values):
return main.NivelesEducativos.get_all()
def _get_titlelogin(self, values):
return main.get_title_app(2)
def _get_canopenpre(self, values):
return main.PreFacturasDetalle.can_open(values['id'])
def _get_importinvoice(self, values):
return main.import_invoice()
def _get_main(self, values):
return main.config_main()
def _get_configtimbrar(self, values):
return main.config_timbrar()
def _get_invoicenotes(self, values):
return main.Facturas.get_notes(values['id'])
def save_invoice_notes(self, values):
return main.Facturas.save_notes(values)
def _get_configticket(self, values):
return main.config_ticket()
def _get_saldocuenta(self, values):
return main.CuentasBanco.get_saldo(values['id'])
def _get_validartimbrar(self, values):
return main.validar_timbrar()
def _get_preproductos(self, values):
return main.PreFacturasDetalle.facturar(values['id'])
def upload_file(self, session, table, file_obj):
if not 'rfc' in session:
return {'status': 'error'}
return main.upload_file(session['rfc'], table, file_obj)
def get_config(self, values):
return main.Configuracion.get_(values)
def add_config(self, values):
return main.Configuracion.add(values)
def add_cert(self, file_obj):
return main.Certificado.add(file_obj)
def validate_cert(self, values, session):
return main.Certificado.validate(values, session)
def validate_email(self, values):
return main.test_correo(values)
def send_email(self, values, session):
return main.Facturas.send(values['id'], session['rfc'])
def enviar_prefac(self, values):
return main.PreFacturas.enviar(values['id'])
def _get_cancelinvoice(self, values):
return main.Facturas.cancel(values['id'])
def _get_statussat(self, values):
return main.Facturas.get_status_sat(values['id'])
def _get_filteryears(self, values):
years1 = main.Facturas.filter_years()
years2 = main.PreFacturas.filter_years()
return [years1, years2]
def _get_filteryearsticket(self, values):
return main.Tickets.filter_years()
def _get_filteryearsnomina(self, values):
return main.CfdiNomina.filter_years()
def _get_cuentayears(self, values):
return main.CuentasBanco.get_years()
def _get_cert(self, values):
return main.Certificado.get_data()
def _get_cp(self, values):
return main.get_cp(values['cp'])
def _get_formapago(self, values):
return main.SATFormaPago.get_activos(values)
def _get_tiporelacion(self, values):
return main.SATTipoRelacion.get_activos(values)
def _get_condicionespago(self, values):
return main.CondicionesPago.get_()
def _get_categorias(self, values):
return main.Categorias.get_all()
def _get_newkey(self, values):
return main.Productos.next_key()
def _get_unidades(self, values):
return main.SATUnidades.get_activos()
def add_moneda(self, values):
return main.SATMonedas.add(values)
def add_unidad(self, values):
return main.SATUnidades.add(values)
def add_impuesto(self, values):
return main.SATImpuestos.add(values)
def add_usuario(self, values):
return main.Usuarios.add(values)
def edit_usuario(self, values):
return main.Usuarios.edit(values)
def _get_taxes(self, values):
return main.SATImpuestos.get_activos()
def _get_alltaxes(self, values):
return main.SATImpuestos.get_()
def _get_allcurrencies(self, values):
return main.SATMonedas.get_()
def _get_allbancos(self, values):
return main.SATBancos.get_()
def _get_allunidades(self, values):
return main.SATUnidades.get_()
def _get_allformasdepago(self, values):
return main.SATFormaPago.get_()
def _get_allusoscfdi(self, values):
return main.SATUsoCfdi.get_all()
def _get_allusuarios(self, values, session):
return main.Usuarios.get_(session['userobj'])
def _get_usuarioupdate(self, values, session):
return main.Usuarios.actualizar(values, session['userobj'])
def _get_taxupdate(self, values):
return main.SATImpuestos.actualizar(values)
def _get_currencyupdate(self, values):
return main.SATMonedas.actualizar(values)
def _get_bancoupdate(self, values):
return main.SATBancos.actualizar(values)
def _get_unidadupdate(self, values):
return main.SATUnidades.actualizar(values)
def _get_formasdepagoupdate(self, values):
return main.SATFormaPago.actualizar(values)
def _get_usocfdiupdate(self, values):
return main.SATUsoCfdi.actualizar(values)
def _get_emisorcuentasbanco(self, values):
return main.CuentasBanco.emisor()
def _get_satkey(self, values):
return main.get_sat_key(values['key'])
def _get_satmonedas(self, values):
return main.get_sat_monedas(values['key'])
def _get_satunidades(self, values):
return main.get_sat_unidades(values['key'])
def _get_satproductos(self, values):
return main.get_sat_productos(values['key'])
def _get_series(self, values):
return main.Folios.get_all()
def _get_monedas(self, values):
return main.SATMonedas.get_activos()
def _get_monedasid(self, values):
return main.SATMonedas.get_activos_by_id()
def _get_bancosid(self, values):
return main.SATBancos.get_activos_by_id()
def _get_regimenes(self, values):
return main.Emisor.get_regimenes()
def _get_usocfdi(self, values):
return main.SATUsoCfdi.get_activos()
def _get_ebancomov(self, values):
return main.MovimientosBanco.con(values['id'])
def delete(self, table, id):
if table == 'partner':
return main.Socios.remove(id)
if table == 'product':
return main.Productos.remove(id)
if table == 'invoice':
return main.Facturas.remove(id)
if table == 'folios':
return main.Folios.remove(id)
if table == 'preinvoice':
return main.PreFacturas.remove(id)
if table == 'satimpuesto':
return main.SATImpuestos.remove(id)
if table == 'satunit':
return main.SATUnidades.remove(id)
if table == 'cuentasbanco':
return main.CuentasBanco.remove(id)
if table == 'movbanco':
return main.MovimientosBanco.remove(id)
if table == 'usuario':
return main.Usuarios.remove(id)
if table == 'config':
return main.Configuracion.remove(id)
<<<<<<< HEAD
if table == 'nivedu':
return main.NivelesEducativos.remove(id)
if table == 'students':
return main.Alumnos.remove(id)
=======
if table == 'employee':
return main.Empleados.remove(id)
if table == 'nomina':
return main.CfdiNomina.remove(id)
>>>>>>> nomina
return False
def _get_client(self, values):
return main.Socios.get_by_client(values)
def _get_student(self, values):
return main.Alumnos.get_by_name(values)
def _get_product(self, values):
return main.Productos.get_by(values)
def _get_productokey(self, values):
return main.Productos.get_by_key(values)
def get_partners(self, values):
return main.Socios.get_(values)
def partner(self, values):
id = int(values.pop('id', '0'))
if id:
return main.Socios.actualizar(values, id)
return main.Socios.add(values)
def get_products(self, values):
return main.Productos.get_(values)
def products(self, values):
id = int(values.pop('id', '0'))
if id:
return main.Productos.actualizar(values, id)
opt = values.get('opt', '')
if opt:
return main.Productos.opt(values)
return main.Productos.add(values)
def invoice(self, values, user):
id = int(values.pop('id', '0'))
if id:
return main.Facturas.actualizar(values, id)
return main.Facturas.add(values, user)
def preinvoice(self, values):
id = int(values.pop('id', '0'))
#~ if id:
#~ return main.PreFacturas.actualizar(values, id)
return main.PreFacturas.add(values)
def get_students(self, values):
return main.Alumnos.get_by(values)
def students(self, values):
opt = values.pop('opt')
if opt == 'add':
return main.Alumnos.add(values['values'])
if opt == 'edit':
return main.Alumnos.actualizar(values['values'])
def tickets(self, values, user):
opt = values.pop('opt')
if opt == 'add':
return main.Tickets.add(values, user)
if opt == 'cancel':
return main.Tickets.cancel(values)
if opt == 'invoice':
return main.Tickets.invoice(values, user)
if opt == 'print':
return main.Tickets.printer(values)
def get_tickets(self, values):
return main.Tickets.get_by(values)
def get_invoices(self, values):
return main.Facturas.get_(values)
def get_preinvoices(self, values):
return main.PreFacturas.get_(values)
def _get_timbrar(self, values):
return main.Facturas.timbrar(int(values['id']))
def _get_anticipoegreso(self, values):
return main.Facturas.anticipo_egreso(int(values['id']))
def get_emisor(self, rfc):
return main.Emisor.get_(rfc)
def emisor(self, values):
return main.Emisor.add(values)
def cuentasbanco(self, values):
return main.CuentasBanco.add(values)
def add_movbanco(self, values):
return main.MovimientosBanco.add(values)
def get_cuentasbanco(self, values):
return main.CuentasBanco.get_(values)
def get_folios(self):
return main.Folios.get_()
def add_folios(self, values):
return main.Folios.add(values)
def add_nivel_educativo(self, values):
return main.NivelesEducativos.add(values)
def get_doc(self, type_doc, id, rfc):
return main.get_doc(type_doc, id, rfc)
def get_movimientosbanco(self, values):
return main.MovimientosBanco.get_(values)
def importar_bdfl(self):
return main.importar_bdfl()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -115,6 +115,7 @@ PRE = {
} }
CURRENT_CFDI = '3.3' CURRENT_CFDI = '3.3'
CURRENT_CFDI_NOMINA = '1.2'
DECIMALES = 2 DECIMALES = 2
DECIMALES_TAX = 4 DECIMALES_TAX = 4
IMPUESTOS = { IMPUESTOS = {
@ -134,4 +135,12 @@ DEFAULT_SERIE_TICKET = 'T'
DIR_FACTURAS = 'facturas' DIR_FACTURAS = 'facturas'
USAR_TOKEN = False USAR_TOKEN = False
CANCEL_SIGNATURE = False CANCEL_SIGNATURE = False
PUBLIC = 'Público en general' PUBLIC = 'Público en general'
DEFAULT_SAT_NOMINA = {
'SERIE': 'N',
'FORMA_PAGO': '99',
'USO_CFDI': 'P01',
'CLAVE': '84111505',
'UNIDAD': 'ACT',
'DESCRIPCION': 'Pago de nómina',
}

File diff suppressed because it is too large Load Diff

View File

@ -75,9 +75,14 @@ var controllers = {
$$('chk_ticket_edit_cant').attachEvent('onItemClick', chk_config_item_click) $$('chk_ticket_edit_cant').attachEvent('onItemClick', chk_config_item_click)
$$('chk_ticket_total_up').attachEvent('onItemClick', chk_config_item_click) $$('chk_ticket_total_up').attachEvent('onItemClick', chk_config_item_click)
$$('txt_ticket_printer').attachEvent('onKeyPress', txt_ticket_printer_key_press) $$('txt_ticket_printer').attachEvent('onKeyPress', txt_ticket_printer_key_press)
$$('txt_config_nomina_serie').attachEvent('onKeyPress', txt_config_nomina_serie_press)
$$('txt_config_nomina_folio').attachEvent('onKeyPress', txt_config_nomina_folio_press)
$$('chk_usar_nomina').attachEvent('onItemClick', chk_config_item_click)
$$('cmd_subir_bdfl').attachEvent('onItemClick', cmd_subir_bdfl_click) $$('cmd_subir_bdfl').attachEvent('onItemClick', cmd_subir_bdfl_click)
$$('cmd_subir_cfdixml').attachEvent('onItemClick', cmd_subir_cfdixml_click)
$$('up_bdfl').attachEvent('onUploadComplete', up_bdfl_upload_complete) $$('up_bdfl').attachEvent('onUploadComplete', up_bdfl_upload_complete)
$$('up_cfdixml').attachEvent('onUploadComplete', up_cfdixml_upload_complete)
} }
} }
@ -198,6 +203,9 @@ function get_emisor(){
if(emisor.regimenes){ if(emisor.regimenes){
$$('lst_emisor_regimen').select(emisor.regimenes) $$('lst_emisor_regimen').select(emisor.regimenes)
} }
if(emisor.emisor_rfc.length == 12){
show('emisor_curp', false)
}
}else{ }else{
msg_error(values.msg) msg_error(values.msg)
} }
@ -1014,8 +1022,8 @@ function txt_plantilla_donataria_click(e){
function tab_options_change(nv, ov){ function tab_options_change(nv, ov){
var cv = { var cv = {
Plantillas: 'templates', tab_admin_templates: 'templates',
Otros: 'configotros', tab_admin_otros: 'configotros',
} }
get_config_values(cv[nv]) get_config_values(cv[nv])
} }
@ -1589,6 +1597,69 @@ function up_bdfl_upload_complete(response){
} }
function cmd_subir_cfdixml_click(){
var form = $$('form_upload_cfdixml')
if (!form.validate()){
msg = 'Valores inválidos'
msg_error(msg)
return
}
var values = form.getValues()
if($$('lst_cfdixml').count() < 1){
msg = 'Selecciona un archivo XML'
msg_error(msg)
return
}
if($$('lst_cfdixml').count() > 1){
msg = 'Selecciona solo un archivo'
msg_error(msg)
return
}
var cfdixml = $$('up_cfdixml').files.getItem($$('up_cfdixml').files.getFirstId())
var ext = []
if(cfdixml.type.toLowerCase() != 'xml'){
msg = 'Archivo inválido, se requiere un archivo XML'
msg_error(msg)
return
}
msg = '¿Estás seguro de subir este archivo?'
webix.confirm({
title: 'Importar CFDI',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if(result){
$$('up_cfdixml').send()
}
}
})
}
function up_cfdixml_upload_complete(response){
if(response.status != 'server'){
msg = 'Ocurrio un error al subir los archivos'
msg_error(msg)
return
}
msg = 'Archivo importado correctamente'
msg_ok(msg)
$$('form_upload_cfdixml').setValues({})
$$('up_cfdixml').files.data.clearAll()
}
function cmd_usuario_agregar_click(){ function cmd_usuario_agregar_click(){
var form = $$('form_usuario') var form = $$('form_usuario')
@ -1839,6 +1910,88 @@ function txt_ticket_printer_key_press(code, e){
} }
function txt_config_nomina_serie_press(code, e){
var value = this.getValue()
if(code != 13){
return
}
if(!value.trim()){
webix.ajax().del('/config', {id: 'txt_config_nomina_serie'}, function(text, xml, xhr){
var msg = 'Serie de Nómina borrado correctamente'
if(xhr.status == 200){
msg_ok(msg)
}else{
msg = 'No se pudo eliminar'
msg_error(msg)
}
})
return
}
webix.ajax().post('/config', {'txt_config_nomina_serie': value.toUpperCase()}, {
error: function(text, data, xhr) {
msg = 'Error al guardar la configuración'
msg_error(msg)
},
success: function(text, data, xhr) {
var values = data.json();
if (values.ok){
msg = 'Serie de Nómina guardada correctamente'
msg_ok(msg)
}else{
msg_error(values.msg)
}
}
})
}
function txt_config_nomina_folio_press(code, e){
var value = this.getValue()
if(code != 13){
return
}
if(!value.trim()){
webix.ajax().del('/config', {id: 'txt_config_nomina_folio'}, function(text, xml, xhr){
var msg = 'Folio de Nómina borrado correctamente'
if(xhr.status == 200){
msg_ok(msg)
}else{
msg = 'No se pudo eliminar'
msg_error(msg)
}
})
return
}
if(!value.trim().is_number()){
msg = 'El Folio de Nómina debe ser un número'
msg_error(msg)
return
}
webix.ajax().post('/config', {'txt_config_nomina_folio': value}, {
error: function(text, data, xhr) {
msg = 'Error al guardar la configuración'
msg_error(msg)
},
success: function(text, data, xhr) {
var values = data.json();
if (values.ok){
msg = 'Folio de Nómina guardado correctamente'
msg_ok(msg)
}else{
msg_error(values.msg)
}
}
})
}
function cmd_niveles_educativos_click(){ function cmd_niveles_educativos_click(){
admin_ui_niveles_educativos.init() admin_ui_niveles_educativos.init()
$$('win_niveles_educativos').show() $$('win_niveles_educativos').show()

View File

@ -1617,7 +1617,8 @@ function generate_pdf(id){
function grid_preinvoices_click(id, e, node){ function grid_preinvoices_click(id, e, node){
if(id.column == 'pdf'){ if(id.column == 'pdf'){
generate_pdf(id.row) //~ generate_pdf(id.row)
window.open('/doc/pre/' + id, '_blank')
}else if(id.column == 'email'){ }else if(id.column == 'email'){
enviar_prefactura(id) enviar_prefactura(id)
} }

View File

@ -9,7 +9,6 @@ function configuracion_inicial(){
webix.ajax().get('/values/main', function(text, data){ webix.ajax().get('/values/main', function(text, data){
var values = data.json() var values = data.json()
$$('lbl_title_main').setValue(values.empresa) $$('lbl_title_main').setValue(values.empresa)
//~ showvar()
var pos = 4 var pos = 4
if(values.escuela){ if(values.escuela){
var node = { var node = {
@ -19,6 +18,14 @@ function configuracion_inicial(){
$$('main_sidebar').add(node, pos) $$('main_sidebar').add(node, pos)
pos += 1 pos += 1
} }
if(values.nomina){
var node = {
id: 'app_nomina',
icon: 'users',
value: 'Nómina'}
$$('main_sidebar').add(node, pos)
pos += 1
}
if(values.punto_de_venta){ if(values.punto_de_venta){
var node = { var node = {
id: 'app_tickets', id: 'app_tickets',
@ -55,6 +62,7 @@ var controllers = {
bancos_controllers.init() bancos_controllers.init()
invoices_controllers.init() invoices_controllers.init()
controllers_school.init() controllers_school.init()
nomina_controllers.init()
tickets_controllers.init() tickets_controllers.init()
} }
} }
@ -156,6 +164,14 @@ function multi_change(prevID, nextID){
return return
} }
if(nextID == 'app_nomina'){
active = $$('multi_nomina').getActiveId()
if(active == 'nomina_home'){
default_config_nomina()
}
return
}
if(nextID == 'app_tickets'){ if(nextID == 'app_tickets'){
active = $$('multi_tickets').getActiveId() active = $$('multi_tickets').getActiveId()
if(active == 'tickets_home'){ if(active == 'tickets_home'){

View File

@ -0,0 +1,210 @@
var gi = null
function configuracion_inicial(){
webix.ajax().get('/values/admin', function(text, data){
var values = data.json()
show('cmd_ir_al_admin', values)
})
webix.ajax().get('/values/main', function(text, data){
var values = data.json()
$$('lbl_title_main').setValue(values.empresa)
<<<<<<< HEAD
//~ showvar()
var pos = 4
if(values.escuela){
var node = {
id: 'app_school',
icon: 'graduation-cap',
value: 'Escuela'}
=======
var pos = 4
if(values.nomina){
var node = {
id: 'app_nomina',
icon: 'users',
value: 'Nómina'}
>>>>>>> nomina
$$('main_sidebar').add(node, pos)
pos += 1
}
if(values.punto_de_venta){
var node = {
id: 'app_tickets',
icon: 'money',
value: 'Punto de venta'}
$$('main_sidebar').add(node, pos)
}
})
}
function cmd_ir_al_admin_click(){
window.location = '/admin'
}
var controllers = {
init: function(){
//~ Main
$$('menu_user').attachEvent('onMenuItemClick', menu_user_click);
configuracion_inicial()
var tb_invoice = $$('tv_invoice').getTabbar()
tb_invoice.attachEvent('onChange', tb_invoice_change)
$$('prefilter_year').attachEvent('onChange', prefilter_year_change)
$$('prefilter_month').attachEvent('onChange', prefilter_month_change)
$$('cmd_delete_preinvoice').attachEvent('onItemClick', cmd_delete_preinvoice_click)
$$('cmd_facturar_preinvoice').attachEvent('onItemClick', cmd_facturar_preinvoice_click)
$$('grid_preinvoices').attachEvent('onItemClick', grid_preinvoices_click)
partners_controllers.init()
products_controllers.init()
bancos_controllers.init()
invoices_controllers.init()
<<<<<<< HEAD
controllers_school.init()
=======
nomina_controllers.init()
>>>>>>> nomina
tickets_controllers.init()
}
}
function get_uso_cfdi_to_table(){
webix.ajax().sync().get('/values/usocfdi', function(text, data){
var values = data.json()
table_usocfdi.clear()
table_usocfdi.insert(values)
})
}
function get_partners(){
webix.ajax().get('/partners', {}, {
error: function(text, data, xhr) {
msg_error('Error al consultar')
},
success: function(text, data, xhr) {
var values = data.json();
$$('grid_partners').clearAll();
if (values.data){
$$('grid_partners').parse(values.data, 'json');
};
}
})
}
function menu_user_click(id, e, node){
if (id == 1){
window.location = '/logout';
return
}
}
function current_dates(){
var fy = $$('filter_year')
var fm = $$('filter_month')
var pfy = $$('prefilter_year')
var pfm = $$('prefilter_month')
var d = new Date()
fy.blockEvent()
fm.blockEvent()
pfy.blockEvent()
pfm.blockEvent()
fm.setValue(d.getMonth() + 1)
pfm.setValue(d.getMonth() + 1)
webix.ajax().sync().get('/values/filteryears', function(text, data){
var values = data.json()
fy.getList().parse(values[0])
pfy.getList().parse(values[1])
fy.setValue(d.getFullYear())
pfy.setValue(d.getFullYear())
})
fy.unblockEvent()
fm.unblockEvent()
pfy.unblockEvent()
pfm.unblockEvent()
}
function multi_change(prevID, nextID){
if(nextID == 'app_partners'){
active = $$('multi_partners').getActiveId()
if(active == 'partners_home'){
get_partners()
}
return
}
if(nextID == 'app_products'){
active = $$('multi_products').getActiveId()
if(active == 'products_home'){
get_products()
}
return
}
if(nextID == 'app_bancos'){
active = $$('multi_bancos').getActiveId()
if(active == 'banco_home'){
get_cuentas_banco()
}
return
}
if(nextID == 'app_school'){
active = $$('multi_school').getActiveId()
if(active == 'school_home'){
init_config_school()
}
return
}
if(nextID == 'app_tickets'){
active = $$('multi_tickets').getActiveId()
if(active == 'tickets_home'){
configuracion_inicial_ticket()
}
return
}
if(nextID == 'app_nomina'){
active = $$('multi_nomina').getActiveId()
if(active == 'nomina_home'){
default_config_nomina()
}
return
}
if(nextID == 'app_invoices'){
active = $$('multi_invoices').getActiveId()
if(active == 'invoices_home'){
current_dates()
get_invoices()
validar_timbrar()
}
gi = $$('grid_invoices')
return
}
}
function get_taxes(){
webix.ajax().sync().get('/values/taxes', function(text, data){
var values = data.json()
table_taxes.clear()
table_taxes.insert(values)
$$("grid_product_taxes").clearAll()
$$("grid_product_taxes").parse(values, 'json')
})
}

View File

@ -0,0 +1,485 @@
var query = []
var cfg_nomina = new Object()
var nomina_controllers = {
init: function(){
$$('cmd_nomina_import').attachEvent('onItemClick', cmd_nomina_import_click)
$$('cmd_empleados').attachEvent('onItemClick', cmd_empleados_click)
$$('cmd_close_empleados').attachEvent('onItemClick', cmd_close_empleados_click)
$$('cmd_delete_empleado').attachEvent('onItemClick', cmd_delete_empleado_click)
$$('cmd_import_empleados').attachEvent('onItemClick', cmd_import_empleados_click)
$$('cmd_nomina_without_stamp').attachEvent('onItemClick', cmd_nomina_without_stamp_click)
$$('cmd_nomina_delete').attachEvent('onItemClick', cmd_nomina_delete_click)
$$('cmd_nomina_timbrar').attachEvent('onItemClick', cmd_nomina_timbrar_click)
$$('cmd_nomina_log').attachEvent('onItemClick', cmd_nomina_log_click)
$$('cmd_nomina_cancel').attachEvent('onItemClick', cmd_nomina_cancel_click)
$$('grid_nomina').attachEvent('onItemClick', grid_nomina_click)
$$('filter_year_nomina').attachEvent('onChange', filter_year_nomina_change)
$$('filter_month_nomina').attachEvent('onChange', filter_month_nomina_change)
$$('filter_dates_nomina').attachEvent('onChange', filter_dates_nomina_change)
webix.extend($$('grid_nomina'), webix.ProgressBar)
}
}
function default_config_nomina(){
current_dates_nomina()
get_nomina()
}
function current_dates_nomina(){
var fy = $$('filter_year_nomina')
var fm = $$('filter_month_nomina')
var d = new Date()
fy.blockEvent()
fm.blockEvent()
fm.setValue(d.getMonth() + 1)
webix.ajax().sync().get('/values/filteryearsnomina', function(text, data){
var values = data.json()
fy.getList().parse(values)
fy.setValue(d.getFullYear())
})
fy.unblockEvent()
fm.unblockEvent()
}
function get_nomina(filters){
var grid = $$('grid_nomina')
grid.showProgress({type: 'icon'})
webix.ajax().get('/nomina', filters, {
error: function(text, data, xhr) {
msg = 'Error al consultar'
msg_error(msg)
},
success: function(text, data, xhr) {
var values = data.json();
if (values.ok){
grid.clearAll();
grid.parse(values.rows, 'json');
}else{
msg_error(values.msg)
}
}
})
}
function cmd_nomina_import_click(){
win_import_nomina.init()
$$('win_import_nomina').show()
}
function cmd_import_template_nomina_click(){
var form = $$('form_upload_nomina')
var values = form.getValues()
if(!$$('lst_upload_nomina').count()){
$$('win_import_nomina').close()
return
}
if($$('lst_upload_nomina').count() > 1){
msg = 'Selecciona solo un archivo'
msg_error(msg)
return
}
var template = $$('up_nomina').files.getItem($$('up_nomina').files.getFirstId())
if(template.type.toLowerCase() != 'ods'){
msg = 'Archivo inválido.\n\nSe requiere un archivo ODS'
msg_error(msg)
return
}
msg = '¿Estás seguro de importar este archivo?'
webix.confirm({
title: 'Importar Nómina',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if(result){
$$('up_nomina').send()
}
}
})
}
function up_nomina_upload_complete(response){
if(response.status != 'server'){
msg = 'Ocurrio un error al subir el archivo'
msg_error(msg)
return
}
msg = 'Archivo subido correctamente.\n\nComenzando importación.'
msg_ok(msg)
$$('win_import_nomina').close()
webix.ajax().get('/nomina', {opt: 'import'}, {
error: function(text, data, xhr) {
msg = 'Error al importar'
msg_error(msg)
},
success: function(text, data, xhr) {
var values = data.json();
if (values.ok){
msg_ok(values.msg)
get_nomina()
}else{
msg_error(values.msg)
}
}
})
}
function get_employees(){
webix.ajax().get('/employees', {
error: function(text, data, xhr) {
msg = 'Error al consultar'
msg_error(msg)
},
success: function(text, data, xhr) {
var values = data.json();
if (values.ok){
$$('grid_employees').clearAll();
$$('grid_employees').parse(values.rows, 'json');
}else{
msg_error(values.msg)
}
}
})
}
function cmd_empleados_click(){
get_employees()
$$('multi_nomina').setValue('nomina_empleados')
}
function cmd_close_empleados_click(){
$$('multi_nomina').setValue('nomina_home')
}
function cmd_import_empleados_click(){
win_import_employees.init()
$$('win_import_employees').show()
}
function cmd_import_employees_click(){
var form = $$('form_upload_employees')
var values = form.getValues()
if(!$$('lst_upload_employees').count()){
$$('win_import_employees').close()
return
}
if($$('lst_upload_employees').count() > 1){
msg = 'Selecciona solo un archivo'
msg_error(msg)
return
}
var template = $$('up_employees').files.getItem($$('up_employees').files.getFirstId())
if(template.type.toLowerCase() != 'ods'){
msg = 'Archivo inválido.\n\nSe requiere un archivo ODS'
msg_error(msg)
return
}
msg = '¿Estás seguro de importar este archivo?'
webix.confirm({
title: 'Importar Empleados',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if(result){
$$('up_employees').send()
}
}
})
}
function up_employees_upload_complete(response){
if(response.status != 'server'){
msg = 'Ocurrio un error al subir el archivo'
msg_error(msg)
return
}
msg = 'Archivo subido correctamente.\n\nComenzando importación.'
msg_ok(msg)
$$('win_import_employees').close()
webix.ajax().get('/employees', {opt: 'import'}, {
error: function(text, data, xhr) {
msg = 'Error al importar'
msg_error(msg)
},
success: function(text, data, xhr) {
var values = data.json();
if (values.ok){
msg_ok(values.msg)
get_employees()
}else{
msg_error(values.msg)
}
}
})
}
function delete_empleado(id){
webix.ajax().del('/employees', {id: id}, function(text, xml, xhr){
var msg = 'Empleado eliminado correctamente'
if (xhr.status == 200){
$$('grid_employees').remove(id);
msg_ok(msg)
} else {
msg = 'El Empleado tiene recibos timbrados'
msg_error(msg)
}
})
}
function cmd_delete_empleado_click(){
var row = $$('grid_employees').getSelectedItem()
if (row == undefined){
msg = 'Selecciona un Empleado'
msg_error(msg)
return
}
msg = '¿Estás seguro de eliminar al Empleado?<BR><BR>'
msg += row['nombre_completo'] + ' (' + row['rfc'] + ')'
msg += '<BR><BR>ESTA ACCIÓN NO SE PUEDE DESHACER<BR><BR>'
webix.confirm({
title: 'Eliminar Empleado',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if (result){
delete_empleado(row['id'])
}
}
})
}
function cmd_nomina_without_stamp_click(){
get_nomina()
}
function cmd_nomina_delete_click(){
var rows = $$('grid_nomina').getSelectedItem()
if (rows == undefined){
msg = 'Selecciona al menos un registro'
msg_error(msg)
return
}
var ids = []
if(Array.isArray(rows)){
for(var i in rows){
ids.push(rows[i].id)
}
}else{
ids.push(rows.id)
}
msg = '¿Estás seguro de eliminar los recibos seleccionado?<BR><BR>'
msg += 'ESTA ACCIÓN NO SE PUEDE DESHACER<BR><BR>'
msg += 'Solo se eliminan recibos no timbrados'
webix.confirm({
title: 'Eliminar Nomina',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if (result){
delete_nomina(ids)
}
}
})
}
function delete_nomina(ids){
webix.ajax().del('/nomina', {id: ids}, function(text, xml, xhr){
var msg = 'Registros eliminados correctamente'
if (xhr.status == 200){
get_nomina()
msg_ok(msg)
} else {
msg = 'No se pudo eliminar.'
msg_error(msg)
}
})
}
function cmd_nomina_timbrar_click(){
get_nomina()
msg = 'Se enviarán a timbrar todos los recibos sin timbrar<BR><BR>'
msg += '¿Estás seguro de continuar?<BR><BR>'
webix.confirm({
title: 'Enviar a timbrar',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if (result){
timbrar_nomina()
}
}
})
}
function timbrar_nomina(){
webix.ajax().get('/nomina', {opt: 'stamp'}, {
error: function(text, data, xhr) {
msg = 'Error al timbrar'
msg_error(msg)
},
success: function(text, data, xhr) {
var values = data.json();
if(values.ok){
get_nomina()
msg_ok(values.msg_ok)
}
if(values.error){
webix.alert({
title: 'Error al Timbrar',
text: values.msg_error,
type: 'alert-error'
})
}
}
})
}
function grid_nomina_click(id, e, node){
var row = this.getItem(id)
if(id.column == 'xml'){
location = '/doc/xmlnom/' + row.id
}else if(id.column == 'pdf'){
//~ get_momina_pdf(row.id)
//~ }else if(id.column == 'email'){
//~ enviar_correo(row)
}
}
function filter_year_nomina_change(nv, ov){
var fm = $$('filter_month_nomina')
filters = {'opt': 'yearmonth', 'year': nv, 'month': fm.getValue()}
get_nomina(filters)
}
function filter_month_nomina_change(nv, ov){
var fy = $$('filter_year_nomina')
filters = {'opt': 'yearmonth', 'year': fy.getValue(), 'month': nv}
get_nomina(filters)
}
function filter_dates_nomina_change(range){
if(range.start != null && range.end != null){
filters = {'opt': 'dates', 'range': range}
get_nomina(filters)
}
}
function cmd_nomina_cancel_click(){
var row = $$('grid_nomina').getSelectedItem()
if(row == undefined){
msg = 'Selecciona un registro'
msg_error(msg)
return
}
if(row['estatus'] != 'Timbrado'){
msg = 'Solo se pueden cancelar recibos timbrados'
msg_error(msg)
return
}
msg = '¿Estás seguro de cancelar el recibo?<BR><BR>'
msg += row['empleado'] + ' (' + row['serie'] + '-' + row['folio'] + ')'
msg += '<BR><BR>ESTA ACCIÓN NO SE PUEDE DESHACER<BR><BR>'
webix.confirm({
title: 'Cancelar Nomina',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if (result){
cancel_nomina(row['id'])
}
}
})
}
function cancel_nomina(id){
var grid = $$('grid_nomina')
var data = new Object()
data['opt'] = 'cancel'
data['id'] = id
webix.ajax().sync().post('nomina', data, {
error:function(text, data, XmlHttpRequest){
msg = 'Ocurrio un error, consulta a soporte técnico'
msg_error(msg)
},
success:function(text, data, XmlHttpRequest){
values = data.json();
if(values.ok){
grid.updateItem(id, values.row)
msg_ok(values.msg)
}else{
msg_error(values.msg)
}
}
})
}
function cmd_nomina_log_click(){
location = '/doc/nomlog/0'
}

View File

@ -16,6 +16,7 @@ var table_series = db.addCollection('series')
var table_usocfdi = db.addCollection('usocfdi') var table_usocfdi = db.addCollection('usocfdi')
var table_relaciones = db.addCollection('relaciones') var table_relaciones = db.addCollection('relaciones')
var msg = ''
var months = [ var months = [
{id: -1, value: 'Todos'}, {id: -1, value: 'Todos'},

View File

@ -144,9 +144,14 @@ var sidebar_admin = {
var emisor_datos_fiscales = [ var emisor_datos_fiscales = [
{template: 'Datos SAT', type: 'section'}, {template: 'Datos SAT', type: 'section'},
{cols: [{view: 'text', id: 'emisor_rfc', name: 'emisor_rfc', label: 'RFC: ', {cols: [
width: 300, required: true, invalidMessage: 'RFC inválido', {view: 'text', id: 'emisor_rfc', name: 'emisor_rfc', label: 'RFC: ',
readonly: true, attributes: {maxlength: 13}}, {}]}, width: 300, required: true, invalidMessage: 'RFC inválido',
readonly: true, attributes: {maxlength: 13}},
{view: 'text', id: 'emisor_curp', name: 'emisor_curp', label: 'CURP: ',
width: 350, labelWidth: 100, attributes: {maxlength: 18},
placeholder: 'Solo si timbran nómina'},
{}]},
{view: 'text', id: 'emisor_nombre', name: 'emisor_nombre', {view: 'text', id: 'emisor_nombre', name: 'emisor_nombre',
label: 'Razón Social: ', required: true, label: 'Razón Social: ', required: true,
invalidMessage: 'La Razón Social es requerida'}, invalidMessage: 'La Razón Social es requerida'},
@ -182,16 +187,25 @@ var emisor_datos_fiscales = [
var emisor_otros_datos= [ var emisor_otros_datos= [
{template: 'Generales', type: 'section'}, {template: 'Generales', type: 'section'},
{view: 'search', id: 'emisor_logo', icon: 'file-image-o', {cols: [
name: 'emisor_logo', label: 'Logotipo: '}, {view: 'search', id: 'emisor_logo', icon: 'file-image-o',
{view: 'text', id: 'emisor_nombre_comercial', name: 'emisor_logo', label: 'Logotipo: '},
name: 'emisor_nombre_comercial', label: 'Nombre comercial: '}, {view: 'text', id: 'emisor_nombre_comercial',
{view: 'text', id: 'emisor_telefono', name: 'emisor_telefono', name: 'emisor_nombre_comercial', label: 'Nombre comercial: '},
label: 'Teléfonos: '}, ]},
{view: 'text', id: 'emisor_correo', name: 'emisor_correo', {cols: [
label: 'Correos: '}, {view: 'text', id: 'emisor_telefono', name: 'emisor_telefono',
{view: 'text', id: 'emisor_web', name: 'emisor_web', label: 'Teléfonos: '},
label: 'Página Web: '}, {view: 'text', id: 'emisor_correo', name: 'emisor_correo',
label: 'Correos: '},
]},
{cols: [
{view: 'text', id: 'emisor_registro_patronal', attributes: {maxlength: 20},
name: 'emisor_registro_patronal', label: 'Registro Patronal: ',
placeholder: 'Solo para timbrado de nómina'},
{view: 'text', id: 'emisor_web', name: 'emisor_web',
label: 'Página Web: '},
]},
{template: 'Escuela', type: 'section'}, {template: 'Escuela', type: 'section'},
{cols: [{view: 'checkbox', id: 'chk_escuela', name: 'es_escuela', {cols: [{view: 'checkbox', id: 'chk_escuela', name: 'es_escuela',
label: 'Es Escuela'}, label: 'Es Escuela'},
@ -473,7 +487,6 @@ var controls_folios = [
{ {
view: 'tabview', view: 'tabview',
id: 'tab_folios', id: 'tab_folios',
//~ tabbar: {options: ['Folios']},
animate: true, animate: true,
cells: [ cells: [
{id: 'Folios', rows: emisor_folios}, {id: 'Folios', rows: emisor_folios},
@ -497,7 +510,6 @@ var controls_correo = [
var form_folios = { var form_folios = {
type: 'space', type: 'space',
//~ responsive: true,
cols: [{ cols: [{
view: 'form', view: 'form',
id: 'form_folios', id: 'form_folios',
@ -528,7 +540,6 @@ var form_correo = {
labelWidth: 150, labelWidth: 150,
labelAlign: 'right' labelAlign: 'right'
}, },
//~ autoheight: true
}], }],
} }
@ -629,23 +640,29 @@ var options_admin_otros = [
{view: 'checkbox', id: 'chk_ticket_total_up', labelWidth: 0, {view: 'checkbox', id: 'chk_ticket_total_up', labelWidth: 0,
labelRight: 'Mostrar total arriba'}, labelRight: 'Mostrar total arriba'},
{}]}, {}]},
{maxHeight: 20},
{template: 'Nómina', type: 'section'},
{cols: [{maxWidth: 15},
{view: 'checkbox', id: 'chk_usar_nomina', labelWidth: 0,
labelRight: 'Usar timbrado de Nómina'},
{view: 'text', id: 'txt_config_nomina_serie', name: 'config_nomina_serie',
label: 'Serie', labelWidth: 50, labelAlign: 'right'},
{view: 'text', id: 'txt_config_nomina_folio', name: 'config_nomina_folio',
label: 'Folio', labelWidth: 50, labelAlign: 'right'},
{}]},
{}] {}]
var body_admin_otros = {
view: 'scrollview', body: {rows: options_admin_otros},
}
var tab_options = { var tab_options = {
view: 'tabview', view: 'tabview',
id: 'tab_options', id: 'tab_options',
animate: true, animate: true,
cells: [ cells: [
{id: 'Plantillas', rows: options_templates}, {header: 'Plantillas', body: {id: 'tab_admin_templates',
{id: 'Otros', rows: options_admin_otros}, rows: options_templates}},
], {header: 'Otros', body: {id: 'tab_admin_otros', view: 'scrollview',
body: {rows: options_admin_otros}}},
]
} }
@ -662,6 +679,18 @@ var utilidades_archivos = [
{cols: [{}, {view: 'button', id: 'cmd_subir_bdfl', {cols: [{}, {view: 'button', id: 'cmd_subir_bdfl',
label: 'Subir base de datos de Factura Libre'}, {}]}, label: 'Subir base de datos de Factura Libre'}, {}]},
]}, ]},
{maxHeight: 15},
{template: 'Importar archivo CFDI (XML)', type: 'section'},
{view: 'form', id: 'form_upload_cfdixml', rows: [
{cols: [{},
{view: 'uploader', id: 'up_cfdixml', autosend: false, link: 'lst_cfdixml',
value: 'Seleccionar archivo XML', upload: '/files/cfdixml'}, {}]},
{cols: [{},
{view: 'list', id: 'lst_cfdixml', name: 'cfdixml',
type: 'uploader', autoheight: true, borderless: true}, {}]},
{cols: [{}, {view: 'button', id: 'cmd_subir_cfdixml',
label: 'Importar CFDI'}, {}]},
]},
{}] {}]
@ -725,7 +754,6 @@ var grid_admin_taxes = {
view: 'datatable', view: 'datatable',
id: 'grid_admin_taxes', id: 'grid_admin_taxes',
select: 'cell', select: 'cell',
//~ multiselect: true,
adjust: true, adjust: true,
autoheight: true, autoheight: true,
autowidth: true, autowidth: true,

View File

@ -2,7 +2,7 @@
var menu_data = [ var menu_data = [
{id: 'app_home', icon: 'dashboard', value: 'Inicio'}, {id: 'app_home', icon: 'dashboard', value: 'Inicio'},
{id: 'app_partners', icon: 'users', value: 'Clientes y Proveedores'}, {id: 'app_partners', icon: 'address-book-o', value: 'Clientes y Proveedores'},
{id: 'app_products', icon: 'server', value: 'Productos y Servicios'}, {id: 'app_products', icon: 'server', value: 'Productos y Servicios'},
{id: 'app_bancos', icon: 'university', value: 'Bancos'}, {id: 'app_bancos', icon: 'university', value: 'Bancos'},
{id: 'app_invoices', icon: 'file-code-o', value: 'Facturas'}, {id: 'app_invoices', icon: 'file-code-o', value: 'Facturas'},
@ -38,6 +38,7 @@ var multi_main = {
app_products, app_products,
app_bancos, app_bancos,
app_school, app_school,
app_nomina,
app_tickets, app_tickets,
app_invoices, app_invoices,
], ],

View File

@ -0,0 +1,90 @@
var menu_data = [
{id: 'app_home', icon: 'dashboard', value: 'Inicio'},
{id: 'app_partners', icon: 'address-book-o', value: 'Clientes y Proveedores'},
{id: 'app_products', icon: 'server', value: 'Productos y Servicios'},
{id: 'app_bancos', icon: 'university', value: 'Bancos'},
{id: 'app_invoices', icon: 'file-code-o', value: 'Facturas'},
]
var sidebar = {
view: 'sidebar',
id: 'main_sidebar',
data: menu_data,
ready: function(){
this.select('app_home');
this.open(this.getParentId('app_home'));
},
on:{
onAfterSelect: function(id){
$$('multi').setValue(id)
}
},
}
var multi_main = {
id: 'multi',
animate: true,
cells:[
{
id: 'app_home',
view: 'template',
template: 'HOME'
},
app_partners,
app_products,
app_bancos,
<<<<<<< HEAD
app_school,
=======
app_nomina,
>>>>>>> nomina
app_tickets,
app_invoices,
],
}
var menu_user = {
view: 'menu',
id: 'menu_user',
width: 150,
autowidth: true,
data: [
{id: '0', value: 'User...', submenu:[{id:1, value:'Cerrar Sesión'}]},
],
type: {
subsign: true,
},
}
var ui_main = {
rows: [
{view: 'toolbar', padding: 3, elements: [
{view: 'button', type: 'icon', icon: 'bars',
width: 37, align: 'left', css: 'app_button', click: function(){
$$('main_sidebar').toggle()
}
},
{view: 'label', id: 'lbl_title_main', label: '<b>Empresa Libre</b>'},
{},
menu_user,
{view: 'button', type: 'icon', width: 45, css: 'app_button',
icon: 'bell-o', badge: 0},
{view: 'button', type: 'icon', width: 45, css: 'app_button',
icon: 'cogs', id: 'cmd_ir_al_admin', hidden: true,
click: 'cmd_ir_al_admin_click'}
]
},
{
cols:[
sidebar,
multi_main,
]
}
]
};

View File

@ -0,0 +1,242 @@
var toolbar_nomina = [
{view: 'button', id: 'cmd_empleados', label: 'Empleados', type: 'iconButton',
autowidth: true, icon: 'users'},
{},
{view: 'button', id: 'cmd_nomina_report', label: 'Reporte', type: 'iconButton',
autowidth: true, icon: 'table'},
{},
{view: 'button', id: 'cmd_nomina_delete', label: 'Eliminar',
type: 'iconButton', autowidth: true, icon: 'minus'},
]
var toolbar_nomina_util = [
{view: 'button', id: 'cmd_nomina_import', label: 'Importar',
type: 'iconButton', autowidth: true, icon: 'upload'},
{view: 'button', id: 'cmd_nomina_timbrar', label: 'Timbrar',
type: 'iconButton', autowidth: true, icon: 'ticket'},
{view: 'button', id: 'cmd_nomina_sat', label: 'SAT',
type: 'iconButton', autowidth: true, icon: 'check-circle'},
{view: 'button', id: 'cmd_nomina_log', label: 'Log',
type: 'iconButton', autowidth: true, icon: 'download'},
{},
{view: 'button', id: 'cmd_nomina_cancel', label: 'Cancelar',
type: 'iconButton', autowidth: true, icon: 'ban'},
]
var toolbar_nomina_filter = [
{view: 'richselect', id: 'filter_year_nomina', label: 'Año',
labelAlign: 'right', labelWidth: 50, width: 150, options: []},
{view: 'richselect', id: 'filter_month_nomina', label: 'Mes',
labelAlign: 'right', labelWidth: 50, width: 200, options: months},
{view: 'daterangepicker', id: 'filter_dates_nomina', label: 'Fechas',
labelAlign: 'right', width: 300},
{},
{view: 'button', id: 'cmd_nomina_without_stamp', label: 'Sin Timbrar',
type: 'iconButton', autowidth: true, icon: 'filter'},
]
var grid_cols_nomina = [
{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: "header"},
{id: 'folio', header: ['Folio', {content: 'numberFilter'}], adjust: 'header',
sort: 'int', css: 'right', footer: {text: 'Recibos', colspan: 3}},
{id: "fecha", header: ["Fecha y Hora"], adjust: "data", sort: "string"},
{id: "estatus", header: ["Estatus", {content: "selectFilter"}],
adjust: "data", sort:"string"},
{id: 'fecha_pago', header: ['Fecha de Pago', {content: 'selectFilter'}],
adjust: 'data', sort: 'string'},
{id: 'total', header: ['Total', {content: 'numberFilter'}], width: 150,
sort: 'int', format: webix.i18n.priceFormat, css: 'right',
footer: {content: 'summActive', css: 'right'}},
{id: "empleado", header: ["Empleado", {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')},
]
var grid_nomina = {
view: 'datatable',
id: 'grid_nomina',
select: 'row',
multiselect: true,
scrollY: true,
adjust: true,
footer: true,
resizeColumn: true,
headermenu: true,
columns: grid_cols_nomina,
scheme:{
$change:function(item){
if (item.estatus == 'Cancelado'){
item.$css = 'cancel'
}
}
},
on:{
'data->onStoreUpdated':function(){
this.data.each(function(obj, i){
obj.index = i + 1
})
}
},
}
var rows_nomina_home = [
{view: 'toolbar', elements: toolbar_nomina},
{view: 'toolbar', elements: toolbar_nomina_util},
{view: 'toolbar', elements: toolbar_nomina_filter},
grid_nomina,
]
var toolbar_nomina_empleados = [
{view: 'button', id: 'cmd_new_empleado', label: 'Nuevo', type: 'iconButton',
autowidth: true, icon: 'user-plus'},
{view: 'button', id: 'cmd_edit_empleado', label: 'Editar', type: 'iconButton',
autowidth: true, icon: 'user'},
{view: 'button', id: 'cmd_delete_empleado', label: 'Eliminar', type: 'iconButton',
autowidth: true, icon: 'user-times'},
{},
{view: 'button', id: 'cmd_import_empleados', label: 'Importar',
type: 'iconButton', autowidth: true, icon: 'upload'},
{},
{view: 'button', id: 'cmd_close_empleados', label: 'Cerrar', type: 'iconButton',
autowidth: true, icon: 'times-circle-o'},
]
var grid_cols_empleados = [
{id: 'index', header: '#', adjust: 'data', css: 'right',
footer: {content: 'countRows', colspan: 3, css: 'right'}},
{id: "id", header:"ID", hidden:true},
{id: "num_empleado", header: ["No Empleado"], adjust: "data"},
{id: "rfc", header: ["RFC", {content: 'textFilter'}], adjust: "data", sort: "string"},
{id: "curp", header: ["CURP"], adjust: "data", hidden:true, sort: "string"},
{id: "nombre_completo", header: ["Empleado", {content: 'textFilter'}],
adjust: "data", fillspace: true, sort: "string"},
{id: 'imss', header: ['IMSS'], adjust: 'data'},
{id: 'salario_base', header: ['Salario Base'], adjust: 'header',
format: webix.i18n.priceFormat, css: 'right'},
{id: 'salario_diario', header: ['Salario Diario'], adjust: 'header',
format: webix.i18n.priceFormat, css: 'right'},
{id: "fecha_ingreso", header: ["Fecha de Ingreso"], adjust: "header",
sort: "string"},
]
var grid_empleados = {
view: 'datatable',
id: 'grid_employees',
select: 'row',
scrollY: true,
adjust: true,
footer: true,
resizeColumn: true,
headermenu: true,
columns: grid_cols_empleados,
on:{
'data->onStoreUpdated':function(){
this.data.each(function(obj, i){
obj.index = i + 1
})
}
},
}
var rows_nomina_empleados = [
{view: 'toolbar', elements: toolbar_nomina_empleados},
grid_empleados,
]
var multi_nomina = {
id: 'multi_nomina',
view: 'multiview',
animate: true,
cells:[
{id: 'nomina_home', rows: rows_nomina_home},
{id: 'nomina_empleados', rows: rows_nomina_empleados},
],
}
var app_nomina = {
id: 'app_nomina',
rows:[
{view: 'template', type: 'header', template: 'Timbrado de Nómina'},
multi_nomina
],
}
var body_import_employees = {rows: [
{view: 'form', id: 'form_upload_employees', rows: [
{cols: [{},
{view: 'uploader', id: 'up_employees', autosend: false,
link: 'lst_upload_employees', value: 'Seleccionar Plantilla',
upload: '/files/employees'}, {}]},
{cols: [
{view: 'list', id: 'lst_upload_employees', name: 'lst_employees',
type: 'uploader', autoheight: true, borderless: true}]},
{cols: [{}, {view: 'button', id: 'cmd_import_employees',
label: 'Importar Empleados'}, {}]},
]},
],}
var win_import_employees = {
init: function(){
webix.ui({
view: 'window',
id: 'win_import_employees',
width: 400,
modal: true,
position: 'center',
head: 'Importar Empleados',
body: body_import_employees,
})
$$('cmd_import_employees').attachEvent('onItemClick', cmd_import_employees_click)
$$('up_employees').attachEvent('onUploadComplete', up_employees_upload_complete)
}
}
var body_import_nomina = {rows: [
{view: 'form', id: 'form_upload_nomina', rows: [
{cols: [{},
{view: 'uploader', id: 'up_nomina', autosend: false,
link: 'lst_upload_nomina', value: 'Seleccionar Plantilla',
upload: '/files/nomina'}, {}]},
{cols: [
{view: 'list', id: 'lst_upload_nomina', name: 'lst_nomina',
type: 'uploader', autoheight: true, borderless: true}]},
{cols: [{}, {view: 'button', id: 'cmd_import_template_nomina',
label: 'Importar Nómina'}, {}]},
]},
],}
var win_import_nomina = {
init: function(){
webix.ui({
view: 'window',
id: 'win_import_nomina',
width: 400,
modal: true,
position: 'center',
head: 'Importar Nómina',
body: body_import_nomina,
})
$$('cmd_import_template_nomina').attachEvent('onItemClick', cmd_import_template_nomina_click)
$$('up_nomina').attachEvent('onUploadComplete', up_nomina_upload_complete)
}
}

View File

@ -209,9 +209,10 @@ var multi_products = {
var app_products = { var app_products = {
id: "app_products", id: 'app_products',
rows:[ rows:[
{view: "template", id: "th_products", type: "header", template:"Administración de Productos" }, {view: 'template', id: 'th_products', type: 'header',
template: 'Administración de Productos y Servicios'},
multi_products multi_products
], ],
} }

View File

@ -9,6 +9,7 @@
<script src="/static/js/ui/products.js" type="text/javascript" ></script> <script src="/static/js/ui/products.js" type="text/javascript" ></script>
<script src="/static/js/ui/bancos.js" type="text/javascript" ></script> <script src="/static/js/ui/bancos.js" type="text/javascript" ></script>
<script src="/static/js/ui/school.js" type="text/javascript" ></script> <script src="/static/js/ui/school.js" type="text/javascript" ></script>
<script src="/static/js/ui/nomina.js" type="text/javascript" ></script>
<script src="/static/js/ui/tickets.js" type="text/javascript" ></script> <script src="/static/js/ui/tickets.js" type="text/javascript" ></script>
<script src="/static/js/ui/invoices.js" type="text/javascript" ></script> <script src="/static/js/ui/invoices.js" type="text/javascript" ></script>
<script src="/static/js/ui/main.js" type="text/javascript" ></script> <script src="/static/js/ui/main.js" type="text/javascript" ></script>
@ -17,6 +18,7 @@
<script src="/static/js/controller/products.js" type="text/javascript" ></script> <script src="/static/js/controller/products.js" type="text/javascript" ></script>
<script src="/static/js/controller/bancos.js" type="text/javascript" ></script> <script src="/static/js/controller/bancos.js" type="text/javascript" ></script>
<script src="/static/js/controller/school.js" type="text/javascript" ></script> <script src="/static/js/controller/school.js" type="text/javascript" ></script>
<script src="/static/js/controller/nomina.js" type="text/javascript" ></script>
<script src="/static/js/controller/tickets.js" type="text/javascript" ></script> <script src="/static/js/controller/tickets.js" type="text/javascript" ></script>
<script src="/static/js/controller/invoices.js" type="text/javascript" ></script> <script src="/static/js/controller/invoices.js" type="text/javascript" ></script>
<script src="/static/js/controller/main.js" type="text/javascript" ></script> <script src="/static/js/controller/main.js" type="text/javascript" ></script>

View File

@ -0,0 +1,50 @@
<%inherit file="base.html"/>
<%block name="media">
<link rel="stylesheet" href="/static/css/sidebar_air.css" type="text/css">
<script src="/static/js/sidebar.js" type="text/javascript" ></script>
<script src="/static/js/controller/util.js" type="text/javascript" ></script>
<script src="/static/js/ui/partners.js" type="text/javascript" ></script>
<script src="/static/js/ui/products.js" type="text/javascript" ></script>
<script src="/static/js/ui/bancos.js" type="text/javascript" ></script>
<<<<<<< HEAD
<script src="/static/js/ui/school.js" type="text/javascript" ></script>
=======
<script src="/static/js/ui/nomina.js" type="text/javascript" ></script>
>>>>>>> nomina
<script src="/static/js/ui/tickets.js" type="text/javascript" ></script>
<script src="/static/js/ui/invoices.js" type="text/javascript" ></script>
<script src="/static/js/ui/main.js" type="text/javascript" ></script>
<script src="/static/js/controller/partners.js" type="text/javascript" ></script>
<script src="/static/js/controller/products.js" type="text/javascript" ></script>
<script src="/static/js/controller/bancos.js" type="text/javascript" ></script>
<<<<<<< HEAD
<script src="/static/js/controller/school.js" type="text/javascript" ></script>
=======
<script src="/static/js/controller/nomina.js" type="text/javascript" ></script>
>>>>>>> nomina
<script src="/static/js/controller/tickets.js" type="text/javascript" ></script>
<script src="/static/js/controller/invoices.js" type="text/javascript" ></script>
<script src="/static/js/controller/main.js" type="text/javascript" ></script>
</%block>
<%block name="content">
<input type=hidden id="username" value="${username}"/>
<script type="text/javascript" charset="utf-8">
webix.ready(function(){
webix.CustomScroll.init()
webix.ui(ui_main)
controllers.init()
var user = document.getElementById("username").value
$$('menu_user').getMenu(0).updateItem(0, {value:user})
})
</script>
</%block>

View File

@ -1,26 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.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:iedu="http://www.sat.gob.mx/iedu"> <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:iedu="http://www.sat.gob.mx/iedu">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="no"/> <xsl:output method="text" version="1.0" encoding="UTF-8" indent="no"/>
<!-- Manejador de nodos tipo iedu --> <!-- Manejador de nodos tipo iedu -->
<xsl:template match="iedu:instEducativas"> <xsl:template match="iedu:instEducativas">
<!--Iniciamos el tratamiento de los atributos de instEducativas --> <!--Iniciamos el tratamiento de los atributos de instEducativas -->
<xsl:call-template name="Requerido"> <xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@version"/> <xsl:with-param name="valor" select="./@version"/>
</xsl:call-template> </xsl:call-template>
<xsl:call-template name="Requerido"> <xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@nombreAlumno"/> <xsl:with-param name="valor" select="./@nombreAlumno"/>
</xsl:call-template> </xsl:call-template>
<xsl:call-template name="Requerido"> <xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@CURP"/> <xsl:with-param name="valor" select="./@CURP"/>
</xsl:call-template> </xsl:call-template>
<xsl:call-template name="Requerido"> <xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@nivelEducativo"/> <xsl:with-param name="valor" select="./@nivelEducativo"/>
</xsl:call-template> </xsl:call-template>
<xsl:call-template name="Requerido"> <xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@autRVOE"/> <xsl:with-param name="valor" select="./@autRVOE"/>
</xsl:call-template> </xsl:call-template>
<xsl:call-template name="Opcional"> <xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@rfcPago"/> <xsl:with-param name="valor" select="./@rfcPago"/>
</xsl:call-template> </xsl:call-template>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>