Complemento EDU

This commit is contained in:
Mauricio Baeza 2018-01-29 13:21:48 -06:00
commit 0e909628dc
18 changed files with 812 additions and 24 deletions

View File

@ -58,6 +58,12 @@ SAT = {
'xmlns': 'http://www.sat.gob.mx/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', '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',
},
} }
@ -72,6 +78,7 @@ class CFDI(object):
self._impuestos_locales = False self._impuestos_locales = False
self._donativo = False self._donativo = False
self._ine = False self._ine = False
self._edu = False
self.error = '' self.error = ''
def _now(self): def _now(self):
@ -118,6 +125,8 @@ class CFDI(object):
if 'ine' in datos['complementos']: if 'ine' in datos['complementos']:
self._ine = True self._ine = True
self._edu = datos['edu']
if 'nomina' in datos: if 'nomina' in datos:
return self._validate_nomina(datos) return self._validate_nomina(datos)
return True return True
@ -160,10 +169,16 @@ class CFDI(object):
if self._ine: if self._ine:
name = 'xmlns:{}'.format(SAT['ine']['prefix']) name = 'xmlns:{}'.format(SAT['ine']['prefix'])
attributes[name] = SAT['ine']['xmlns'] attributes[name] = SAT['ine']['xmlns']
schema_donativo = SAT['ine']['schema'] schema_ine = SAT['ine']['schema']
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'] + \ attributes['xsi:schemaLocation'] = self._sat_cfdi['schema'] + \
schema_locales + schema_donativo +schema_ine schema_locales + schema_donativo + schema_ine + schema_edu
attributes.update(datos) attributes.update(datos)
if not 'Version' in attributes: if not 'Version' in attributes:
@ -213,6 +228,7 @@ class CFDI(object):
complemento = row.pop('complemento') complemento = row.pop('complemento')
cuenta_predial = row.pop('CuentaPredial', '') cuenta_predial = row.pop('CuentaPredial', '')
pedimento = row.pop('Pedimento', '') pedimento = row.pop('Pedimento', '')
student = row.pop('student', '')
taxes = {} taxes = {}
if 'impuestos' in row: if 'impuestos' in row:
@ -246,20 +262,10 @@ class CFDI(object):
node_name = '{}:CuentaPredial'.format(self._pre) node_name = '{}:CuentaPredial'.format(self._pre)
ET.SubElement(concepto, node_name, attributes) ET.SubElement(concepto, node_name, attributes)
if 'autRVOE' in row: if student:
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) node_name = '{}:ComplementoConcepto'.format(self._pre)
complemento = ET.SubElement(concepto, node_name) complemento = ET.SubElement(concepto, node_name)
ET.SubElement(complemento, 'iedu:instEducativas', attributes) ET.SubElement(complemento, 'iedu:instEducativas', student)
return return
def _impuestos(self, datos): def _impuestos(self, datos):

View File

@ -150,6 +150,8 @@ class AppValues(object):
req.context['result'] = self._db.importar_bdfl() req.context['result'] = self._db.importar_bdfl()
elif table == 'invoicenotes': elif table == 'invoicenotes':
req.context['result'] = self._db.save_invoice_notes(values) req.context['result'] = self._db.save_invoice_notes(values)
elif table == 'nivedu':
req.context['result'] = self._db.add_nivel_educativo(values)
else: else:
req.context['result'] = self._db.validate_cert(values, session) req.context['result'] = self._db.validate_cert(values, session)
else: else:
@ -219,6 +221,29 @@ class AppPartners(object):
resp.status = falcon.HTTP_204 resp.status = falcon.HTTP_204
class AppStudents(object):
def __init__(self, db):
self._db = db
def on_get(self, req, resp):
values = req.params
req.context['result'] = self._db.get_students(values)
resp.status = falcon.HTTP_200
def on_post(self, req, resp):
values = req.params
req.context['result'] = self._db.students(values)
resp.status = falcon.HTTP_200
def on_delete(self, req, resp):
values = req.params
if self._db.delete('students', values['id']):
resp.status = falcon.HTTP_200
else:
resp.status = falcon.HTTP_204
class AppProducts(object): class AppProducts(object):
def __init__(self, db): def __init__(self, db):

View File

@ -1145,6 +1145,13 @@ def _conceptos(doc, version):
info = '\nNúmero Pedimento: {}'.format(v['numeropedimento']) info = '\nNúmero Pedimento: {}'.format(v['numeropedimento'])
values['descripcion'] += info values['descripcion'] += info
n = c.find('{}ComplementoConcepto'.format(PRE[version]))
if n is not None:
v = CaseInsensitiveDict(n[0].attrib.copy())
info = '\nAlumno: {} (CURP: {})\nNivel: {}, Autorización: {}'.format(
v['nombreAlumno'], v['CURP'], v['nivelEducativo'], v['autRVOE'])
values['descripcion'] += info
data.append(values) data.append(values)
return data return data

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 AppMovimientosBanco, AppTickets, AppStudents
) )
@ -52,6 +52,7 @@ api.add_route('/preinvoices', AppPreInvoices(db))
api.add_route('/tickets', AppTickets(db)) 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))
# ~ Activa si usas waitress y NO estas usando servidor web # ~ Activa si usas waitress y NO estas usando servidor web

