diff --git a/B4A/B4XMainPage.bas b/B4A/B4XMainPage.bas
index 626e1d0..b637e17 100644
--- a/B4A/B4XMainPage.bas
+++ b/B4A/B4XMainPage.bas
@@ -120,6 +120,7 @@ Sub Class_Globals
' Type TResultado(Tag As String, Success As Boolean, resultado As DBResult, ErrorMessage As String)
Private Label4 As Label
Private clicked As Int = 0
+ Dim linker As C_deviceLinker
End Sub
Public Sub Initialize
@@ -395,9 +396,10 @@ End Sub
Sub B4XPage_Appear
Log(">>>>>> APPEAR - INICIAMOS MAIN PAGE <<<<<<<<<")
+ linker.Initialize(Me, "Linker", True)
clicked = 0
If Not(MES1.IsInitialized) Then MES1.Initialize(Me, "MES1")
- Log(DateTime.GetDayOfWeek(DateTime.Now))
+' Log(DateTime.GetDayOfWeek(DateTime.Now))
kh.RD_Init
kh.SetButtonTintList(cb_geocerca, Colors.LightGray, Colors.RGB(43, 154, 211))
kh.SetButtonTintList(cb_cartaPorte, Colors.LightGray, Colors.RGB(43, 154, 211))
@@ -465,7 +467,7 @@ Sub B4XPage_Appear
cmd.Name = "select_fecha"
' cmd.Parameters = Array As Object(Null)
reqManager.ExecuteQuery(cmd , 0, "fecha")
- Log("############### APPEAR PAGE ####################")
+ Log("############### PAGE_APPEAR ####################")
Log(MES1.IsInitialized)
If MES1.IsInitialized Then
LogColor("Permisos de almacenamiento: " & MES1.HasPermission, Colors.Magenta)
@@ -1033,15 +1035,18 @@ End Sub
Private Sub ImageView1_LongClick
' Log("###### TRAEMOS FECHA #######")
' GetFecha
-
- Log("traeConexion")
- Private reqManagerX As DBRequestManager
- reqManagerX.Initialize(Me, "http://keymon.net:9010/DB2")
- Private cmdX As DBCommand
- cmdX.Initialize
- cmdX.Name = "traeConexion"
- cmdX.Parameters = Array As Object()
- reqManagerX.ExecuteQuery(cmdX, 0, "traeConexion")
+
+' Log("traeConexion")
+' Private reqManagerX As DBRequestManager
+' reqManagerX.Initialize(Me, "http://keymon.net:9010/DB2")
+' Private cmdX As DBCommand
+' cmdX.Initialize
+' cmdX.Name = "traeConexion"
+' cmdX.Parameters = Array As Object()
+' reqManagerX.ExecuteQuery(cmdX, 0, "traeConexion")
+ If Subs.traeAlmacen <> "" Then
+ linker.VerifyAndLinkDevice(Subs.traeAlmacen, Subs.traeRuta)
+ End If
End Sub
Sub ponUsuario
@@ -1060,3 +1065,33 @@ Private Sub Label4_Click
ponUsuario
End If
End Sub
+
+Sub Linker_Response(Status As String) ' << AÑADE ESTE SUB [New Query]
+ If Starter.Logger Then LogColor($"Respuesta de DeviceLinker para la verificación del dispositivo: ${Status}"$, Colors.Magenta) '
+ Select Status
+ Case "UUID_ERROR"
+ ToastMessageShow("Error interno al obtener el identificador único del dispositivo.", True)
+ Case "HTTP_ERROR"
+ LogColor("Error HTTP al verificar el dispositivo: " & linker.lastJobDoneError, Colors.Red)
+ ToastMessageShow("Error de conexión al servidor durante la verificación del dispositivo.", True)
+ Case "SERVER_LOGIC_ERROR"
+ ToastMessageShow("El servidor no proporcionó un estado de verificación válido. Contacte a soporte.", True)
+ Case "OK"
+ If Starter.Logger Then Log("Dispositivo ligado y verificado exitosamente.")
+ ToastMessageShow("Dispositivo verificado y ligado correctamente.", False)
+ ' Aquí puedes añadir lógica adicional si la verificación es exitosa, por ejemplo, habilitar ciertos botones o continuar con el flujo normal.
+ Case "NO_REGISTRADO"
+ If Starter.Logger Then Log("Dispositivo NO registrado.")
+ ToastMessageShow("Dispositivo NO registrado.", False)
+ Case "REGISTRO_NUEVO"
+ If Starter.Logger Then Log("¡¡Registro nuevo!!")
+ ToastMessageShow("¡¡Registro nuevo!!", False)
+ Case "ALREADY_REGISTERED"
+ If Starter.Logger Then Log("¡¡El dispositivo ya esta registrado con otra ruta!!")
+ ToastMessageShow("¡¡El dispositivo ya esta registrado con otra ruta!!", True)
+ Case Else ' Otros estados que tu servidor pueda devolver (ej. "UNAUTHORIZED", "PENDING_APPROVAL")
+ If Starter.Logger Then Log($"Estado de verificación del dispositivo: ${Status}"$)
+ ToastMessageShow($"Verificación del dispositivo: ${Status}"$, True)
+ ' Puedes decidir si bloquear la funcionalidad o mostrar un mensaje específico según el estado.
+ End Select
+End Sub
\ No newline at end of file
diff --git a/B4A/C_Cliente.bas b/B4A/C_Cliente.bas
index c559ef3..f9dcc00 100644
--- a/B4A/C_Cliente.bas
+++ b/B4A/C_Cliente.bas
@@ -405,6 +405,7 @@ End Sub
Sub B4XPage_Appear
indicePregunta = 0
b_noVenta.Enabled = False
+ Log("NoVenta False")
' Log(kh.traeTotalCliente)
If kh.traeTotalCliente = 0 Then b_noVenta.Enabled = True
clienteId = kh.traeCliente
@@ -414,6 +415,7 @@ Sub B4XPage_Appear
' Log($"TOTAL VENTA: ${kh.traeTotalCliente}"$)
B_VENTA.Visible = False
b_noVenta.Visible = False
+ Log("NoVenta False")
If clienteId.StartsWith("N") Then b_noVenta.Visible = False
l_doe.Text = "HAY PEDIDO DOE"
' Log(Starter.rp.Check("android.permission.BLUETOOTH_CONNECT"))
@@ -545,9 +547,13 @@ Sub B4XPage_Appear
End If
If kh.traeTotalCliente < 0.01 And kh.traeTotalClienteDOE < 0.01 Then
- If Not(clienteId.StartsWith("N")) And la_cuenta.Text <> "0" Then b_noVenta.Visible = True 'Ni cliente nuevo, ni abordo.
+ If Not(clienteId.StartsWith("N")) And la_cuenta.Text <> "0" Then
+' b_noVenta.Visible = True 'Ni cliente nuevo, ni abordo. ... Si apagan el GPS, y este esta habilitado, les da tiempo de meter NoVenta aun estando fuera de la geocerca.
+' Log("NoVenta True")
+ End If
Else
b_noVenta.Visible = False
+ Log("NoVenta False")
If la_cuenta.text = 0 Then
CREDITO_DISPONIBLE = 10000000
CREDITO = 0
@@ -681,7 +687,10 @@ Sub B4XPage_Appear
c = Starter.skmt.ExecQuery("select count(*) as conNoVenta FROM NOVENTA WHERE NV_CLIENTE IN (Select CUENTA from cuentaa)")
c.Position = 0
- If c.GetString("conNoVenta") = 1 Then b_noVenta.Visible = False 'Si ya tiene NoVenta, ocultamos el boton.
+ If c.GetString("conNoVenta") = 1 Then
+ b_noVenta.Visible = False 'Si ya tiene NoVenta, ocultamos el boton.
+ Log("NoVenta False")
+ End If
c.Close
Else
RutaBoleta=Starter.rutaV
@@ -899,10 +908,14 @@ Sub GPS_LocationChanged (Location1 As Location)
' If gps_boton_doe = "1" And clienteConPromo = "0" And revisaExistenciasDOE Then b_whats.Visible = True
If Not(clienteDeudor) Then B_VENTA.Visible = True 'Si el cliente no tiene adeudo, habilitamos el boton de venta
- If Not(clienteId.StartsWith("N")) And la_cuenta.Text <> "0" Then b_noVenta.Visible = True 'Ni cliente nuevo, ni abordo.
+ If Not(clienteId.StartsWith("N")) And la_cuenta.Text <> "0" Then
+ b_noVenta.Visible = True 'Ni cliente nuevo, ni abordo.
+ Log("NoVenta False")
+ End If
If Not(p_rechazoDOE.Visible) Then pedido_doe_muestra
Else
b_noVenta.Visible = False
+ Log("NoVenta False")
B_VENTA.Visible = False
b_whats.Visible = False
End If
diff --git a/B4A/C_NuevoCliente.bas b/B4A/C_NuevoCliente.bas
index ce72c42..b8feefc 100644
--- a/B4A/C_NuevoCliente.bas
+++ b/B4A/C_NuevoCliente.bas
@@ -51,6 +51,7 @@ End Sub
'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.
Sub B4XPage_Appear
+ b_guardar.Visible = False
b_guardar.Enabled = False
permitirCtesNuevos = True
b_guardar.Text = "Sin Ubicación ..."
@@ -61,22 +62,24 @@ Sub B4XPage_Appear
c.Position = 0
maxClientesNuevos = c.GetString("CAT_VA_VALOR")
End If
-' Log("MaxClientesNuevos: " & maxClientesNuevos)
+ Log("MaxClientesNuevos: " & maxClientesNuevos)
'Para el almacen 12 (GDL) no hay limite de clientes nuevos.
- If kh.traeAlmacen = 12 Then maxClientesNuevos = 0
+' If kh.traeAlmacen = 12 Then maxClientesNuevos = 0
If maxClientesNuevos <> 0 Then
Private d As Cursor = Starter.skmt.ExecQuery($"select count(CAT_CL_CODIGO) as ctesNuevos from kmt_info where CAT_CL_CODIGO like 'N%'"$)
If d.RowCount > 0 Then
d.Position = 0
-' Log($"Clientes nuevos actuales: ${d.GetString("ctesNuevos")}"$)
+ Log($"Clientes nuevos actuales: ${d.GetString("ctesNuevos")}"$)
If d.GetString("ctesNuevos") >= maxClientesNuevos Then
b_guardar.Enabled = False
permitirCtesNuevos = False
ToastMessageShow("¡Ha alcanzado el LIMITE de usuarios nuevos por día!", True)
End If
End If
+ Else
+ b_guardar.Visible = True
End If
End Sub
@@ -87,6 +90,7 @@ Sub GPS_LocationChanged (Location1 As Location)
b_guardar.Enabled = False
Else
b_guardar.Enabled = True
+ b_guardar.Visible = True
End If
b_guardar.Text = "Guardar"
End Sub
@@ -128,7 +132,7 @@ Sub b_guardar_Click
Starter.skmt.ExecNonQuery2("INSERT INTO CUENTAA VALUES (?)", Array As Object(no_cliente))
Subs.iniciaActividad("cliente")
Else
- ToastMessageShow("No hay clientes para visitar el día de hoy.", true)
+ ToastMessageShow("No hay clientes para visitar el día de hoy.", True)
End If
End If
End Sub
diff --git a/B4A/C_Principal.bas b/B4A/C_Principal.bas
index 43cc9cf..f380748 100644
--- a/B4A/C_Principal.bas
+++ b/B4A/C_Principal.bas
@@ -548,8 +548,13 @@ Sub B4XPage_Appear
NUEVO.Enabled = True
B_PROXIMA.Enabled = True
End If
-' LogColor("REVISAMOS GUID", Colors.red)
-' Subs.generaGUID_EnExterno
+ kh.traeMaxClientesNuevos
+ Private n As Cursor = Starter.skmt.ExecQuery("select count(*) as cuantos from kmt_info where cat_cl_codigo like 'N%'")
+ n.Position = 0
+ Log(n.GetString("cuantos"))
+ If n.GetString("cuantos") >= kh.traeMaxClientesNuevos Then NUEVO.Enabled = False
+ LogColor(">>>>>>>> REVISAMOS GUID <<<<<<<<<", Colors.red)
+ Subs.generaGUID_EnExterno
End Sub
Sub trabajar_Click
@@ -842,6 +847,34 @@ Sub cargar_Click
Log(r.ErrorMessage)
End If
+ 'Autorizacion para crear clientes nuevos
+ cmd.Initialize
+ cmd.Name = "autorizacionClientesNuevos"
+ cmd.Parameters = Array As Object(ALMACEN, e_ruta.text)
+ reqManagerW.ExecuteQuery(Starter.DBReqServer, cmd, Me, "autorizacionClientesNuevos")
+ Wait For autorizacionClientesNuevos_Completed (r0 As TResultado)
+ Log("tag: " & r0.tag & " Success: " & r0.Success)
+ If r0.Success Then
+ Subs.logJobDoneResultados(r0.resultado)
+ Private result As DBResult = r0.resultado
+ cargar.Enabled = True
+' Log("TIEMPO kmt_datos : " & ((DateTime.Now-inicioContador)/1000))
+' S_CC.TEXT = "CARGANDO"
+ Starter.skmt.BeginTransaction
+ For Each records() As Object In result.Rows
+ Dim CNR_AUTORIZADO As String = records(result.Columns.Get("CNR_AUTORIZADO"))
+ Dim CNR_CUANTOS_CN As String = records(result.Columns.Get("CNR_CUANTOS_CN"))
+ Next
+ Starter.skmt.ExecNonQuery2("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = ?", Array As Object ("CN_AUTORIZADO"))
+ Starter.skmt.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("CN_AUTORIZADO", CNR_AUTORIZADO))
+ Starter.skmt.ExecNonQuery2("delete from CAT_VARIABLES where CAT_VA_DESCRIPCION = ?", Array As Object ("CN_CUANTOS"))
+ Starter.skmt.ExecNonQuery2("INSERT INTO CAT_VARIABLES(CAT_VA_DESCRIPCION, CAT_VA_VALOR) VALUES (?,?)", Array As Object ("CN_CUANTOS", CNR_CUANTOS_CN))
+ Starter.skmt.TransactionSuccessful 'Si no se pone TransactionSuccessful no se escribe NADA!!
+ Starter.skmt.EndTransaction
+ Else
+ Log(r0.ErrorMessage)
+ End If
+
cmd.Initialize
cmd.Name = "select_cat_clientes_guna_KELL2"
cmd.Parameters = Array As Object(e_ruta.text, ALMACEN)
@@ -892,7 +925,7 @@ Sub cargar_Click
Starter.skmt.ExecNonQuery2("INSERT INTO kmt_info(CAT_CL_CODIGO,CAT_CL_RUTA,CAT_CL_NOMBRE,CAT_CL_ATIENDE1,CAT_CL_ATIENTE2,CAT_CL_TELEFONO,CAT_CL_EMAIL,CAT_CL_CALLE,CAT_CL_NOEXT,CAT_CL_NOINT,CAT_CL_CALLE1,CAT_CL_CALLE2,CAT_CL_COLONIA,CAT_CL_MUNI,CAT_CL_EDO,CAT_CL_CP,CAT_CL_LONG,CAT_CL_LAT,CAT_CL_BFACTURA,CAT_CL_BCREDITO,CAT_CL_MTOCOMPRA,CAT_CL_NUM_SERIEFISICO,CAT_CL_DIAS_VISITA, gestion, IMPRESION) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,0,0,0,?,0,0) ",Array As Object ("0",e_ruta.TEXT, "VENTA ABORDO","null","null","null","null","null","null","null","null","null","null","null","0","null","null","null","10000000","null"))
Starter.skmt.TransactionSuccessful 'Si no se pone TransactionSuccessful no se escribe NADA!!
Starter.skmt.EndTransaction
- LogColor("##################################################################3", Colors.red)
+' LogColor("##################################################################3", Colors.red)
Listo1 = 1
S_CC.Text = "LISTO"
' ToastMessageShow("Catalogo Clientes Actualizados." , True)
@@ -2086,7 +2119,7 @@ Sub JobDone(Job As HttpJob)
Starter.skmt.ExecNonQuery2("INSERT INTO HIST_TREND_SPENDING_SEMANAL (HIST_TSS_RUTA, HIST_TSS_IDALMACEN, HIST_TSS_TIPO, HIST_TSS_SEMANA1, HIST_TSS_SEMANA1_ACUM, HIST_TSS_SEMANA2, HIST_TSS_SEMANA2_ACUM, HIST_TSS_SEMANA3, HIST_TSS_SEMANA3_ACUM, HIST_TSS_SEMANA4, HIST_TSS_SEMANA4_ACUM, HIST_TSS_SEMANA5, HIST_TSS_SEMANA5_ACUM, HIST_TSS_SEMANA6, HIST_TSS_SEMANA6_ACUM, HIST_TSS_GRUPO) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", Array As Object (HIST_TSS_RUTA, HIST_TSS_IDALMACEN, HIST_TSS_TIPO, HIST_TSS_SEMANA1, HIST_TSS_SEMANA1_ACUM, HIST_TSS_SEMANA2, HIST_TSS_SEMANA2_ACUM, HIST_TSS_SEMANA3, HIST_TSS_SEMANA3_ACUM, HIST_TSS_SEMANA4, HIST_TSS_SEMANA4_ACUM, HIST_TSS_SEMANA5, HIST_TSS_SEMANA5_ACUM, HIST_TSS_SEMANA6, HIST_TSS_SEMANA6_ACUM, HIST_TSS_GRUPO))
Next
LogColor("GUARDAMOS INFO DE TRADE SPENDING", Colors.Blue)
- Subs.logJobDoneResultados(RESULT)
+' Subs.logJobDoneResultados(RESULT)
ts.Initialize(Me, "ts", Starter.skmt)
End If
End If
diff --git a/B4A/C_deviceLinker.bas b/B4A/C_deviceLinker.bas
new file mode 100644
index 0000000..aa8a19b
--- /dev/null
+++ b/B4A/C_deviceLinker.bas
@@ -0,0 +1,193 @@
+B4A=true
+Group=Default Group
+ModulesStructureVersion=1
+Type=Class
+Version=12.8
+@EndOfDesignText@
+'-----------------------------------------------------------------------------------
+' Modulo de Clase: DeviceLinker.bas
+' Propósito: Gestionar el GUID del dispositivo y verificar/ligar el dispositivo
+' a un almacén y ruta en el servidor de forma segura.
+'-----------------------------------------------------------------------------------
+
+Sub Class_Globals
+ ' Configuración del servidor y comandos
+ Private Const GUID_KEY_ALIAS As String = "DeviceGUID" ' << ALIAS PARA EL GUID EN EL KEYSTORE
+
+ ' Objetos y variables internas
+ Private kvs As KeyValueStore ' << ALMACENAMIENTO SEGURO PARA EL GUID
+ Private CallBack As Object ' << OBJETO DE CALLBACK PARA ENVIAR RESPUESTAS
+ Private EventName As String ' << NOMBRE DEL EVENTO DE RESPUESTA
+ Public reqManager As DBRequestManager ' << GESTOR DE PETICIONES AL SERVIDOR jRDC
+ Private logger As Boolean ' << PARA CONTROLAR LOS LOGS DE ESTA CLASE
+ Dim lastJobDoneError As String = ""
+ Dim almacen As String = ""
+ Dim ruta As String = ""
+ Dim deviceId As String = ""
+ ' Se requieren las siguientes librerías:
+ ' - KeyValueStore2
+ ' - DBRequestManager
+ ' - XUI
+End Sub
+
+' Inicializa la clase DeviceLinker.
+' PageObject: El módulo (ej. C_Principal) que inicializa esta clase y manejará sus respuestas (normalmente "Me").
+' NameOfEvent: El prefijo para el evento de respuesta (ej. "DeviceLinker_Response").
+' AppLogger: Booleano para activar/desactivar los logs internos de esta clase, siguiendo el Starter.Logger de la app.
+Public Sub Initialize (PageObject As Object, NameOfEvent As String, AppLogger As Boolean)
+ CallBack = PageObject
+ EventName = NameOfEvent
+ logger = AppLogger ' Asignamos el estado del logger de la aplicación.
+
+ ' Inicializamos el KeyValueStore para almacenamiento seguro del GUID
+ kvs.Initialize(File.DirInternal, "DeviceKeyStore.b4xkey")
+ If logger Then Log("B4XKeyStore 'DeviceKeyStore' inicializado.")
+
+ ' Inicializamos el DBRequestManager para las comunicaciones con el servidor.
+ ' 'Me' indica que el evento JobDone de esta clase se encargará de las respuestas de reqManager.
+' reqManager.Initialize(Me, Starter.DBReqServer)
+ reqManager.Initialize(Me, "http://keymon.net:9010/DB2") 'Servidor de pruebas
+
+ If logger Then Log("DBRequestManager para DeviceLinker inicializado.")
+ If logger Then Log("DeviceLinker inicializado y listo para operar.")
+End Sub
+
+' Verifica y liga el dispositivo con un almacén y una ruta en el servidor.
+' Almacen: El identificador del almacén.
+' Ruta: El identificador de la ruta.
+Public Sub VerifyAndLinkDevice(Almacen_ As String, Ruta_ As String)
+ Dim DeviceId_ As String = GetDeviceGUID ' Obtenemos o generamos el GUID del dispositivo.
+ almacen = Almacen_
+ ruta = Ruta_
+ deviceId = DeviceId_
+ If DeviceId_ = "" Then
+ If logger Then LogColor("Error: GUID del dispositivo no pudo ser obtenido o generado.", Colors.Red)
+ ' Enviar una respuesta de error al callback si no se pudo obtener el GUID.
+ If SubExists(CallBack, EventName & "_Response") Then ' [New Query]
+ CallSub2(CallBack, EventName & "_Response", "GUID_ERROR")
+ End If
+ Return
+ End If
+
+ If logger Then Log($"Enviando solicitud de verificación para DeviceId: ${DeviceId_}, Almacen: ${Almacen_}, Ruta: ${Ruta_}"$)
+
+ Dim cmd As DBCommand ' Creamos un comando para enviar al servidor.
+ cmd.Initialize
+ cmd.Name = "verify_device"
+ ' Pasamos el almacén, la ruta y el GUID del dispositivo como parámetros.
+ cmd.Parameters = Array As Object(Almacen_, Ruta_) ', DeviceId_
+
+ ' Ejecutamos el comando en el servidor. 'Me' indica que DBRequestManager_JobDone en esta clase manejará la respuesta.
+ reqManager.ExecuteQuery(cmd, 0, "verify_device")
+End Sub
+
+' Obtiene el GUID único del dispositivo desde B4XKeyStore.
+' Si no existe, lo genera y lo guarda utilizando Subs.GUID.
+Private Sub GetDeviceGUID As String
+ If kvs.ContainsKey(GUID_KEY_ALIAS) = False Then
+ ' Corrección: Usamos la función GUID ya existente en el módulo Subs [1].
+ Dim NewGUID As String = generaGUID
+ kvs.Put(GUID_KEY_ALIAS, NewGUID) ' Lo guardamos de forma segura en el KeyStore.
+ If logger Then LogColor($"Nuevo GUID generado y guardado: ${NewGUID}"$, Colors.Blue)
+ Return NewGUID
+ Else
+ Dim ExistingGUID As String = kvs.Get(GUID_KEY_ALIAS) ' Recuperamos el GUID existente.
+ If logger Then LogColor($"GUID existente cargado: ${ExistingGUID}"$, Colors.Blue)
+ Return ExistingGUID
+ End If
+End Sub
+
+' Callback para manejar las respuestas del DBRequestManager de esta clase.
+Public Sub JobDone(Job As HttpJob) ' El nombre del sub debe ser 'JobDone' o el que se haya especificado en reqManager.Initialize(Me, ApiUrl)
+ If logger Then Log("INICA JOBDONE DEVICELINKER - " & Job.Tag)
+ If reqManager.reqsList.IsInitialized Then 'Si tenemos lista de requests, la procesamos.
+ If reqManager.reqsList.IndexOf(Job.tag) <> -1 Then
+ reqManager.reqsList.RemoveAt(reqManager.reqsList.IndexOf(Job.tag))
+ LogColor($">>>>>> Recibimos y quitamos ${Job.tag.As(String).ToUpperCase}"$, Colors.Blue)
+ End If
+ LogColor(">>>>>> " & reqManager.reqsList.Size & " - " & reqManager.reqsList, Colors.Blue)
+ End If
+ If Job.Success = False Then
+ lastJobDoneError = Job.ErrorMessage
+ LogColor("############################################", Colors.red)
+ LogColor("###### JobError: " & Job.Tag & CRLF & Job.ErrorMessage, Colors.red)
+ LogColor("############################################", Colors.red)
+ ' Enviar una respuesta de error HTTP al callback.
+ If SubExists(CallBack, EventName & "_Response") Then
+ CallSub2(CallBack, EventName & "_Response", "HTTP_ERROR")
+ End If
+ Else 'If Job Success then ...
+ lastJobDoneError = ""
+ If Job.JobName = "DBRequest" Then ' Asegurarse de que sea una respuesta de DBRequestManager.
+ ' Primero verificamos Job.Success para saber si la comunicación HTTP fue exitosa [New Query]
+ If Job.Success Then
+ Dim result As DBResult = reqManager.HandleJob(Job) ' Procesamos el HttpJob para obtener el DBResult.
+ If logger Then LogColor($"Petición exitosa al servidor. Registros devueltos: ${result.Rows.Size}"$, Colors.Green)
+
+
+ If result.Tag = "hist_cliente_promos" Then 'query tag
+ Starter.skmt.BeginTransaction
+ For Each records() As Object In result.Rows
+ Dim HCCP_CLIENTE As String = records(result.Columns.Get("HCCP_CLIENTE"))
+ Starter.skmt.ExecNonQuery2("INSERT INTO HIST_CLIENTE_CANT_PROMOS(HCCP_CLIENTE, HCCP_PROMO, HCCP_CANT, HCCP_CANT_VENDIDA) VALUES (?,?,?,?)", Array As Object (HCCP_CLIENTE))
+ Next
+ Starter.skmt.TransactionSuccessful
+ Starter.skmt.EndTransaction
+ ' ToastMessageShow(" Historico Clientes Promociones Actualizado." , True)
+ End If
+
+ If result.Tag = "verify_device" Then 'query tag
+ ' Aquí es donde la lógica de la aplicación interpreta el éxito/falla de la operación en el servidor.
+ ' No usamos result.Success porque DBResult no tiene esa propiedad.
+ ' En su lugar, comprobamos si se devolvieron filas y el campo 'status' dentro de los datos.
+ If result.Rows.Size > 0 Then
+ Subs.logJobDoneResultados(result)
+ For Each records() As Object In result.Rows
+ Dim Status As String = records(result.Columns.Get("ESTATUS"))
+ Dim GUID As String = records(result.Columns.Get("GUID"))
+ If deviceId <> GUID Then Status = "ALREADY_REGISTERED" ' Ya existe OTRO registro.
+ ' Invocamos el callback en el módulo principal con el estado.
+ If SubExists(CallBack, EventName & "_Response") Then
+ CallSub2(CallBack, EventName & "_Response", Status)
+ End If
+ Next
+ Else
+ If logger Then LogColor($"El servidor respondió con éxito, pero no encontró registros.${CRLF}Quiere decir que la ruta NO esta registrada en el servidor."$, Colors.Red)
+ Dim cmd As DBCommand ' Creamos un comando para enviar al servidor.
+ cmd.Initialize
+ cmd.Name = "registarMovil"
+ ' Pasamos el almacén, la ruta y el GUID del dispositivo como parámetros.
+ cmd.Parameters = Array As Object(almacen, ruta, deviceId)
+ reqManager.ExecuteCommand(cmd, "registramosGUID")
+ If SubExists(CallBack, EventName & "_Response") Then
+ CallSub2(CallBack, EventName & "_Response", "NO_REGISTRADO")
+ End If
+ End If
+ End If
+
+ If result.Tag = "registramosGUID" Then
+ Subs.logJobDoneResultados(result)
+ If SubExists(CallBack, EventName & "_Response") Then
+ CallSub2(CallBack, EventName & "_Response", "REGISTRO_NUEVO")
+ End If
+ End If
+ End If
+ End If
+ Job.Release ' Muy importante liberar el HttpJob para evitar fugas de memoria.
+ End If
+End Sub
+
+'Genera un GUID (globally unique identifier)
+Sub generaGUID As String
+ Dim sb As StringBuilder
+ sb.Initialize
+ For Each stp As Int In Array(8, 4, 4, 4, 12)
+ If sb.Length > 0 Then sb.Append("-")
+ For n = 1 To stp
+ Dim c As Int = Rnd(0, 16)
+ If c < 10 Then c = c + 48 Else c = c + 55
+ sb.Append(Chr(c))
+ Next
+ Next
+ Return sb.ToString
+End Sub
\ No newline at end of file
diff --git a/B4A/DBRequestManagerW.bas b/B4A/DBRequestManagerW.bas
index 2a1aa3f..cc822a5 100644
--- a/B4A/DBRequestManagerW.bas
+++ b/B4A/DBRequestManagerW.bas
@@ -130,7 +130,7 @@ Public Sub JobDone(job As HttpJob)
job.Release
'<<< Usamos la información recuperada del mapa para llamar al Sub correcto
- if logger then LogColor($"EVENTO: ${jobInfo.EventName}_Completed"$, Colors.Magenta)
+ If logger Then LogColor($"EVENTO: ${jobInfo.EventName}_Completed"$, Colors.Magenta)
CallSubDelayed2(jobInfo.Target, jobInfo.EventName & "_Completed", resultado)
Else
' Handle command result
@@ -161,7 +161,7 @@ Public Sub JobDone(job As HttpJob)
'C <<< Se remueve el job del mapa en caso de ÉXITO
activeJobs.Remove(currentJobTag)
Catch
- if logger then LogColor("Error en jRDC1Wrapper.JobDone: " & LastException, Colors.Red)
+ If logger Then LogColor("Error en jRDC1Wrapper.JobDone: " & LastException, Colors.Red)
'<<< MUY IMPORTANTE: Remover el job del mapa para no tener fugas de memoria
activeJobs.Remove(currentJobTag)
End Try
diff --git a/B4A/KelloggsV4.b4a b/B4A/KelloggsV4.b4a
index c648aff..30e1b73 100644
--- a/B4A/KelloggsV4.b4a
+++ b/B4A/KelloggsV4.b4a
@@ -867,6 +867,7 @@ Library25=togglelibrary
Library26=xcustomlistview
Library27=xui
Library28=zxing_scanner
+Library29=keyvaluestore2
Library3=baqrcode
Library4=bitmapcreator
Library5=byteconverter
@@ -876,46 +877,47 @@ Library8=core
Library9=fileprovider
ManifestCode='This code will be applied to the manifest file during compilation.~\n~'You do not need to modify it in most cases.~\n~'See this link for for more information: https://www.b4x.com/forum/showthread.php?p=78136~\n~AddManifestText(~\n~~\n~)~\n~SetApplicationAttribute(android:icon, "@drawable/icon")~\n~SetApplicationAttribute(android:label, "$LABEL$")~\n~CreateResourceFromFile(Macro, Themes.LightTheme)~\n~'End of default text.~\n~~\n~AddApplicationText(~\n~)~\n~'Set activity to Landscape~\n~SetActivityAttribute(foto, android:screenOrientation, "landscape")~\n~AddApplicationText(~\n~~\n~ ~\n~)~\n~AddManifestText(~\n~~\n~)~\n~'''' para el teclado~\n~ SetActivityAttribute(main, android:windowSoftInputMode, adjustResize|stateHidden)~\n~SetApplicationAttribute(android:allowBackup, "false")~\n~SetServiceAttribute(Tracker, android:foregroundServiceType, "location")~\n~ ~\n~AddManifestText(~\n~~\n~)~\n~AddManifestText(~\n~~\n~)~\n~''CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)~\n~ 'End of default text.~\n~ ~\n~SetApplicationAttribute(android:usesCleartextTraffic, "true")~\n~ AddManifestText(~\n~~\n~)~\n~AddPermission(android.permission.ACCESS_BACKGROUND_LOCATION)~\n~AddManifestText(~\n~~\n~)~\n~AddManifestText()~\n~'AddManifestText()~\n~'AddManifestText()~\n~'AddManifestText()~\n~~\n~AddPermission(android.permission.ACCESS_FINE_LOCATION)~\n~AddPermission(android.permission.BLUETOOTH_ADVERTISE)~\n~AddPermission(android.permission.BLUETOOTH_CONNECT)~\n~AddPermission(android.permission.BLUETOOTH_SCAN)~\n~~\n~AddPermission(android.permission.MANAGE_EXTERNAL_STORAGE)~\n~AddManifestText() 'in order to access the device non-resettable identifiers such as IMEI and serial number.~\n~~\n~'///////////////////////// FLP Y PUSH /////////////~\n~' CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)~\n~' CreateResourceFromFile(Macro, FirebaseAnalytics.Firebase)~\n~' CreateResourceFromFile(Macro, FirebaseAnalytics.FirebaseAnalytics)~\n~' CreateResourceFromFile(Macro, FirebaseNotifications.FirebaseNotifications)~\n~SetServiceAttribute(Tracker, android:foregroundServiceType, "location")~\n~'//////////////////////////////////////////////////////~\n~'Le da mas memoria a la aplicacion~\n~SetApplicationAttribute(android:largeHeap, "true")~\n~AddApplicationText(~\n~ ~\n~ ~\n~ ~\n~)~\n~CreateResource(xml, provider_paths, ~\n~~\n~ ~\n~ ~\n~ ~\n~~\n~)~\n~~\n~'Si al cargar un mapa de google manda este error "java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/ProtocolVersion". agregar la siguiente linea:~\n~AddApplicationText()~\n~SetApplicationAttribute(android:allowBackup, "false")~\n~SetApplicationAttribute(android:exported, "true")~\n~AddManifestText()~\n~AddApplicationText(~\n~~\n~ ~\n~ )~\n~~\n~ 'Para que se registre para abrir bases de datos~\n~' AddActivityText(main,~\n~'~\n~'~\n~'~\n~'~\n~')~\n~~\n~ 'Para que se registre para abrir bases de datos~\n~ AddActivityText(main,~\n~~\n~~\n~~\n~~\n~~\n~)
Module1=B4XMainPage
-Module10=C_Pedidos
-Module11=C_Principal
-Module12=C_Productos
-Module13=C_Promos
-Module14=C_TicketsDia
-Module15=|relative|..\C_TrendSpending
-Module16=C_updateAvailable
-Module17=CameraExClass
-Module18=DBRequestManager
-Module19=DBRequestManagerW
+Module10=C_NuevoCliente
+Module11=C_Pedidos
+Module12=C_Principal
+Module13=C_Productos
+Module14=C_Promos
+Module15=C_TicketsDia
+Module16=|relative|..\C_TrendSpending
+Module17=C_updateAvailable
+Module18=CameraExClass
+Module19=DBRequestManager
Module2=C_CheckList
-Module20=DownloadService
-Module21=errorManager
-Module22=EscPosPrinter
-Module23=FileHandler
-Module24=foto
-Module25=kms_helperSubs
-Module26=ManageExternalStorage
-Module27=MAPA_RUTAS
-Module28=Promociones
-Module29=SD_Spinner
+Module20=DBRequestManagerW
+Module21=DownloadService
+Module22=errorManager
+Module23=EscPosPrinter
+Module24=FileHandler
+Module25=foto
+Module26=kms_helperSubs
+Module27=ManageExternalStorage
+Module28=MAPA_RUTAS
+Module29=Promociones
Module3=C_Cliente
-Module30=Starter
-Module31=Subs
-Module32=Tracker
+Module30=SD_Spinner
+Module31=Starter
+Module32=Subs
+Module33=Tracker
Module4=C_Clientes
-Module5=C_Historico
-Module6=C_Mapas
-Module7=C_Nota
-Module8=C_NoVenta
-Module9=C_NuevoCliente
+Module5=C_deviceLinker
+Module6=C_Historico
+Module7=C_Mapas
+Module8=C_Nota
+Module9=C_NoVenta
NumberOfFiles=423
-NumberOfLibraries=28
-NumberOfModules=32
+NumberOfLibraries=29
+NumberOfModules=33
Version=12.8
@EndOfDesignText@
#Region Project Attributes
#ApplicationLabel: Kelloggs Venta
#VersionCode: 3000
- #VersionName: 5.09.01
+ #VersionName: 5.09.10
#SupportedOrientations: portrait
#CanInstallToExternalStorage: False
#BridgeLogger:true
diff --git a/B4A/KelloggsV4.b4a.meta b/B4A/KelloggsV4.b4a.meta
index d7ca96e..e57018b 100644
--- a/B4A/KelloggsV4.b4a.meta
+++ b/B4A/KelloggsV4.b4a.meta
@@ -25,6 +25,7 @@ ModuleBookmarks3=
ModuleBookmarks30=
ModuleBookmarks31=
ModuleBookmarks32=
+ModuleBookmarks33=
ModuleBookmarks4=
ModuleBookmarks5=
ModuleBookmarks6=
@@ -58,6 +59,7 @@ ModuleBreakpoints3=
ModuleBreakpoints30=
ModuleBreakpoints31=
ModuleBreakpoints32=
+ModuleBreakpoints33=
ModuleBreakpoints4=
ModuleBreakpoints5=
ModuleBreakpoints6=
@@ -65,38 +67,39 @@ ModuleBreakpoints7=
ModuleBreakpoints8=
ModuleBreakpoints9=
ModuleClosedNodes0=
-ModuleClosedNodes1=4,6
+ModuleClosedNodes1=6,8,46,47
ModuleClosedNodes10=
-ModuleClosedNodes11=3,5,6
-ModuleClosedNodes12=3,7,8,9,10,11,12
-ModuleClosedNodes13=6,7,8,9,12,13
-ModuleClosedNodes14=
-ModuleClosedNodes15=3,7,8,15,17
-ModuleClosedNodes16=
+ModuleClosedNodes11=
+ModuleClosedNodes12=3,5,6
+ModuleClosedNodes13=7,8,9,10,11,12
+ModuleClosedNodes14=6,7,8,9,12,13
+ModuleClosedNodes15=
+ModuleClosedNodes16=3,7,8,15,17
ModuleClosedNodes17=
ModuleClosedNodes18=
-ModuleClosedNodes19=
+ModuleClosedNodes19=7,8,9,10,11,12,13,14
ModuleClosedNodes2=
ModuleClosedNodes20=
ModuleClosedNodes21=
ModuleClosedNodes22=
ModuleClosedNodes23=
ModuleClosedNodes24=
-ModuleClosedNodes25=24,25,26,27,31,32,33,35
-ModuleClosedNodes26=
-ModuleClosedNodes27=4
-ModuleClosedNodes28=
+ModuleClosedNodes25=
+ModuleClosedNodes26=24,26,27,31,32,33,35
+ModuleClosedNodes27=
+ModuleClosedNodes28=4
ModuleClosedNodes29=
ModuleClosedNodes3=1,3,5,6
ModuleClosedNodes30=
-ModuleClosedNodes31=114,116
-ModuleClosedNodes32=
+ModuleClosedNodes31=
+ModuleClosedNodes32=114,116
+ModuleClosedNodes33=
ModuleClosedNodes4=
ModuleClosedNodes5=
ModuleClosedNodes6=
ModuleClosedNodes7=
ModuleClosedNodes8=
ModuleClosedNodes9=
-NavigationStack=B4XMainPage,ImageView1_LongClick,1031,6,C_Principal,Class_Globals,12,0,Diseñador Visual,productos.bal,-100,1,C_Productos,Busca_TextChanged,1467,4,Subs,traeTablaProds,1683,0,Subs,generaGUID_EnExterno,1966,0,Subs,parseHTTPError,1978,0,C_TrendSpending,Initialize,29,0,C_Principal,JobDone,2081,6,C_Principal,cargar_Click,939,0,B4XMainPage,JobDone,570,0
+NavigationStack=C_Cliente,GPS_LocationChanged,906,0,C_Cliente,B4XPage_Appear,552,6,Diseñador Visual,cliente.bal,-100,6,Diseñador Visual,principal.bal,-100,2,C_Principal,cargar_Click,837,0,C_Principal,B4XPage_Appear,539,6,kms_helperSubs,traeRuta,748,0,C_deviceLinker,Initialize,43,0,C_deviceLinker,VerifyAndLinkDevice,64,0,B4XMainPage,ImageView1_LongClick,1041,0
SelectedBuild=0
-VisibleModules=1,30,11,15,3,31,12,13,7,28
+VisibleModules=31,1,12,5,16,26,3,32,13,14,8,33,10,28
diff --git a/B4A/kms_helperSubs.bas b/B4A/kms_helperSubs.bas
index b337d97..f35b772 100644
--- a/B4A/kms_helperSubs.bas
+++ b/B4A/kms_helperSubs.bas
@@ -1035,15 +1035,25 @@ Sub traeUsarIntentBDWA As Boolean 'ignore
End Sub
'Regresa los clientes nuevos maximos.
-'Si no está especificado, el default es 2.
+'Si no está especificado o no esta autorizado para crear clientes nuevos, el default es 0.
Sub traeMaxClientesNuevos As Int 'ignore
- Private CN As Int = 5
- Private x As Cursor = Starter.skmt.ExecQuery($"select CAT_VA_VALOR from CAT_VARIABLES where CAT_VA_DESCRIPCION = 'MAXCTESNUEVOS'"$)
+ Private CN_AUT As Int = 0
+ Private CN_MAX As Int = 0
+ Private x As Cursor = Starter.skmt.ExecQuery($"select ifnull(CAT_VA_VALOR, 0) as CAT_VA_VALOR from CAT_VARIABLES where CAT_VA_DESCRIPCION = 'CN_AUTORIZADO'"$)
If x.RowCount > 0 Then
x.Position = 0
- CN = x.GetString("CAT_VA_VALOR")
+ CN_AUT = x.GetInt("CAT_VA_VALOR")
End If
- Return CN
+ If CN_AUT = 1 Then
+ Private x As Cursor = Starter.skmt.ExecQuery($"select ifnull(CAT_VA_VALOR, 0) as CAT_VA_VALOR from CAT_VARIABLES where CAT_VA_DESCRIPCION = 'CN_CUANTOS'"$)
+ If x.RowCount > 0 Then
+ x.Position = 0
+ CN_MAX = x.GetString("CAT_VA_VALOR")
+ End If
+ End If
+ x.Close
+ Log($"Clientes Nuevos, Autorizado ${CN_AUT}, Cuantos: ${CN_MAX}"$)
+ Return CN_MAX
End Sub
'Regresa verdadero o falso dependiendo si el cliente lleva pedido DOE.