Import nomina from template
This commit is contained in:
parent
b4cab5aa2f
commit
cd8bd1ceeb
|
@ -424,6 +424,29 @@ class AppEmployees(object):
|
||||||
resp.status = falcon.HTTP_204
|
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):
|
||||||
|
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):
|
||||||
|
|
|
@ -1013,6 +1013,27 @@ class LIBO(object):
|
||||||
msg = 'Empleados importados correctamente'
|
msg = 'Empleados importados correctamente'
|
||||||
return rows, msg
|
return rows, msg
|
||||||
|
|
||||||
|
def nomina(self, path):
|
||||||
|
options = {'AsTemplate': True, 'Hidden': True}
|
||||||
|
doc = self._doc_open(path, options)
|
||||||
|
if doc is None:
|
||||||
|
return ()
|
||||||
|
|
||||||
|
data, msg = self._get_data(doc, 'Nomina')
|
||||||
|
doc.close(True)
|
||||||
|
|
||||||
|
if len(data) == 1:
|
||||||
|
msg = 'Sin datos para importar'
|
||||||
|
return (), msg
|
||||||
|
|
||||||
|
fields = (
|
||||||
|
'num_empleado',
|
||||||
|
'rfc',
|
||||||
|
)
|
||||||
|
rows = tuple([dict(zip(fields, r)) for r in data[1:]])
|
||||||
|
msg = 'Nomina importada correctamente'
|
||||||
|
return rows, msg
|
||||||
|
|
||||||
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)
|
||||||
|
@ -1072,6 +1093,20 @@ def import_employees(rfc):
|
||||||
return ()
|
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)
|
||||||
|
|
||||||
|
@ -1504,6 +1539,15 @@ def upload_file(rfc, opt, file_obj):
|
||||||
|
|
||||||
name = '{}_employees.ods'.format(rfc.lower())
|
name = '{}_employees.ods'.format(rfc.lower())
|
||||||
path = _join(PATH_MEDIA, 'tmp', name)
|
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)
|
||||||
|
|
||||||
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}
|
||||||
|
|
|
@ -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, AppEmployees
|
AppMovimientosBanco, AppTickets, AppEmployees, AppNomina
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ 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('/employees', AppEmployees(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
|
||||||
|
|
|
@ -14,6 +14,9 @@ class StorageEngine(object):
|
||||||
def get_employees(self, values):
|
def get_employees(self, values):
|
||||||
return main.Empleados.get_by(values)
|
return main.Empleados.get_by(values)
|
||||||
|
|
||||||
|
def get_nomina(self, values):
|
||||||
|
return main.CfdiNomina.get_by(values)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,8 @@ def desconectar():
|
||||||
def upload_file(rfc, opt, file_obj):
|
def upload_file(rfc, opt, file_obj):
|
||||||
result = util.upload_file(rfc, opt, file_obj)
|
result = util.upload_file(rfc, opt, file_obj)
|
||||||
if result['ok']:
|
if result['ok']:
|
||||||
if opt != 'bdfl':
|
names = ('bdfl', 'employees', 'nomina', 'products', 'invoiceods')
|
||||||
|
if not opt in names:
|
||||||
Configuracion.add({opt: file_obj.filename})
|
Configuracion.add({opt: file_obj.filename})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -197,7 +198,7 @@ def config_main():
|
||||||
nomina = util.get_bool(Configuracion.get_('chk_usar_nomina'))
|
nomina = util.get_bool(Configuracion.get_('chk_usar_nomina'))
|
||||||
data = {
|
data = {
|
||||||
'empresa': get_title_app(3),
|
'empresa': get_title_app(3),
|
||||||
'punto_de_venta': punto_de_venta
|
'punto_de_venta': punto_de_venta,
|
||||||
'nomina': nomina,
|
'nomina': nomina,
|
||||||
}
|
}
|
||||||
if not obj is None:
|
if not obj is None:
|
||||||
|
@ -5526,6 +5527,53 @@ class CfdiNomina(BaseModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
order_by = ('fecha',)
|
order_by = ('fecha',)
|
||||||
|
|
||||||
|
def _validate_import(self, row):
|
||||||
|
sn = {'si': True, 'no': False}
|
||||||
|
data = row.copy()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def _import(self):
|
||||||
|
emisor = Emisor.select()[0]
|
||||||
|
rows, msg = util.import_nomina(emisor.rfc)
|
||||||
|
if not rows:
|
||||||
|
return {'ok': False, 'msg': msg}
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
data = self._validate_import(self, row)
|
||||||
|
# ~ w = (Nomina.empleado.rfc==row['rfc'])
|
||||||
|
with database_proxy.transaction():
|
||||||
|
pass
|
||||||
|
# ~ if Empleados.select().where(w).exists():
|
||||||
|
# ~ q = Empleados.update(**data).where(w)
|
||||||
|
# ~ q.execute()
|
||||||
|
# ~ else:
|
||||||
|
# ~ obj = Empleados.create(**data)
|
||||||
|
return {'ok': True, 'msg': msg}
|
||||||
|
|
||||||
|
def _get(self):
|
||||||
|
rows = (nomina
|
||||||
|
.select(
|
||||||
|
Nomina.id,
|
||||||
|
Nomina.serie,
|
||||||
|
Nomina.folio,
|
||||||
|
Nomina.fecha,
|
||||||
|
Nomina.status,
|
||||||
|
Nomina.fecha_pago,
|
||||||
|
Nomina.total,
|
||||||
|
Nomina.empleado.nombre_completo
|
||||||
|
)
|
||||||
|
.dicts()
|
||||||
|
)
|
||||||
|
return {'ok': True, 'rows': tuple(rows)}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_by(cls, values):
|
||||||
|
if not 'opt' in values:
|
||||||
|
return cls._get(cls)
|
||||||
|
|
||||||
|
if values['opt'] == 'import':
|
||||||
|
return cls._import(cls)
|
||||||
|
|
||||||
|
|
||||||
class CfdiNominaDetalle(BaseModel):
|
class CfdiNominaDetalle(BaseModel):
|
||||||
cfdi = ForeignKeyField(CfdiNomina)
|
cfdi = ForeignKeyField(CfdiNomina)
|
||||||
|
|
|
@ -39,8 +39,82 @@ function current_dates_nomina(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function get_nomina(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function cmd_nomina_import_click(){
|
function cmd_nomina_import_click(){
|
||||||
msg_ok('ok')
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -201,3 +201,35 @@ var win_import_employees = {
|
||||||
$$('up_employees').attachEvent('onUploadComplete', up_employees_upload_complete)
|
$$('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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue