From f4309477087fd22cd33f67440a5b3133ab21226c Mon Sep 17 00:00:00 2001 From: Mauricio Baeza Date: Thu, 21 Dec 2017 01:13:28 -0600 Subject: [PATCH] Filtrar tickets. Cancelar tickets --- source/app/controllers/util.py | 4 + source/app/models/db.py | 8 ++ source/app/models/main.py | 67 ++++++++++++ source/static/css/app.css | 4 + source/static/js/controller/main.js | 5 +- source/static/js/controller/tickets.js | 136 ++++++++++++++++++++++++- source/static/js/controller/util.js | 2 +- source/static/js/ui/invoices.js | 7 ++ source/static/js/ui/partners.js | 4 +- source/static/js/ui/tickets.js | 12 ++- 10 files changed, 238 insertions(+), 11 deletions(-) diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index 6077607..fec29c8 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -235,6 +235,10 @@ def now(): return datetime.datetime.now().replace(microsecond=0) +def today(): + return datetime.date.today() + + def get_token(): return _get_hash(uuid.uuid4().hex) diff --git a/source/app/models/db.py b/source/app/models/db.py index 693e05f..89df7f6 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -77,6 +77,9 @@ class StorageEngine(object): years2 = main.PreFacturas.filter_years() return [years1, years2] + def _get_filteryearsticket(self, values): + return main.Tickets.filter_years() + def _get_cuentayears(self, values): return main.CuentasBanco.get_years() @@ -258,6 +261,11 @@ class StorageEngine(object): opt = values.pop('opt') if opt == 'add': return main.Tickets.add(values) + if opt == 'cancel': + return main.Tickets.cancel(values) + + def get_tickets(self, values): + return main.Tickets.get_by(values) def get_invoices(self, values): return main.Facturas.get_(values) diff --git a/source/app/models/main.py b/source/app/models/main.py index c0a689b..bd5d43f 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -3972,6 +3972,73 @@ class Tickets(BaseModel): data = {'ok': True, 'row': row} return data + @classmethod + def cancel(cls, values): + id = int(values['id']) + msg = 'Ticket cancelado correctamente' + u = {'cancelado': True, 'estatus': 'Cancelado'} + obj = Tickets.update(**u).where(Tickets.id==id) + result = bool(obj.execute()) + row = {'estatus': 'Cancelado'} + return {'ok': result, 'row': row, 'msg': msg} + + def _get_filters(self, values): + opt = values.get('opt', '') + if not opt: + return + + if opt == 'today': + t = util.today() + filters = ( + (Tickets.fecha.day == t.day) & + (Tickets.fecha.month == t.month) & + (Tickets.fecha.year == t.year) + ) + return filters + + if opt == 'yearmonth': + if values['year'] == '-1': + fy = (Tickets.fecha.year > 0) + else: + fy = (Tickets.fecha.year == int(values['year'])) + if values['month'] == '-1': + fm = (Tickets.fecha.month > 0) + else: + fm = (Tickets.fecha.month == int(values['month'])) + filters = (fy & fm) + return filters + + return + + @classmethod + def get_by(cls, values): + filters = cls._get_filters(cls, values) + + rows = tuple(Tickets + .select( + Tickets.id, + Tickets.serie, + Tickets.folio, + Tickets.fecha, + Tickets.estatus, + Tickets.total) + .where(filters) + .dicts() + ) + return {'ok': True, 'rows': rows} + + @classmethod + def filter_years(cls): + data = [{'id': -1, 'value': 'Todos'}] + rows = (Tickets + .select(Tickets.fecha.year.alias('year')) + .group_by(Tickets.fecha.year) + .order_by(Tickets.fecha.year) + ) + if not rows is None: + data += [{'id': int(r.year), 'value': int(r.year)} for r in rows] + return tuple(data) + class TicketsDetalle(BaseModel): ticket = ForeignKeyField(Tickets) diff --git a/source/static/css/app.css b/source/static/css/app.css index 3ddaa5a..0bd1d39 100644 --- a/source/static/css/app.css +++ b/source/static/css/app.css @@ -54,6 +54,10 @@ color: red; } +.cancel { + color: red; +} + .cmd_close_partner div button { background-color: red !important; diff --git a/source/static/js/controller/main.js b/source/static/js/controller/main.js index 1d707cb..f7be4f1 100644 --- a/source/static/js/controller/main.js +++ b/source/static/js/controller/main.js @@ -206,7 +206,10 @@ function multi_change(prevID, nextID){ } if(nextID == 'app_tickets'){ - + active = $$('multi_tickets').getActiveId() + if(active == 'tickets_home'){ + configuracion_inicial_ticket() + } return } diff --git a/source/static/js/controller/tickets.js b/source/static/js/controller/tickets.js index c1bfc63..6adcffa 100644 --- a/source/static/js/controller/tickets.js +++ b/source/static/js/controller/tickets.js @@ -7,28 +7,99 @@ var tickets_controllers = { $$('cmd_nuevo_ticket').attachEvent('onItemClick', cmd_nuevo_ticket_click) $$('cmd_generar_ticket').attachEvent('onItemClick', cmd_generar_ticket_click) $$('cmd_cerrar_ticket').attachEvent('onItemClick', cmd_cerrar_ticket_click) + $$('cmd_cancelar_ticket').attachEvent('onItemClick', cmd_cancelar_ticket_click) $$('tsearch_product_key').attachEvent('onKeyPress', tsearch_product_key_press) $$('grid_tdetails').attachEvent('onItemClick', grid_ticket_details_click) $$('grid_tdetails').attachEvent('onBeforeEditStop', grid_tickets_details_before_edit_stop) $$('gt_productos_found').attachEvent('onValueSuggest', gt_productos_found_click) + $$('filter_year_ticket').attachEvent('onChange', filter_year_ticket_change) + $$('filter_month_ticket').attachEvent('onChange', filter_month_ticket_change) + + webix.extend($$('grid_tickets'), webix.ProgressBar) } } +function current_dates_tickets(){ + var fy = $$('filter_year_ticket') + var fm = $$('filter_month_ticket') + var d = new Date() + + fy.blockEvent() + fm.blockEvent() + + fm.setValue(d.getMonth() + 1) + webix.ajax().sync().get('/values/filteryearsticket', function(text, data){ + var values = data.json() + fy.getList().parse(values) + fy.setValue(d.getFullYear()) + }) + + fy.unblockEvent() + fm.unblockEvent() +} + + +function get_tickets(filters){ + if(filters == undefined){ + filters = {'opt': 'today'} + } + + var grid = $$('grid_tickets') + grid.showProgress({type: 'icon'}) + + webix.ajax().get('/tickets', filters, { + error: function(text, data, xhr) { + msg_error('Error al consultar') + }, + success: function(text, data, xhr) { + var values = data.json(); + grid.clearAll(); + if (values.ok){ + grid.parse(values.rows, 'json') + } + } + }) +} + + +function filter_year_ticket_change(nv, ov){ + var fm = $$('filter_month_ticket') + filters = {'opt': 'yearmonth','year': nv, 'month': fm.getValue()} + get_tickets(filters) +} + + +function filter_month_ticket_change(nv, ov){ + var fy = $$('filter_year_ticket') + filters = {'opt': 'yearmonth','year': fy.getValue(), 'month': nv} + get_tickets(filters) +} + + function configuracion_inicial_ticket(){ + current_dates_tickets() + get_tickets() +} + + +function configuracion_inicial_nuevo_ticket(){ + var grid = $$('grid_tdetails') + webix.ajax().sync().get('/values/taxes', function(text, data){ var values = data.json() table_taxes.clear() table_taxes.insert(values) }) get_forma_pago('lst_ticket_forma_pago') + grid.clearAll() table_pt.clear() table_totals.clear() } function cmd_nuevo_ticket_click(){ - configuracion_inicial_ticket() + configuracion_inicial_nuevo_ticket() $$('multi_tickets').setValue('tickets_new') } @@ -48,10 +119,10 @@ function validar_ticket(){ function guardar_ticket(values){ - var grid = $$('grid_tdetails') - //~ showvar(values) + var gd = $$('grid_tdetails') + var grid = $$('grid_tickets') - var rows = grid.data.getRange() + var rows = gd.data.getRange() for (i = 0; i < rows.length; i++) { delete rows[i]['delete'] delete rows[i]['clave'] @@ -77,6 +148,8 @@ function guardar_ticket(values){ if(values.ok){ msg_ok('Ticket generado correctamente') $$('form_new_ticket').setValues({}) + gd.clearAll() + grid.add(values.row) $$('multi_tickets').setValue('tickets_home') }else{ msg_error(values.msg) @@ -264,3 +337,58 @@ function gt_productos_found_click(obj){ buscar_producto_key(obj.clave) } + +function cancel_ticket(id){ + var grid = $$('grid_tickets') + var data = new Object() + data['opt'] = 'cancel' + data['id'] = id + + webix.ajax().sync().post('tickets', 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_cancelar_ticket_click(){ + var grid = $$('grid_tickets') + + if(grid.count() == 0){ + return + } + + var row = grid.getSelectedItem() + if (row == undefined){ + msg_error('Selecciona un ticket') + return + } + + msg = '¿Estás seguro de cancelar el siguiente Ticket?

' + msg += 'Folio: ' + row['folio'] + msg += '

ESTA ACCIÓN NO SE PUEDE DESHACER' + webix.confirm({ + title:'Cancelar Ticket', + ok:'Si', + cancel:'No', + type:'confirm-error', + text:msg, + callback:function(result){ + if (result){ + cancel_ticket(row['id']) + } + } + }) + +} \ No newline at end of file diff --git a/source/static/js/controller/util.js b/source/static/js/controller/util.js index fc8e90d..0beb469 100644 --- a/source/static/js/controller/util.js +++ b/source/static/js/controller/util.js @@ -39,7 +39,7 @@ function get_icon(tipo){ pdf: 'fa-file-pdf-o', zip: 'fa-file-zip-o', email: 'fa-envelope-o', - print: 'print', + print: 'fa-print', } return "" } diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index c183c19..7d1327a 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -216,6 +216,13 @@ var grid_invoices = { resizeColumn: true, headermenu: true, columns: grid_invoices_cols, + scheme:{ + $change:function(item){ + if (item.estatus == 'Cancelada'){ + item.$css = 'cancel' + } + } + }, on:{ 'data->onStoreUpdated':function(){ this.data.each(function(obj, i){ diff --git a/source/static/js/ui/partners.js b/source/static/js/ui/partners.js index 4b763fe..bc082c7 100644 --- a/source/static/js/ui/partners.js +++ b/source/static/js/ui/partners.js @@ -12,7 +12,7 @@ var toolbar_partners = [ var grid_partners_cols = [ {id: 'index', header:'#', css: 'right', - footer: {content: 'rowCount', colspan: 2, css: 'right'}}, + footer: {content: 'countRows', colspan: 2, css: 'right'}}, {id: 'id', header: 'Clave', sort: 'int', css: 'right'}, {id: 'rfc', header: ['RFC', {content: 'textFilter'}], adjust: 'data', sort: 'string', footer: {text: 'Clientes y Proveedores', colspan: 2}}, @@ -143,7 +143,7 @@ var toolbar_contacts = [ var grid_contacts_cols = [ {id: 'index', header: '#', adjust:'data', css:'right', - footer: {content: 'rowCount'}}, + footer: {content: 'countRows'}}, {id: 'id', header: '', hidden: true}, {id: 'title', header: 'Título', adjust:'data', sort: 'string', footer: 'Contactos'}, diff --git a/source/static/js/ui/tickets.js b/source/static/js/ui/tickets.js index 7087603..a60051c 100644 --- a/source/static/js/ui/tickets.js +++ b/source/static/js/ui/tickets.js @@ -24,8 +24,8 @@ var grid_tickets_cols = [ footer: {content: 'countRows', colspan: 3, css: 'right'}}, {id: "id", header:"ID", hidden:true}, {id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data", - sort:"string"}, - {id: 'folio', header: ['Folio', {content: 'numberFilter'}], adjust: 'data', + sort:"string", hidden: true}, + {id: 'folio', header: ['Folio', {content: 'numberFilter'}], adjust: 'header', sort: 'int', css: 'right', footer: {text: 'Tickets', colspan: 3}}, {id: "fecha", header: ["Fecha y Hora"], adjust: "data", sort: "date"}, @@ -37,7 +37,6 @@ var grid_tickets_cols = [ fillspace:true, sort:"string", hidden: true}, {id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')}, {id: 'print', header: 'I', adjust: 'data', template: get_icon('print')}, - {id: 'email', header: '', adjust: 'data', template: get_icon('email')} ] @@ -50,6 +49,13 @@ var grid_tickets = { resizeColumn: true, headermenu: true, columns: grid_tickets_cols, + scheme:{ + $change:function(item){ + if (item.estatus == 'Cancelado'){ + item.$css = 'cancel' + } + } + }, on:{ 'data->onStoreUpdated':function(){ this.data.each(function(obj, i){