View File

@ -25,6 +25,15 @@ class StorageEngine(object):
return getattr(self, '_get_{}'.format(table))(values, session) return getattr(self, '_get_{}'.format(table))(values, session)
return getattr(self, '_get_{}'.format(table))(values) 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): def _get_titlelogin(self, values):
return main.get_title_app(2) return main.get_title_app(2)
@ -244,11 +253,18 @@ class StorageEngine(object):
return main.Usuarios.remove(id) return main.Usuarios.remove(id)
if table == 'config': if table == 'config':
return main.Configuracion.remove(id) return main.Configuracion.remove(id)
if table == 'nivedu':
return main.NivelesEducativos.remove(id)
if table == 'students':
return main.Alumnos.remove(id)
return False return False
def _get_client(self, values): def _get_client(self, values):
return main.Socios.get_by_client(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): def _get_product(self, values):
return main.Productos.get_by(values) return main.Productos.get_by(values)
@ -291,6 +307,16 @@ class StorageEngine(object):
#~ return main.PreFacturas.actualizar(values, id) #~ return main.PreFacturas.actualizar(values, id)
return main.PreFacturas.add(values) 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): def tickets(self, values, user):
opt = values.pop('opt') opt = values.pop('opt')
if opt == 'add': if opt == 'add':
@ -338,6 +364,9 @@ class StorageEngine(object):
def add_folios(self, values): def add_folios(self, values):
return main.Folios.add(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): def get_doc(self, type_doc, id, rfc):
return main.get_doc(type_doc, id, rfc) return main.get_doc(type_doc, id, rfc)

View File

@ -195,12 +195,13 @@ def config_main():
punto_de_venta = util.get_bool(Configuracion.get_('chk_usar_punto_de_venta')) punto_de_venta = util.get_bool(Configuracion.get_('chk_usar_punto_de_venta'))
data = { data = {
'empresa': get_title_app(3), 'empresa': get_title_app(3),
'punto_de_venta': punto_de_venta 'punto_de_venta': punto_de_venta,
'escuela': False,
} }
if not obj is None: if not obj is None:
titulo = '{} - <b><font color="#610B0B">{}</font></b>' titulo = '{} - <b><font color="#610B0B">{}</font></b>'
data['empresa'] = titulo.format(data['empresa'], obj.nombre) data['empresa'] = titulo.format(data['empresa'], obj.nombre)
data['escuela'] = obj.es_escuela
return data return data
@ -215,6 +216,7 @@ def config_timbrar():
'cfdi_donativo': obj.es_ong, 'cfdi_donativo': obj.es_ong,
'cfdi_anticipo': Configuracion.get_('chk_config_anticipo'), 'cfdi_anticipo': Configuracion.get_('chk_config_anticipo'),
'cfdi_ine': Configuracion.get_bool('chk_config_ine'), 'cfdi_ine': Configuracion.get_bool('chk_config_ine'),
'cfdi_edu': Configuracion.get_bool('chk_config_edu'),
'cfdi_metodo_pago': Configuracion.get_bool('chk_config_ocultar_metodo_pago'), 'cfdi_metodo_pago': Configuracion.get_bool('chk_config_ocultar_metodo_pago'),
'cfdi_condicion_pago': Configuracion.get_bool('chk_config_ocultar_condiciones_pago'), 'cfdi_condicion_pago': Configuracion.get_bool('chk_config_ocultar_condiciones_pago'),
'cfdi_open_pdf': Configuracion.get_bool('chk_config_open_pdf'), 'cfdi_open_pdf': Configuracion.get_bool('chk_config_open_pdf'),
@ -1401,6 +1403,12 @@ class SATNivelesEducativos(BaseModel):
def __str__(self): def __str__(self):
return self.name return self.name
@classmethod
def get_by(cls):
rows = SATNivelesEducativos.select(
SATNivelesEducativos.name).tuples()
return tuple([r[0] for r in rows])
class NivelesEducativos(BaseModel): class NivelesEducativos(BaseModel):
nombre = TextField() nombre = TextField()
@ -1415,6 +1423,32 @@ class NivelesEducativos(BaseModel):
def __str__(self): def __str__(self):
return '{} ({})'.format(self.nombre, self.autorizacion) return '{} ({})'.format(self.nombre, self.autorizacion)
@classmethod
def get_all(cls):
rows = NivelesEducativos.select().dicts()
return tuple(rows)
def _add_group(self, obj):
Grupos.get_or_create(**{'nivel': obj})
return
@classmethod
def add(cls, values):
try:
obj = NivelesEducativos.create(**values)
# Revisar
cls._add_group(cls, obj)
result = {'ok': True}
except IntegrityError:
msg = 'Nivel Educativo existente'
result = {'ok': False, 'msg': msg}
return result
@classmethod
def remove(cls, id):
q = NivelesEducativos.delete().where(NivelesEducativos.id==int(id))
return bool(q.execute())
class Grupos(BaseModel): class Grupos(BaseModel):
nivel = ForeignKeyField(NivelesEducativos) nivel = ForeignKeyField(NivelesEducativos)
@ -1430,6 +1464,17 @@ class Grupos(BaseModel):
def __str__(self): def __str__(self):
return '{} {} {}'.format(self.nivel.nombre, self.grado, self.nombre) return '{} {} {}'.format(self.nivel.nombre, self.grado, self.nombre)
@classmethod
def get_by(cls, values):
rows = (Grupos.select(
Grupos.id.alias('id'),
NivelesEducativos.nombre.alias('value'))
.join(NivelesEducativos)
.switch(Grupos)
.dicts()
)
return tuple(rows)
class CuentasBanco(BaseModel): class CuentasBanco(BaseModel):
de_emisor = BooleanField(default=False) de_emisor = BooleanField(default=False)
@ -2128,6 +2173,91 @@ class Alumnos(BaseModel):
class Meta: class Meta:
order_by = ('nombre', 'paterno') order_by = ('nombre', 'paterno')
def _clean(self, values):
fields = util.clean(util.loads(values))
fields['rfc'] = fields['rfc'].upper()
fields['curp'] = fields['curp'].upper()
fields['nombre'] = util.spaces(fields['nombre'])
fields['paterno'] = util.spaces(fields['paterno'])
fields['materno'] = util.spaces(fields['materno'])
return fields
def _get(self, where):
rows = (Alumnos
.select()
.where(where)
.dicts()
)
return tuple(rows)
@classmethod
def get_by_name(cls, values):
rows = ()
name = values.get('name', '')
if name:
rows = (Alumnos
.select(
Alumnos.id,
Alumnos.nombre,
Alumnos.paterno,
Alumnos.materno,
Alumnos.rfc)
.where((Alumnos.es_activo==True) &
(Alumnos.nombre.contains(name) |
Alumnos.paterno.contains(name) |
Alumnos.materno.contains(name) |
Alumnos.rfc.contains(name)))
.dicts())
rows = tuple(rows)
return rows
@classmethod
def get_by(cls, values):
if 'id' in values:
id = int(values['id'])
w = (Alumnos.id==id)
rows = cls._get(cls, w)
return rows[0]
if not values:
w = None
return cls._get(cls, w)
@classmethod
def add(cls, values):
fields = cls._clean(cls, values)
try:
obj = Alumnos.create(**fields)
except IntegrityError as e:
msg = 'Ya existe un alumno con este CURP'
data = {'ok': False, 'msg': msg}
return data
data = {'ok': True}
return data
@classmethod
def actualizar(cls, values):
fields = cls._clean(cls, values)
id = int(fields.pop('id'))
try:
q = Alumnos.update(**fields).where(Alumnos.id==id)
q.execute()
except IntegrityError:
msg = 'Ya existe un Alumno con este CURP'
data = {'ok': False, 'msg': msg}
return data
data = {'ok': True}
return data
@classmethod
def remove(cls, id):
q = Alumnos.delete().where(Alumnos.id==id)
return bool(q.execute())
class AlumnosParientes(BaseModel): class AlumnosParientes(BaseModel):
alumno = ForeignKeyField(Alumnos) alumno = ForeignKeyField(Alumnos)
@ -3101,8 +3231,9 @@ class Facturas(BaseModel):
locales_retenciones = 0 locales_retenciones = 0
for product in products: for product in products:
# ~ print ('\n', product['descripcion']) # ~ print ('\n', product)
id_product = product.pop('id') id_product = product.pop('id')
id_student = product.pop('id_student', 0)
p = Productos.get(Productos.id==id_product) p = Productos.get(Productos.id==id_product)
product['unidad'] = p.unidad.key product['unidad'] = p.unidad.key
@ -3128,6 +3259,13 @@ class Facturas(BaseModel):
descuento_cfdi += product['descuento'] descuento_cfdi += product['descuento']
subtotal += product['importe'] subtotal += product['importe']
if id_student:
student = Alumnos.get(Alumnos.id==id_student)
product['alumno'] = str(student)
product['curp'] = student.curp
product['nivel'] = student.grupo.nivel.nombre
product['autorizacion'] = student.grupo.nivel.autorizacion.strip()
FacturasDetalle.create(**product) FacturasDetalle.create(**product)
base = product['importe'] - product['descuento'] base = product['importe'] - product['descuento']
@ -3258,6 +3396,7 @@ class Facturas(BaseModel):
emisor = Emisor.select()[0] emisor = Emisor.select()[0]
certificado = Certificado.select()[0] certificado = Certificado.select()[0]
is_edu = False
comprobante = {} comprobante = {}
relacionados = {} relacionados = {}
donativo = {} donativo = {}
@ -3331,6 +3470,16 @@ class Facturas(BaseModel):
if row.pedimento: if row.pedimento:
concepto['Pedimento'] = row.pedimento concepto['Pedimento'] = row.pedimento
if row.autorizacion:
is_edu = True
concepto['student'] = {
'version': '1.0',
'nombreAlumno': row.alumno,
'CURP': row.curp,
'nivelEducativo': row.nivel,
'autRVOE': row.autorizacion,
}
taxes = {} taxes = {}
traslados = [] traslados = []
retenciones = [] retenciones = []
@ -3457,6 +3606,7 @@ class Facturas(BaseModel):
'conceptos': conceptos, 'conceptos': conceptos,
'impuestos': impuestos, 'impuestos': impuestos,
'donativo': donativo, 'donativo': donativo,
'edu': is_edu,
'complementos': complementos, 'complementos': complementos,
} }
return util.make_xml(data, certificado, auth) return util.make_xml(data, certificado, auth)

