Generar ticket
This commit is contained in:
parent
ccdfacb476
commit
9b4d0bffd7
|
@ -269,6 +269,22 @@ class AppPreInvoices(object):
|
||||||
resp.status = falcon.HTTP_204
|
resp.status = falcon.HTTP_204
|
||||||
|
|
||||||
|
|
||||||
|
class AppTickets(object):
|
||||||
|
|
||||||
|
def __init__(self, db):
|
||||||
|
self._db = db
|
||||||
|
|
||||||
|
def on_get(self, req, resp):
|
||||||
|
values = req.params
|
||||||
|
req.context['result'] = self._db.get_tickets(values)
|
||||||
|
resp.status = falcon.HTTP_200
|
||||||
|
|
||||||
|
def on_post(self, req, resp):
|
||||||
|
values = req.params
|
||||||
|
req.context['result'] = self._db.tickets(values)
|
||||||
|
resp.status = falcon.HTTP_200
|
||||||
|
|
||||||
|
|
||||||
class AppEmisor(object):
|
class AppEmisor(object):
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, db):
|
||||||
|
|
|
@ -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
|
AppMovimientosBanco, AppTickets
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ api.add_route('/partners', AppPartners(db))
|
||||||
api.add_route('/products', AppProducts(db))
|
api.add_route('/products', AppProducts(db))
|
||||||
api.add_route('/invoices', AppInvoices(db))
|
api.add_route('/invoices', AppInvoices(db))
|
||||||
api.add_route('/preinvoices', AppPreInvoices(db))
|
api.add_route('/preinvoices', AppPreInvoices(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))
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,9 @@ class StorageEngine(object):
|
||||||
def _get_product(self, values):
|
def _get_product(self, values):
|
||||||
return main.Productos.get_by(values)
|
return main.Productos.get_by(values)
|
||||||
|
|
||||||
|
def _get_productokey(self, values):
|
||||||
|
return main.Productos.get_by_key(values)
|
||||||
|
|
||||||
def get_partners(self, values):
|
def get_partners(self, values):
|
||||||
return main.Socios.get_(values)
|
return main.Socios.get_(values)
|
||||||
|
|
||||||
|
@ -251,6 +254,11 @@ 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 tickets(self, values):
|
||||||
|
opt = values.pop('opt')
|
||||||
|
if opt == 'add':
|
||||||
|
return main.Tickets.add(values)
|
||||||
|
|
||||||
def get_invoices(self, values):
|
def get_invoices(self, values):
|
||||||
return main.Facturas.get_(values)
|
return main.Facturas.get_(values)
|
||||||
|
|
||||||
|
|
|
@ -1977,6 +1977,34 @@ class Productos(BaseModel):
|
||||||
value += 1
|
value += 1
|
||||||
return {'value': value}
|
return {'value': value}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_by_key(cls, values):
|
||||||
|
clave = values.get('key', '')
|
||||||
|
row = (Productos
|
||||||
|
.select(
|
||||||
|
Productos.id,
|
||||||
|
Productos.clave,
|
||||||
|
Productos.clave_sat,
|
||||||
|
Productos.descripcion,
|
||||||
|
SATUnidades.name.alias('unidad'),
|
||||||
|
Productos.valor_unitario,
|
||||||
|
Productos.descuento)
|
||||||
|
.join(SATUnidades).switch(Productos)
|
||||||
|
.where((Productos.clave==clave) | (Productos.codigo_barras==clave))
|
||||||
|
.dicts()
|
||||||
|
)
|
||||||
|
if len(row):
|
||||||
|
id = row[0]['id']
|
||||||
|
model_pt = Productos.impuestos.get_through_model()
|
||||||
|
taxes = tuple(model_pt
|
||||||
|
.select(
|
||||||
|
model_pt.productos_id.alias('product'),
|
||||||
|
model_pt.satimpuestos_id.alias('tax'))
|
||||||
|
.where(model_pt.productos_id==id).dicts())
|
||||||
|
return {'ok': True, 'row': row[0], 'taxes': taxes}
|
||||||
|
|
||||||
|
return {'ok': False}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by(cls, values):
|
def get_by(cls, values):
|
||||||
clave = values.get('id', '')
|
clave = values.get('id', '')
|
||||||
|
@ -3838,6 +3866,112 @@ class Tickets(BaseModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
order_by = ('fecha',)
|
order_by = ('fecha',)
|
||||||
|
|
||||||
|
def _get_folio(self, serie):
|
||||||
|
inicio = (Tickets
|
||||||
|
.select(fn.Max(Tickets.folio).alias('mf'))
|
||||||
|
.where(Tickets.serie==serie)
|
||||||
|
.order_by(SQL('mf'))
|
||||||
|
.scalar())
|
||||||
|
|
||||||
|
if inicio is None:
|
||||||
|
inicio = 1
|
||||||
|
else:
|
||||||
|
inicio += 1
|
||||||
|
|
||||||
|
return inicio
|
||||||
|
|
||||||
|
def _calcular_totales(self, ticket, productos):
|
||||||
|
subtotal = 0
|
||||||
|
descuento_cfdi = 0
|
||||||
|
totals_tax = {}
|
||||||
|
total_trasladados = None
|
||||||
|
|
||||||
|
for producto in productos:
|
||||||
|
id_producto = producto.pop('id')
|
||||||
|
p = Productos.get(Productos.id==id_producto)
|
||||||
|
producto['descripcion'] = p.descripcion
|
||||||
|
producto['ticket'] = ticket.id
|
||||||
|
producto['producto'] = id_producto
|
||||||
|
|
||||||
|
cantidad = float(producto['cantidad'])
|
||||||
|
valor_unitario = float(p.valor_unitario)
|
||||||
|
descuento = float(producto['descuento'])
|
||||||
|
precio_final = valor_unitario - descuento
|
||||||
|
importe = round(cantidad * precio_final, DECIMALES)
|
||||||
|
|
||||||
|
producto['cantidad'] = cantidad
|
||||||
|
producto['valor_unitario'] = valor_unitario
|
||||||
|
producto['descuento'] = descuento
|
||||||
|
producto['precio_final'] = precio_final
|
||||||
|
producto['importe'] = importe
|
||||||
|
|
||||||
|
descuento_cfdi += descuento
|
||||||
|
subtotal += importe
|
||||||
|
|
||||||
|
TicketsDetalle.create(**producto)
|
||||||
|
|
||||||
|
base = producto['importe']
|
||||||
|
for tax in p.impuestos:
|
||||||
|
impuesto_producto = round(float(tax.tasa) * base, DECIMALES)
|
||||||
|
if tax.tipo == 'T' and tax.key != '000':
|
||||||
|
total_trasladados = (total_trasladados or 0) + impuesto_producto
|
||||||
|
|
||||||
|
if tax.id in totals_tax:
|
||||||
|
totals_tax[tax.id].base += base
|
||||||
|
totals_tax[tax.id].importe += impuesto_producto
|
||||||
|
else:
|
||||||
|
tax.base = base
|
||||||
|
tax.importe = impuesto_producto
|
||||||
|
totals_tax[tax.id] = tax
|
||||||
|
|
||||||
|
|
||||||
|
for tax in totals_tax.values():
|
||||||
|
if tax.tipo == 'E':
|
||||||
|
continue
|
||||||
|
|
||||||
|
ticket_tax = {
|
||||||
|
'ticket': ticket.id,
|
||||||
|
'impuesto': tax.id,
|
||||||
|
'base': tax.base,
|
||||||
|
'importe': tax.importe,
|
||||||
|
}
|
||||||
|
TicketsImpuestos.create(**ticket_tax)
|
||||||
|
|
||||||
|
total = subtotal + (total_trasladados or 0)
|
||||||
|
data = {
|
||||||
|
'subtotal': subtotal + descuento,
|
||||||
|
'descuento': descuento_cfdi,
|
||||||
|
'total': total,
|
||||||
|
'total_trasladados': total_trasladados,
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add(cls, values):
|
||||||
|
productos = util.loads(values.pop('productos'))
|
||||||
|
|
||||||
|
values['serie'] = 'T'
|
||||||
|
values['folio'] = cls._get_folio(cls, values['serie'])
|
||||||
|
|
||||||
|
with database_proxy.atomic() as txn:
|
||||||
|
obj = Tickets.create(**values)
|
||||||
|
totals = cls._calcular_totales(cls, obj, productos)
|
||||||
|
obj.subtotal = totals['subtotal']
|
||||||
|
obj.descuento = totals['descuento']
|
||||||
|
obj.total_trasladados = totals['total_trasladados']
|
||||||
|
obj.total = totals['total']
|
||||||
|
obj.save()
|
||||||
|
|
||||||
|
row = {
|
||||||
|
'id': obj.id,
|
||||||
|
'folio': obj.folio,
|
||||||
|
'fecha': obj.fecha,
|
||||||
|
'estatus': obj.estatus,
|
||||||
|
'total': obj.total,
|
||||||
|
}
|
||||||
|
data = {'ok': True, 'row': row}
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
class TicketsDetalle(BaseModel):
|
class TicketsDetalle(BaseModel):
|
||||||
ticket = ForeignKeyField(Tickets)
|
ticket = ForeignKeyField(Tickets)
|
||||||
|
|
|
@ -24,6 +24,23 @@
|
||||||
font-size: 125%;
|
font-size: 125%;
|
||||||
color: DarkRed;
|
color: DarkRed;
|
||||||
}
|
}
|
||||||
|
.right_footer2 {
|
||||||
|
text-align: right;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 150%;
|
||||||
|
color: DarkRed;
|
||||||
|
}
|
||||||
|
.right_footer3 {
|
||||||
|
text-align: right;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 120%;
|
||||||
|
color: DarkBlue;
|
||||||
|
}
|
||||||
|
.footer3 {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 120%;
|
||||||
|
color: DarkBlue;
|
||||||
|
}
|
||||||
|
|
||||||
.lbl_partner {
|
.lbl_partner {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
|
@ -41,14 +41,6 @@ function get_series(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function get_forma_pago(){
|
|
||||||
webix.ajax().get('/values/formapago', {key: true}, function(text, data){
|
|
||||||
var values = data.json()
|
|
||||||
$$('lst_forma_pago').getList().parse(values)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function get_monedas(){
|
function get_monedas(){
|
||||||
webix.ajax().get('/values/monedas', function(text, data){
|
webix.ajax().get('/values/monedas', function(text, data){
|
||||||
var values = data.json()
|
var values = data.json()
|
||||||
|
@ -105,7 +97,7 @@ function default_config(){
|
||||||
table_taxes.insert(values)
|
table_taxes.insert(values)
|
||||||
})
|
})
|
||||||
get_series()
|
get_series()
|
||||||
get_forma_pago()
|
get_forma_pago('lst_forma_pago')
|
||||||
get_monedas()
|
get_monedas()
|
||||||
get_uso_cfdi()
|
get_uso_cfdi()
|
||||||
get_regimen_fiscal()
|
get_regimen_fiscal()
|
||||||
|
|
|
@ -19,8 +19,6 @@ function configuracion_inicial(){
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,20 +7,260 @@ var tickets_controllers = {
|
||||||
$$('cmd_nuevo_ticket').attachEvent('onItemClick', cmd_nuevo_ticket_click)
|
$$('cmd_nuevo_ticket').attachEvent('onItemClick', cmd_nuevo_ticket_click)
|
||||||
$$('cmd_generar_ticket').attachEvent('onItemClick', cmd_generar_ticket_click)
|
$$('cmd_generar_ticket').attachEvent('onItemClick', cmd_generar_ticket_click)
|
||||||
$$('cmd_cerrar_ticket').attachEvent('onItemClick', cmd_cerrar_ticket_click)
|
$$('cmd_cerrar_ticket').attachEvent('onItemClick', cmd_cerrar_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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function configuracion_inicial_ticket(){
|
||||||
|
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')
|
||||||
|
table_pt.clear()
|
||||||
|
table_totals.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function cmd_nuevo_ticket_click(){
|
function cmd_nuevo_ticket_click(){
|
||||||
|
configuracion_inicial_ticket()
|
||||||
$$('multi_tickets').setValue('tickets_new')
|
$$('multi_tickets').setValue('tickets_new')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function validar_ticket(){
|
||||||
|
var grid = $$('grid_tdetails')
|
||||||
|
|
||||||
|
if(!grid.count()){
|
||||||
|
webix.UIManager.setFocus('tsearch_product_key')
|
||||||
|
msg = 'Agrega al menos un producto'
|
||||||
|
msg_error(msg)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function guardar_ticket(values){
|
||||||
|
var grid = $$('grid_tdetails')
|
||||||
|
//~ showvar(values)
|
||||||
|
|
||||||
|
var rows = grid.data.getRange()
|
||||||
|
for (i = 0; i < rows.length; i++) {
|
||||||
|
delete rows[i]['delete']
|
||||||
|
delete rows[i]['clave']
|
||||||
|
delete rows[i]['clave_sat']
|
||||||
|
delete rows[i]['unidad']
|
||||||
|
delete rows[i]['importe']
|
||||||
|
rows[i]['valor_unitario'] = parseFloat(rows[i]['valor_unitario'])
|
||||||
|
rows[i]['descuento'] = parseFloat(rows[i]['descuento'])
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = new Object()
|
||||||
|
data['opt'] = 'add'
|
||||||
|
data['productos'] = rows
|
||||||
|
data['forma_pago'] = values.forma_pago
|
||||||
|
|
||||||
|
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){
|
||||||
|
msg_ok('Ticket generado correctamente')
|
||||||
|
$$('form_new_ticket').setValues({})
|
||||||
|
$$('multi_tickets').setValue('tickets_home')
|
||||||
|
}else{
|
||||||
|
msg_error(values.msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function cmd_generar_ticket_click(){
|
function cmd_generar_ticket_click(){
|
||||||
showvar('ok')
|
var form = this.getFormView();
|
||||||
|
|
||||||
|
if(!form.validate()) {
|
||||||
|
msg_error('Valores inválidos')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var values = form.getValues()
|
||||||
|
if(!validar_ticket()){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = '¿Todos los datos son correctos?<BR><BR>'
|
||||||
|
msg += '¿Estás seguro de generar este Ticket?'
|
||||||
|
|
||||||
|
webix.confirm({
|
||||||
|
title: 'Generar Ticket',
|
||||||
|
ok: 'Si',
|
||||||
|
cancel: 'No',
|
||||||
|
type: 'confirm-error',
|
||||||
|
text: msg,
|
||||||
|
callback:function(result){
|
||||||
|
if(result){
|
||||||
|
guardar_ticket(values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function cmd_cerrar_ticket_click(){
|
function cmd_cerrar_ticket_click(){
|
||||||
$$('multi_tickets').setValue('tickets_home')
|
$$('multi_tickets').setValue('tickets_home')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calcular_precio_con_impuestos(precio, taxes){
|
||||||
|
var precio_final = precio
|
||||||
|
|
||||||
|
for(var tax of taxes){
|
||||||
|
impuesto = table_taxes.findOne({'id': tax.tax})
|
||||||
|
if(impuesto.tipo == 'E'){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var base = precio
|
||||||
|
if(impuesto.tipo == 'R'){
|
||||||
|
base = (precio * -1).round(DECIMALES)
|
||||||
|
}
|
||||||
|
precio_final += (impuesto.tasa * base).round(DECIMALES)
|
||||||
|
}
|
||||||
|
|
||||||
|
return precio_final
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function agregar_producto(values){
|
||||||
|
var taxes = values.taxes
|
||||||
|
var producto = values.row
|
||||||
|
var form = $$('form_new_ticket')
|
||||||
|
var grid = $$('grid_tdetails')
|
||||||
|
var row = grid.getItem(producto.id)
|
||||||
|
var precio_final = 0.0
|
||||||
|
|
||||||
|
if(row == undefined){
|
||||||
|
producto['cantidad'] = 1
|
||||||
|
producto['valor_unitario'] = calcular_precio_con_impuestos(
|
||||||
|
parseFloat(producto['valor_unitario']), taxes)
|
||||||
|
producto['importe'] = producto['valor_unitario']
|
||||||
|
grid.add(producto)
|
||||||
|
}else{
|
||||||
|
producto['cantidad'] = parseFloat(row.cantidad) + 1
|
||||||
|
producto['descuento'] = parseFloat(row.descuento)
|
||||||
|
producto['valor_unitario'] = parseFloat(row.valor_unitario)
|
||||||
|
precio_final = producto['valor_unitario'] - producto['descuento']
|
||||||
|
producto['importe'] = (precio_final * producto['cantidad']).round(DECIMALES)
|
||||||
|
grid.updateItem(row.id, producto)
|
||||||
|
}
|
||||||
|
form.setValues({tsearch_product_key: '', tsearch_product_name: ''}, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function buscar_producto_key(key){
|
||||||
|
webix.ajax().get('/values/productokey', {'key': key}, {
|
||||||
|
error: function(text, data, xhr) {
|
||||||
|
msg_error('Error al consultar')
|
||||||
|
},
|
||||||
|
success: function(text, data, xhr){
|
||||||
|
var values = data.json()
|
||||||
|
if (values.ok){
|
||||||
|
agregar_producto(values)
|
||||||
|
} else {
|
||||||
|
msg = 'No se encontró la clave<BR><BR>' + key
|
||||||
|
msg_error(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function tsearch_product_key_press(code, e){
|
||||||
|
var value = this.getValue()
|
||||||
|
if(code == 13 && value.trim().length > 0){
|
||||||
|
buscar_producto_key(value.trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function grid_ticket_details_click(id, e, node){
|
||||||
|
if(id.column != 'delete'){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var grid = $$('grid_tdetails')
|
||||||
|
grid.remove(id.row)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function grid_tickets_details_before_edit_stop(state, editor){
|
||||||
|
var grid = $$('grid_tdetails')
|
||||||
|
var row = grid.getItem(editor.row)
|
||||||
|
|
||||||
|
if(editor.column == 'cantidad'){
|
||||||
|
var cantidad = parseFloat(state.value)
|
||||||
|
if(isNaN(cantidad)){
|
||||||
|
msg = 'La cantidad debe ser un número'
|
||||||
|
msg_error(msg)
|
||||||
|
grid.blockEvent()
|
||||||
|
state.value = state.old
|
||||||
|
grid.editCancel()
|
||||||
|
grid.unblockEvent()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
var valor_unitario = parseFloat(row['valor_unitario'])
|
||||||
|
var descuento = parseFloat(row['descuento'])
|
||||||
|
}
|
||||||
|
|
||||||
|
if(editor.column == 'valor_unitario'){
|
||||||
|
var valor_unitario = parseFloat(state.value)
|
||||||
|
if(isNaN(valor_unitario)){
|
||||||
|
msg = 'El valor unitario debe ser un número'
|
||||||
|
msg_error(msg)
|
||||||
|
grid.blockEvent()
|
||||||
|
state.value = state.old
|
||||||
|
grid.editCancel()
|
||||||
|
grid.unblockEvent()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
var cantidad = parseFloat(row['cantidad'])
|
||||||
|
var descuento = parseFloat(row['descuento'])
|
||||||
|
}
|
||||||
|
|
||||||
|
if(editor.column == 'descuento'){
|
||||||
|
var descuento = parseFloat(state.value)
|
||||||
|
if(isNaN(descuento)){
|
||||||
|
msg = 'El descuento debe ser un número'
|
||||||
|
msg_error(msg)
|
||||||
|
grid.blockEvent()
|
||||||
|
state.value = state.old
|
||||||
|
grid.editCancel()
|
||||||
|
grid.unblockEvent()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
var cantidad = parseFloat(row['cantidad'])
|
||||||
|
var valor_unitario = parseFloat(row['valor_unitario'])
|
||||||
|
}
|
||||||
|
|
||||||
|
var precio_final = valor_unitario - descuento
|
||||||
|
row['importe'] = (cantidad * precio_final).round(DECIMALES)
|
||||||
|
|
||||||
|
grid.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function gt_productos_found_click(obj){
|
||||||
|
buscar_producto_key(obj.clave)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,11 @@ function showvar(values){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function showtype(values){
|
||||||
|
webix.message(typeof(values))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function show(nombre, value){
|
function show(nombre, value){
|
||||||
if(value == '0'){
|
if(value == '0'){
|
||||||
value = false
|
value = false
|
||||||
|
@ -96,7 +101,7 @@ String.prototype.to_float = function(){
|
||||||
|
|
||||||
|
|
||||||
function get_float(value){
|
function get_float(value){
|
||||||
return parseFloat(value.replace('$', '').replace(',', '').trim()).round(2)
|
return parseFloat(value.replace('$', '').replace(',', '').trim()).round(DECIMALES)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,12 +129,17 @@ webix.protoUI({
|
||||||
}, webix.ui.text)
|
}, webix.ui.text)
|
||||||
|
|
||||||
|
|
||||||
webix.ui.datafilter.rowCount = webix.extend({
|
//~ webix.ui.datafilter.rowCount = webix.extend({
|
||||||
refresh:function(master, node, value){
|
//~ refresh:function(master, node, value){
|
||||||
node.firstChild.innerHTML = master.count();
|
//~ node.firstChild.innerHTML = master.count();
|
||||||
}
|
//~ }
|
||||||
}, webix.ui.datafilter.summColumn)
|
//~ }, webix.ui.datafilter.summColumn)
|
||||||
|
|
||||||
|
webix.ui.datafilter.countRows = webix.extend({
|
||||||
|
refresh:function(master, node, value){
|
||||||
|
node.firstChild.innerHTML = master.count();
|
||||||
|
}
|
||||||
|
}, webix.ui.datafilter.summColumn);
|
||||||
|
|
||||||
function validate_rfc(value){
|
function validate_rfc(value){
|
||||||
rfc = value.trim().toUpperCase();
|
rfc = value.trim().toUpperCase();
|
||||||
|
@ -291,3 +301,11 @@ webix.DataDriver.plainjs = webix.extend({
|
||||||
return this.hash2tree(hash, 0);
|
return this.hash2tree(hash, 0);
|
||||||
}
|
}
|
||||||
}, webix.DataDriver.json)
|
}, webix.DataDriver.json)
|
||||||
|
|
||||||
|
|
||||||
|
function get_forma_pago(control){
|
||||||
|
webix.ajax().get('/values/formapago', {key: true}, function(text, data){
|
||||||
|
var values = data.json()
|
||||||
|
$$(control).getList().parse(values)
|
||||||
|
})
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
var grid_cfdi_cliente_cols = [
|
var grid_cfdi_cliente_cols = [
|
||||||
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
||||||
footer: {content: 'rowCount', colspan: 3, css: 'right'}},
|
footer: {content: 'countRows', colspan: 3, css: 'right'}},
|
||||||
{id: "id", header:"ID", hidden:true},
|
{id: "id", header:"ID", hidden:true},
|
||||||
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "header",
|
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "header",
|
||||||
sort:"string"},
|
sort:"string"},
|
||||||
|
@ -182,7 +182,7 @@ var toolbar_invoices_filter = [
|
||||||
|
|
||||||
var grid_invoices_cols = [
|
var grid_invoices_cols = [
|
||||||
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
||||||
footer: {content: 'rowCount', colspan: 3, css: 'right'}},
|
footer: {content: 'countRows', colspan: 3, css: 'right'}},
|
||||||
{id: "id", header:"ID", hidden:true},
|
{id: "id", header:"ID", hidden:true},
|
||||||
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data",
|
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data",
|
||||||
sort:"string"},
|
sort:"string"},
|
||||||
|
@ -306,6 +306,7 @@ var suggest_partners = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var suggest_products = {
|
var suggest_products = {
|
||||||
view: 'gridsuggest',
|
view: 'gridsuggest',
|
||||||
id: 'grid_products_found',
|
id: 'grid_products_found',
|
||||||
|
|
|
@ -13,7 +13,7 @@ var toolbar_products = [
|
||||||
var grid_products_cols = [
|
var grid_products_cols = [
|
||||||
{ id: "id", header: "ID", width: 75, hidden: true},
|
{ id: "id", header: "ID", width: 75, hidden: true},
|
||||||
{ id: "clave", header: ["Clave", {content: "textFilter"}], width: 100,
|
{ id: "clave", header: ["Clave", {content: "textFilter"}], width: 100,
|
||||||
sort: 'string', footer: {content: 'rowCount', css: 'right'}},
|
sort: 'string', footer: {content: 'countRows', css: 'right'}},
|
||||||
{ id: "descripcion", header: ["Descripción", {content: "textFilter"}],
|
{ id: "descripcion", header: ["Descripción", {content: "textFilter"}],
|
||||||
fillspace:true, sort: 'string', footer: 'Productos y Servicios'},
|
fillspace:true, sort: 'string', footer: 'Productos y Servicios'},
|
||||||
{ id: "unidad", header: ["Unidad", {content: "selectFilter"}], width: 150,
|
{ id: "unidad", header: ["Unidad", {content: "selectFilter"}], width: 150,
|
||||||
|
|
|
@ -21,7 +21,7 @@ var toolbar_tickets_filter = [
|
||||||
|
|
||||||
var grid_tickets_cols = [
|
var grid_tickets_cols = [
|
||||||
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
{id: 'index', header: '#', adjust: 'data', css: 'right',
|
||||||
footer: {content: 'rowCount', colspan: 3, css: 'right'}},
|
footer: {content: 'countRows', colspan: 3, css: 'right'}},
|
||||||
{id: "id", header:"ID", hidden:true},
|
{id: "id", header:"ID", hidden:true},
|
||||||
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data",
|
{id: "serie", header: ["Serie", {content: "selectFilter"}], adjust: "data",
|
||||||
sort:"string"},
|
sort:"string"},
|
||||||
|
@ -34,7 +34,7 @@ var grid_tickets_cols = [
|
||||||
{id: 'total', header: ['Total', {content: 'numberFilter'}], width: 150,
|
{id: 'total', header: ['Total', {content: 'numberFilter'}], width: 150,
|
||||||
sort: 'int', format: webix.i18n.priceFormat, css: 'right'},
|
sort: 'int', format: webix.i18n.priceFormat, css: 'right'},
|
||||||
{id: "cliente", header: ["Razón Social", {content: "selectFilter"}],
|
{id: "cliente", header: ["Razón Social", {content: "selectFilter"}],
|
||||||
fillspace:true, sort:"string"},
|
fillspace:true, sort:"string", hidden: true},
|
||||||
{id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')},
|
{id: 'pdf', header: 'PDF', adjust: 'data', template: get_icon('pdf')},
|
||||||
{id: 'print', header: 'I', adjust: 'data', template: get_icon('print')},
|
{id: 'print', header: 'I', adjust: 'data', template: get_icon('print')},
|
||||||
{id: 'email', header: '', adjust: 'data', template: get_icon('email')}
|
{id: 'email', header: '', adjust: 'data', template: get_icon('email')}
|
||||||
|
@ -67,37 +67,66 @@ var rows_tickets_home = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
var ticket_suggest_products = {
|
||||||
|
view: 'gridsuggest',
|
||||||
|
id: 'gt_productos_found',
|
||||||
|
name: 'gt_productos_found',
|
||||||
|
body: {
|
||||||
|
autoConfig: false,
|
||||||
|
header: true,
|
||||||
|
columns: [
|
||||||
|
{id: 'id', hidden: true},
|
||||||
|
{id: 'clave', header: 'Clave', adjust: 'data'},
|
||||||
|
{id: 'descripcion', header: 'Descripción', adjust: 'data'},
|
||||||
|
{id: 'unidad', header: 'Unidad', adjust: 'data'},
|
||||||
|
{id: 'valor_unitario', header: 'Valor Unitario', adjust: 'data',
|
||||||
|
format: webix.i18n.priceFormat}
|
||||||
|
],
|
||||||
|
dataFeed:function(text){
|
||||||
|
if (text.length > 2){
|
||||||
|
this.load('/values/product?name=' + text)
|
||||||
|
}else{
|
||||||
|
this.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var tbody_buscar_producto = {rows: [
|
var tbody_buscar_producto = {rows: [
|
||||||
{cols: [
|
{cols: [
|
||||||
{view: 'search', id: 'tsearch_product_key', name: 'tsearch_product_key',
|
{view: 'search', id: 'tsearch_product_key', name: 'tsearch_product_key',
|
||||||
label: 'por Clave', labelPosition:'top', maxWidth: 250,
|
label: 'por Clave', labelPosition:'top', maxWidth: 250,
|
||||||
placeholder: 'Presiona ENTER para buscar'},
|
placeholder: 'Presiona ENTER para buscar'},
|
||||||
{view: 'search', id: 'tsearch_product_name', name: 'search_product_name',
|
{view: 'search', id: 'tsearch_product_name', name: 'tsearch_product_name',
|
||||||
label: 'por Descripción', labelPosition:'top', suggest: [],
|
label: 'por Descripción', labelPosition:'top',
|
||||||
placeholder: 'Captura al menos tres letras'},
|
suggest: ticket_suggest_products, placeholder: 'Captura al menos tres letras'},
|
||||||
]},
|
]},
|
||||||
]}
|
]}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var grid_tdetails_cols = [
|
var grid_tdetails_cols = [
|
||||||
{id: "id", header:"ID", hidden: true},
|
{id: "id", header:"ID", hidden: true},
|
||||||
{id: 'delete', header: '', width: 30, css: 'delete'},
|
{id: 'delete', header: '', width: 30, css: 'delete'},
|
||||||
{id: "clave", header:{text: 'Clave', css: 'center'}, width: 100},
|
{id: "clave", header:{text: 'Clave', css: 'center'}, width: 100,
|
||||||
|
footer: {text: 'Artículos', css: 'right_footer3'}},
|
||||||
{id: "clave_sat", hidden: true},
|
{id: "clave_sat", hidden: true},
|
||||||
{id: "descripcion", header:{text: 'Descripción', css: 'center'},
|
{id: "descripcion", header:{text: 'Descripción', css: 'center'},
|
||||||
fillspace: true, editor: 'text'},
|
fillspace: true, footer: {content: 'countRows', css: 'footer3'}},
|
||||||
{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',
|
||||||
|
footer: {content: 'summColumn', css: 'right_footer3'}},
|
||||||
{id: "valor_unitario", header:{text: 'Valor Unitario', css: 'center'},
|
{id: "valor_unitario", header:{text: 'Valor Unitario', css: 'center'},
|
||||||
width: 100, format: webix.i18n.priceFormat, css: 'right', editor: 'text'},
|
width: 100, format: webix.i18n.priceFormat, css: 'right',
|
||||||
{id: 'descuento', header:{text: 'Descuento', css: 'center'}, hidden: true,
|
footer: {text: 'Total ', css: 'right_footer2'}},
|
||||||
|
{id: 'descuento', header: {text: 'Descuento', css: 'center'}, hidden: true,
|
||||||
width: 80, format: webix.i18n.priceFormat, css: 'right', editor: 'text'},
|
width: 80, format: webix.i18n.priceFormat, css: 'right', editor: 'text'},
|
||||||
{id: 'precio_final', hidden: true, header: 'precio_final', width: 80,
|
{id: 'precio_final', hidden: true, header: 'precio_final', width: 80,
|
||||||
format: webix.i18n.priceFormat, css: 'right'},
|
format: webix.i18n.priceFormat, css: 'right'},
|
||||||
{id: "importe", header:{text: 'Importe', css: 'center'}, width: 150,
|
{id: "importe", header:{text: 'Importe', css: 'center'}, width: 150,
|
||||||
format: webix.i18n.priceFormat, css: 'right'},
|
format: webix.i18n.priceFormat, css: 'right',
|
||||||
|
footer: {content: 'summColumn', css: 'right_footer2'}},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,11 +137,26 @@ var grid_tdetails = {
|
||||||
adjust: true,
|
adjust: true,
|
||||||
autoheight: true,
|
autoheight: true,
|
||||||
editable: true,
|
editable: true,
|
||||||
|
footer: true,
|
||||||
columns: grid_tdetails_cols,
|
columns: grid_tdetails_cols,
|
||||||
|
on:{
|
||||||
|
'data->onStoreUpdated':function(){
|
||||||
|
this.data.each(function(obj, i){
|
||||||
|
obj.delete = '-'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
data: [],
|
data: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var body_ticket_informacion = {rows: [
|
||||||
|
{view: 'richselect', id: 'lst_ticket_forma_pago', name: 'forma_pago',
|
||||||
|
label: 'Forma de Pago', labelPosition: 'top', required: true,
|
||||||
|
options: []},
|
||||||
|
],}
|
||||||
|
|
||||||
|
|
||||||
var controls_generate_ticket = [
|
var controls_generate_ticket = [
|
||||||
{minHeight: 10, maxHeight: 10},
|
{minHeight: 10, maxHeight: 10},
|
||||||
{cols: [{rows: [
|
{cols: [{rows: [
|
||||||
|
@ -120,7 +164,7 @@ var controls_generate_ticket = [
|
||||||
]},
|
]},
|
||||||
{maxWidth: 10},
|
{maxWidth: 10},
|
||||||
{maxWidth: 300, rows: [
|
{maxWidth: 300, rows: [
|
||||||
{view: 'fieldset', label: 'Información', body: {}},
|
{view: 'fieldset', label: 'Información', body: body_ticket_informacion},
|
||||||
]},
|
]},
|
||||||
]},
|
]},
|
||||||
{view: 'label', label: 'Detalle', height: 30, align: 'left'},
|
{view: 'label', label: 'Detalle', height: 30, align: 'left'},
|
||||||
|
|
Loading…
Reference in New Issue