diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py
index 4192e3b..59cb9e1 100644
--- a/source/app/controllers/main.py
+++ b/source/app/controllers/main.py
@@ -221,6 +221,29 @@ class AppPartners(object):
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):
def __init__(self, db):
diff --git a/source/app/main.py b/source/app/main.py
index 2aa6e39..21c96ee 100644
--- a/source/app/main.py
+++ b/source/app/main.py
@@ -16,7 +16,7 @@ from controllers.main import (AppEmpresas,
AppLogin, AppLogout, AppAdmin, AppEmisor, AppConfig,
AppMain, AppValues, AppPartners, AppProducts, AppInvoices, AppFolios,
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('/cuentasbanco', AppCuentasBanco(db))
api.add_route('/movbanco', AppMovimientosBanco(db))
+api.add_route('/students', AppStudents(db))
# ~ Activa si usas waitress y NO estas usando servidor web
diff --git a/source/app/models/db.py b/source/app/models/db.py
index 98fce0d..0e6b1f0 100644
--- a/source/app/models/db.py
+++ b/source/app/models/db.py
@@ -299,6 +299,14 @@ class StorageEngine(object):
#~ 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'])
+
def tickets(self, values, user):
opt = values.pop('opt')
if opt == 'add':
diff --git a/source/app/models/main.py b/source/app/models/main.py
index 136ffb3..f5b4cb5 100644
--- a/source/app/models/main.py
+++ b/source/app/models/main.py
@@ -195,12 +195,13 @@ def config_main():
punto_de_venta = util.get_bool(Configuracion.get_('chk_usar_punto_de_venta'))
data = {
'empresa': get_title_app(3),
- 'punto_de_venta': punto_de_venta
-
+ 'punto_de_venta': punto_de_venta,
+ 'escuela': False,
}
if not obj is None:
titulo = '{} - {}'
data['empresa'] = titulo.format(data['empresa'], obj.nombre)
+ data['escuela'] = obj.es_escuela
return data
@@ -2154,6 +2155,43 @@ class Alumnos(BaseModel):
class Meta:
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(cls, values):
+ 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
+
class AlumnosParientes(BaseModel):
alumno = ForeignKeyField(Alumnos)
diff --git a/source/static/js/controller/main.js b/source/static/js/controller/main.js
index d2bbf9e..5e4575d 100644
--- a/source/static/js/controller/main.js
+++ b/source/static/js/controller/main.js
@@ -10,12 +10,21 @@ function configuracion_inicial(){
var values = data.json()
$$('lbl_title_main').setValue(values.empresa)
//~ 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){
var node = {
id: 'app_tickets',
icon: 'money',
value: 'Punto de venta'}
- $$('main_sidebar').add(node, 4)
+ $$('main_sidebar').add(node, pos)
}
})
@@ -45,6 +54,7 @@ var controllers = {
products_controllers.init()
bancos_controllers.init()
invoices_controllers.init()
+ controllers_school.init()
tickets_controllers.init()
}
}
@@ -113,6 +123,7 @@ function current_dates(){
function multi_change(prevID, nextID){
+
if(nextID == 'app_partners'){
active = $$('multi_partners').getActiveId()
if(active == 'partners_home'){
@@ -137,6 +148,14 @@ function multi_change(prevID, nextID){
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'){
diff --git a/source/static/js/controller/school.js b/source/static/js/controller/school.js
new file mode 100644
index 0000000..5f5a080
--- /dev/null
+++ b/source/static/js/controller/school.js
@@ -0,0 +1,70 @@
+
+
+var controllers_school = {
+ init: function(){
+ $$('cmd_new_student').attachEvent('onItemClick', cmd_new_student_click)
+ $$('cmd_save_student').attachEvent('onItemClick', cmd_save_student_click)
+ $$('cmd_cancel_student').attachEvent('onItemClick', cmd_cancel_student_click)
+ }
+}
+
+
+function init_config_school(){
+ get_students()
+}
+
+
+function cmd_new_student_click(){
+ $$('grid_students').clearSelection()
+ $$('multi_school').setValue('new_student')
+}
+
+
+function cmd_cancel_student_click(){
+ $$('multi_school').setValue('school_home')
+}
+
+
+function cmd_save_student_click(){
+ var msg = 'Valores inválidos'
+ var form = this.getFormView();
+
+ if (!form.validate()) {
+ msg_error(msg)
+ return
+ }
+
+ var values = form.getValues();
+
+ webix.ajax().post('/students', {opt: 'add', 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)
+ }
+ })
+}
\ No newline at end of file
diff --git a/source/static/js/controller/util.js b/source/static/js/controller/util.js
index 0081054..de495ba 100644
--- a/source/static/js/controller/util.js
+++ b/source/static/js/controller/util.js
@@ -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
webix.editors.$popup = {
text:{
diff --git a/source/static/js/ui/main.js b/source/static/js/ui/main.js
index cd6bdaf..7462eae 100644
--- a/source/static/js/ui/main.js
+++ b/source/static/js/ui/main.js
@@ -37,6 +37,7 @@ var multi_main = {
app_partners,
app_products,
app_bancos,
+ app_school,
app_tickets,
app_invoices,
],
diff --git a/source/static/js/ui/school.js b/source/static/js/ui/school.js
new file mode 100644
index 0000000..2af1a23
--- /dev/null
+++ b/source/static/js/ui/school.js
@@ -0,0 +1,143 @@
+
+
+
+
+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}},
+ {}]},
+]
+
+
+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
+ ],
+}
diff --git a/source/templates/main.html b/source/templates/main.html
index d5395ca..eb2a7aa 100644
--- a/source/templates/main.html
+++ b/source/templates/main.html
@@ -8,6 +8,7 @@
+
@@ -15,6 +16,7 @@
+