View File

@ -23,6 +23,7 @@ var controllers = {
$$('emisor_logo').attachEvent('onItemClick', emisor_logo_click) $$('emisor_logo').attachEvent('onItemClick', emisor_logo_click)
$$('cmd_emisor_agregar_cuenta').attachEvent('onItemClick', cmd_emisor_agregar_cuenta_click) $$('cmd_emisor_agregar_cuenta').attachEvent('onItemClick', cmd_emisor_agregar_cuenta_click)
$$('cmd_emisor_eliminar_cuenta').attachEvent('onItemClick', cmd_emisor_eliminar_cuenta_click) $$('cmd_emisor_eliminar_cuenta').attachEvent('onItemClick', cmd_emisor_eliminar_cuenta_click)
$$('cmd_niveles_educativos').attachEvent('onItemClick', cmd_niveles_educativos_click)
$$('emisor_cuenta_saldo_inicial').attachEvent('onChange', emisor_cuenta_saldo_inicial_change) $$('emisor_cuenta_saldo_inicial').attachEvent('onChange', emisor_cuenta_saldo_inicial_change)
//~ SAT //~ SAT
tb_sat = $$('tab_sat').getTabbar() tb_sat = $$('tab_sat').getTabbar()
@ -479,9 +480,9 @@ function emisor_postal_code_key_press(code, e){
function chk_escuela_change(new_value, old_value){ function chk_escuela_change(new_value, old_value){
var value = Boolean(new_value) var value = Boolean(new_value)
if (value){ if (value){
$$('cmd_niveles').enable() $$('cmd_niveles_educativos').enable()
} else { } else {
$$('cmd_niveles').disable() $$('cmd_niveles_educativos').disable()
} }
} }
@ -1836,3 +1837,90 @@ function txt_ticket_printer_key_press(code, e){
}) })
} }
function cmd_niveles_educativos_click(){
admin_ui_niveles_educativos.init()
$$('win_niveles_educativos').show()
get_niveles_educativos()
}
function get_niveles_educativos(){
webix.ajax().sync().get('/values/niveduall', {
error:function(text, data, XmlHttpRequest){
msg = 'Ocurrio un error, consulta a soporte técnico'
msg_error(msg)
},
success:function(text, data, XmlHttpRequest){
var values = data.json()
$$('grid_niveles_educativos').clearAll()
$$('grid_niveles_educativos').parse(values)
$$('grid_niveles_educativos').refresh()
}
})
}
function add_nivel_educativo_click(){
var form = $$('form_niveles_educativos')
if (!form.validate()){
msg = 'Valores inválidos'
msg_error(msg)
return
}
var values = form.getValues()
webix.ajax().post('/values/nivedu', values, {
error:function(text, data, XmlHttpRequest){
msg = 'Ocurrio un error, consulta a soporte técnico'
msg_error(msg)
},
success:function(text, data, XmlHttpRequest){
var result = data.json()
form.setValues({})
if(result.ok){
$$('grid_niveles_educativos').add(values)
}else{
msg_error(result.msg)
}
}
})
}
function delete_nivel_educativo(id){
webix.ajax().del('/values/nivedu', {id: id}, function(text, xml, xhr){
if(xhr.status == 200){
$$('grid_niveles_educativos').remove(id)
}else{
msg = 'No se pudo eliminar'
msg_error(msg)
}
})
}
function grid_niveles_educativos_click(id){
if(id.column != 'delete'){
return
}
msg = '¿Estás seguro de eliminar este Nivel Educativo'
webix.confirm({
title: 'Eliminar',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if(result){
delete_nivel_educativo(id.row)
}
}
})
}

View File

@ -22,6 +22,7 @@ var invoices_controllers = {
$$('grid_clients_found').attachEvent('onValueSuggest', grid_clients_found_click) $$('grid_clients_found').attachEvent('onValueSuggest', grid_clients_found_click)
$$('search_product_id').attachEvent('onKeyPress', search_product_id_key_press) $$('search_product_id').attachEvent('onKeyPress', search_product_id_key_press)
$$('grid_products_found').attachEvent('onValueSuggest', grid_products_found_click) $$('grid_products_found').attachEvent('onValueSuggest', grid_products_found_click)
$$('grid_students_found').attachEvent('onValueSuggest', grid_students_found_click)
$$('grid_details').attachEvent('onItemClick', grid_details_click) $$('grid_details').attachEvent('onItemClick', grid_details_click)
$$('grid_details').attachEvent('onHeaderClick', grid_details_header_click) $$('grid_details').attachEvent('onHeaderClick', grid_details_header_click)
$$('grid_details').attachEvent('onBeforeEditStart', grid_details_before_edit_start) $$('grid_details').attachEvent('onBeforeEditStart', grid_details_before_edit_start)
@ -161,6 +162,7 @@ function default_config(){
}else{ }else{
$$('tv_invoice').getTabbar().showOption('INE') $$('tv_invoice').getTabbar().showOption('INE')
} }
cfg_invoice['edu'] = values.cfdi_edu
cfg_invoice['open_pdf'] = values.cfdi_open_pdf cfg_invoice['open_pdf'] = values.cfdi_open_pdf
cfg_invoice['tax_locales'] = values.cfdi_tax_locales cfg_invoice['tax_locales'] = values.cfdi_tax_locales
cfg_invoice['tax_decimals'] = values.cfdi_tax_decimals cfg_invoice['tax_decimals'] = values.cfdi_tax_decimals
@ -168,6 +170,9 @@ function default_config(){
if(values.cfdi_show_pedimento){ if(values.cfdi_show_pedimento){
$$('grid_details').showColumn('pedimento') $$('grid_details').showColumn('pedimento')
} }
if(values.cfdi_edu){
$$('grid_details').showColumn('student')
}
}) })
} }
@ -557,6 +562,7 @@ function guardar_y_timbrar(values){
delete rows[i]['clave_sat'] delete rows[i]['clave_sat']
delete rows[i]['unidad'] delete rows[i]['unidad']
delete rows[i]['importe'] delete rows[i]['importe']
delete rows[i]['student']
rows[i]['valor_unitario'] = parseFloat(rows[i]['valor_unitario']) rows[i]['valor_unitario'] = parseFloat(rows[i]['valor_unitario'])
rows[i]['descuento'] = parseFloat(rows[i]['descuento']) rows[i]['descuento'] = parseFloat(rows[i]['descuento'])
} }
@ -893,6 +899,25 @@ function grid_products_found_click(obj){
} }
function grid_students_found_click(obj){
var form = $$('form_invoice')
var row = grid.getSelectedItem()
if (row == undefined){
msg = 'Selecciona un registro primero'
msg_error(msg)
return
}
var values = {
id_student: obj.id,
student: obj.nombre + ' ' + obj.paterno + ' ' + obj.materno,
}
grid.updateItem(row.id, values)
form.setValues({search_student: ''}, true)
}
function search_product_by_key(key){ function search_product_by_key(key){
webix.ajax().get('/values/productokey', {'key': key}, { webix.ajax().get('/values/productokey', {'key': key}, {
error: function(text, data, xhr) { error: function(text, data, xhr) {

View File

@ -10,12 +10,21 @@ function configuracion_inicial(){
var values = data.json() var values = data.json()
$$('lbl_title_main').setValue(values.empresa) $$('lbl_title_main').setValue(values.empresa)
//~ showvar() //~ showvar()
var pos = 4
if(values.escuela){
var node = {
id: 'app_school',
icon: 'graduation-cap',
value: 'Escuela'}
$$('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',
icon: 'money', icon: 'money',
value: 'Punto de venta'} value: 'Punto de venta'}
$$('main_sidebar').add(node, 4) $$('main_sidebar').add(node, pos)
} }
}) })
@ -45,6 +54,7 @@ var controllers = {
products_controllers.init() products_controllers.init()
bancos_controllers.init() bancos_controllers.init()
invoices_controllers.init() invoices_controllers.init()
controllers_school.init()
tickets_controllers.init() tickets_controllers.init()
} }
} }
@ -113,6 +123,7 @@ function current_dates(){
function multi_change(prevID, nextID){ function multi_change(prevID, nextID){
if(nextID == 'app_partners'){ if(nextID == 'app_partners'){
active = $$('multi_partners').getActiveId() active = $$('multi_partners').getActiveId()
if(active == 'partners_home'){ if(active == 'partners_home'){
@ -137,6 +148,14 @@ function multi_change(prevID, nextID){
return return
} }
if(nextID == 'app_school'){
active = $$('multi_school').getActiveId()
if(active == 'school_home'){
init_config_school()
}
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,154 @@
var controllers_school = {
init: function(){
$$('cmd_new_student').attachEvent('onItemClick', cmd_new_student_click)
$$('cmd_edit_student').attachEvent('onItemClick', cmd_edit_student_click)
$$('cmd_delete_student').attachEvent('onItemClick', cmd_delete_student_click)
$$('cmd_save_student').attachEvent('onItemClick', cmd_save_student_click)
$$('cmd_cancel_student').attachEvent('onItemClick', cmd_cancel_student_click)
}
}
function get_school_groups(){
webix.ajax().get('/values/schoolgroups', {
error: function(text, data, xhr) {
},
success: function(text, data, xhr) {
var values = data.json();
$$('student_grupo').define('suggest', values)
$$('student_grupo').refresh()
}
})
}
function init_config_school(){
get_students()
get_school_groups()
}
function cmd_new_student_click(){
$$('form_student').setValues({})
$$('grid_students').clearSelection()
$$('multi_school').setValue('new_student')
}
function cmd_edit_student_click(){
var row = $$('grid_students').getSelectedItem()
if (row == undefined){
msg = 'Selecciona un Alumno'
msg_error(msg)
return
}
webix.ajax().get('/students', {id: row['id']}, {
error: function(text, data, xhr) {
msg_error()
},
success: function(text, data, xhr){
var values = data.json()
$$('form_student').setValues(values)
}
})
$$('multi_school').setValue('new_student')
}
function delete_student(id){
webix.ajax().del('/students', {id: id}, function(text, xml, xhr){
msg = 'Alumno eliminado correctamente'
if (xhr.status == 200){
$$('grid_students').remove(id);
msg_ok(msg)
} else {
msg = 'No se pudo eliminar.'
msg_error(msg)
}
})
}
function cmd_delete_student_click(){
var row = $$('grid_students').getSelectedItem()
if (row == undefined){
msg = 'Selecciona un Alumno'
msg_error(msg)
return
}
msg = '¿Estás seguro de eliminar al Alumno?<BR><BR>'
msg += row['nombre'] + ' ' + row['paterno'] + ' (' + row['rfc'] + ')'
msg += '<BR><BR>ESTA ACCIÓN NO SE PUEDE DESHACER<BR><BR>'
webix.confirm({
title:'Eliminar Alumno',
ok:'Si',
cancel:'No',
type:'confirm-error',
text:msg,
callback:function(result){
if (result){
delete_student(row['id'])
}
}
})
}
function cmd_cancel_student_click(){
$$('multi_school').setValue('school_home')
}
function cmd_save_student_click(){
var form = this.getFormView();
if (!form.validate()) {
msg_error(msg)
return
}
var values = form.getValues();
opt = 'add'
if(values.id){
opt = 'edit'
}
webix.ajax().post('/students', {opt: opt, values: values}, {
error:function(text, data, XmlHttpRequest){
msg = 'Ocurrio un error, consulta a soporte técnico';
msg_error(msg)
},
success:function(text, data, XmlHttpRequest){
var values = data.json();
if (values.ok) {
form.setValues({})
$$('multi_school').setValue('school_home')
get_students()
} else {
msg_error(values.msg)
}
}
})
}
function get_students(){
webix.ajax().get('/students', {}, {
error: function(text, data, xhr) {
msg_error('Error al consultar')
},
success: function(text, data, xhr) {
var values = data.json()
$$('grid_students').clearAll()
$$('grid_students').parse(values)
}
})
}

View File

@ -377,6 +377,12 @@ function validate_pedimento(value){
} }
function validate_curp(value){
var pattern = '[A-Z][A,E,I,O,U,X][A-Z]{2}[0-9]{2}[0-1][0-9][0-3][0-9][M,H][A-Z]{2}[B,C,D,F,G,H,J,K,L,M,N,Ñ,P,Q,R,S,T,V,W,X,Y,Z]{3}[0-9,A-Z][0-9]'
return validate_regexp(value, pattern)
}
//config may as well include only text, color and date hash //config may as well include only text, color and date hash
webix.editors.$popup = { webix.editors.$popup = {
text:{ text:{

View File

@ -48,6 +48,72 @@ var admin_ui_windows = {
} }
var grid_cols_niveles_educativos = [
{id: 'id', header: 'ID', hidden: true},
{id: 'delete', header: '', width: 30, css: 'delete'},
{id: 'nombre', header: 'Nivel', fillspace: 1},
{id: 'autorizacion', header: 'Autorización', fillspace: 1},
]
var grid_niveles_educativos = {
view: 'datatable',
id: 'grid_niveles_educativos',
select: 'cell',
adjust: true,
autoheight: true,
headermenu: true,
columns: grid_cols_niveles_educativos,
on:{
'data->onStoreUpdated':function(){
this.data.each(function(obj, i){
obj.delete = '-'
})
}
},
}
var form_controls_niveles_educativos = [
{cols: [
{view: 'text', id: 'txt_nivel_educativo', label: 'Nivel', suggest: '/values/nivedusat',
labelPosition: 'top', name: 'nombre', required: true},
{view: "text", id: 'txt_auth_rvoe', label: 'Autorización',
name: 'autorizacion', labelPosition: 'top'},
{view: 'button', type: 'iconTop', icon: 'plus', label: 'Agregar',
autowidth: true, click: function(){
add_nivel_educativo_click()
}}
]},
grid_niveles_educativos,
{},
{cols:[{},
{view: "button", value: 'Cerrar', click: "$$('win_niveles_educativos').close()"},
{}]}
]
var admin_ui_niveles_educativos = {
init: function(){
webix.ui({
view: 'window',
id: 'win_niveles_educativos',
head: 'Niveles Educativos',
width: 500,
modal: true,
position: 'center',
body: {
view: 'form', id: 'form_niveles_educativos',
elements: form_controls_niveles_educativos
}
})
$$('grid_niveles_educativos').attachEvent('onItemClick', grid_niveles_educativos_click)
},
}
var menu_data = [ var menu_data = [
{id: 'app_home', icon: 'dashboard', value: 'Inicio'}, {id: 'app_home', icon: 'dashboard', value: 'Inicio'},
{id: 'app_emisor', icon: 'user-circle', value: 'Emisor'}, {id: 'app_emisor', icon: 'user-circle', value: 'Emisor'},
@ -129,7 +195,7 @@ var emisor_otros_datos= [
{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'},
{view: 'button', id: 'cmd_niveles', label: 'Niveles Escolares', {view: 'button', id: 'cmd_niveles_educativos', label: 'Niveles Educativos',
type: 'form', align: 'center', autowidth: true, disabled: true}, type: 'form', align: 'center', autowidth: true, disabled: true},
{}, {}]}, {}, {}]},
{template: 'ONG', type: 'section'}, {template: 'ONG', type: 'section'},

View File

@ -285,6 +285,8 @@ var grid_details_cols = [
{id: "descripcion", header:{text: 'Descripción', css: 'center'}, {id: "descripcion", header:{text: 'Descripción', css: 'center'},
fillspace: true, editor: 'popup'}, fillspace: true, editor: 'popup'},
{id: "pedimento", header: 'Pedimento', editor: 'text', hidden: true}, {id: "pedimento", header: 'Pedimento', editor: 'text', hidden: true},
{id: "id_student", header: 'ID_Alumno', hidden: true},
{id: 'student', header: 'Alumno', hidden: true, width: 150},
{id: "unidad", header:{text: 'Unidad', css: 'center'}, width: 100}, {id: "unidad", header:{text: 'Unidad', css: 'center'}, width: 100},
{id: 'cantidad', header: {text: 'Cantidad', css: 'center'}, width: 100, {id: 'cantidad', header: {text: 'Cantidad', css: 'center'}, width: 100,
format: webix.i18n.numberFormat, css: 'right', editor: 'text'}, format: webix.i18n.numberFormat, css: 'right', editor: 'text'},
@ -386,6 +388,31 @@ var suggest_products = {
} }
var suggest_students = {
view: 'gridsuggest',
id: 'grid_students_found',
name: 'grid_students_found',
body: {
autoConfig: false,
header: false,
columns: [
{id: 'id', hidden: true},
{id: 'nombre', adjust: 'data'},
{id: 'paterno', adjust: 'data'},
{id: 'materno', adjust: 'data'},
{id: 'rfc', adjust: 'data'},
],
dataFeed:function(text){
if (text.length > 2){
this.load('/values/student?name=' + text)
}else{
this.hide()
}
}
}
}
var body_comprobante = {rows: [{ var body_comprobante = {rows: [{
cols: [ cols: [
{ {
@ -450,6 +477,13 @@ var body_regimen_fiscal = {
} }
var body_students = {rows:[
{view: 'search', id: 'search_student',
name: "search_student", label: "por Nombre o RFC",
labelPosition:'top', suggest: suggest_students,
placeholder:'Captura al menos tres letras'},
]}
var controls_generate = [ var controls_generate = [
{minHeight: 10, maxHeight: 10}, {minHeight: 10, maxHeight: 10},
toolbar_invoices_generate, toolbar_invoices_generate,
@ -484,7 +518,9 @@ var controls_generate = [
labelPosition:'top', suggest: suggest_products, labelPosition:'top', suggest: suggest_products,
placeholder:'Captura al menos tres letras'}, placeholder:'Captura al menos tres letras'},
]}, ]},
]}} ]}},
{view: 'fieldset', id: 'fs_students', label: 'Buscar Alumno',
body: body_students},
]}, ]},
{maxWidth: 10}, {maxWidth: 10},
{maxWidth: 300, rows: [ {maxWidth: 300, rows: [

View File

@ -37,6 +37,7 @@ var multi_main = {
app_partners, app_partners,
app_products, app_products,
app_bancos, app_bancos,
app_school,
app_tickets, app_tickets,
app_invoices, app_invoices,
], ],

View File

@ -0,0 +1,147 @@
var toolbar_students = [
{view: 'button', id: 'cmd_new_student', label: 'Nuevo', type: 'iconButton',
autowidth: true, icon: 'user-plus'},
{view: 'button', id: 'cmd_edit_student', label: 'Editar', type: 'iconButton',
autowidth: true, icon: 'user'},
{view: 'button', id: 'cmd_delete_student', label: 'Eliminar', type: 'iconButton',
autowidth: true, icon: 'user-times'},
]
var grid_cols_students = [
{id: 'index', header:'#', css: 'right',
footer: {content: 'countRows', colspan: 2, css: 'right'}},
{id: 'id', header: 'Clave', sort: 'int', css: 'right'},
{id: 'nombre', header: ['Nombre', {content: 'textFilter'}],
sort: 'string'},
{id: 'paterno', header: ['A. Paterno', {content: 'textFilter'}],
sort: 'string'},
{id: 'materno', header: ['A. Materno', {content: 'textFilter'}],
sort: 'string'},
{id: 'rfc', header: ['RFC', {content: 'textFilter'}], adjust: 'data',
sort: 'string'},
{id: 'curp', header: ['CURP'], sort: 'string'},
]
var grid_students = {
view: 'datatable',
id: 'grid_students',
select: 'row',
adjust: true,
footer: true,
resizeColumn: true,
headermenu: true,
columns: grid_cols_students,
ready:function(){
this.adjustColumn('index');
this.adjustColumn('id');
this.adjustColumn('nombre');
this.adjustColumn('rfc');
this.adjustColumn('curp');
},
on:{
'data->onStoreUpdated':function(){
this.data.each(function(obj, i){
obj.index = i+1;
})
}
},
}
var rows_school_home = [
{view: 'toolbar', elements: toolbar_students},
grid_students,
]
var student_controls_generales = [
{view: 'text', id: 'student_name', name: 'nombre', label: 'Nombre: ',
required: true, invalidMessage: 'El nombre es requerido'},
{view: 'text', id: 'student_paterno', name: 'paterno', label: 'Apellido Paterno: ',
required: true, invalidMessage: 'El apellido paterno es requerido'},
{view: 'text', id: 'student_materno', name: 'materno',
label: 'Apellido Materno: '},
{cols: [
{view: 'text', id: 'student_rfc', name: 'rfc', label: 'RFC: ',
required: true, invalidMessage: 'RFC inválido', adjust: 'data',
attributes: {maxlength: 13}},
{view: 'text', id: 'student_curp', name: 'curp', label: 'CURP: ',
required: true, invalidMessage: 'CURP inválido', adjust: 'data',
attributes: {maxlength: 20}},
{}]},
{cols: [
{view: 'richselect', id: 'student_grupo', name: 'grupo',
label: 'Nivel Educativo: ', required: true, options: [],
invalidMessage: 'El Nivel Educativo es requerido'},
{},
]},
]
var form_controls_student = [
{
view: 'tabview',
id: 'tab_student',
tabbar: {options: ['Datos Generales']}, animate: true,
cells: [
{id: 'Datos Generales', rows: student_controls_generales},
]
},
{rows: [
{ template:"", type: "section" },
{ margin: 10, cols: [{},
{view: "button", id: "cmd_save_student", label: "Guardar" ,
type: "form", autowidth: true, align: "center"},
{view: "button", id: "cmd_cancel_student", label: "Cancelar" ,
type: "danger", autowidth: true, align: "center"},
{}]
},
]}
]
var form_student = {
type: 'space',
cols: [{
view: 'form',
id: 'form_student',
complexData: true,
scroll: true,
elements: form_controls_student,
elementsConfig: {
labelWidth: 150,
labelAlign: 'right'
},
rules: {
nombre: function(value){ return value.trim() != '';},
rfc: validate_rfc,
curp: validate_curp,
}
}]
}
var multi_school = {
id: 'multi_school',
view: 'multiview',
animate: true,
cells:[
{id: 'school_home', rows: rows_school_home},
{id: 'school_groups', rows: []},
{id: 'new_student', rows: [form_student]},
],
}
var app_school = {
id: 'app_school',
rows:[
{view: 'template', id: 'th_school', type: 'header',
template: 'Administración de Escuela'},
multi_school
],
}

View File

@ -8,6 +8,7 @@
<script src="/static/js/ui/partners.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/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/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>
@ -15,6 +16,7 @@
<script src="/static/js/controller/partners.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/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/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

@ -11,6 +11,7 @@
<xsl:include href="implocal.xslt"/> <xsl:include href="implocal.xslt"/>
<xsl:include href="donat11.xslt"/> <xsl:include href="donat11.xslt"/>
<xsl:include href="ine11.xslt"/> <xsl:include href="ine11.xslt"/>
<xsl:include href="iedu.xslt"/>
<!-- <!--
<xsl:include href="ecc11.xslt"/> <xsl:include href="ecc11.xslt"/>
<xsl:include href="Divisas.xslt"/> <xsl:include href="Divisas.xslt"/>
@ -27,7 +28,6 @@
<xsl:include href="renovacionysustitucionvehiculos.xslt"/> <xsl:include href="renovacionysustitucionvehiculos.xslt"/>
<xsl:include href="certificadodedestruccion.xslt"/> <xsl:include href="certificadodedestruccion.xslt"/>
<xsl:include href="obrasarteantiguedades.xslt"/> <xsl:include href="obrasarteantiguedades.xslt"/>
<xsl:include href="iedu.xslt"/>
<xsl:include href="ventavehiculos11.xslt"/> <xsl:include href="ventavehiculos11.xslt"/>
<xsl:include href="terceros11.xslt"/> <xsl:include href="terceros11.xslt"/>
<xsl:include href="Pagos10.xslt"/> <xsl:include href="Pagos10.xslt"/>

26
source/xslt/iedu.xslt Normal file
View File

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