From ae8ac63b1d262d2cf887015b952b8aae007c108c Mon Sep 17 00:00:00 2001 From: Jose Alberto Guerra Ugalde Date: Wed, 17 Sep 2025 18:51:37 -0600 Subject: [PATCH] =?UTF-8?q?-=20VERSION=205.09.10=20-=20Se=20escondio=20el?= =?UTF-8?q?=20boton=20de=20NoVenta=20en=20cliente=20hata=20tener=20ubicaci?= =?UTF-8?q?on.=20-=20Se=20habilit=C3=B3=20los=20clientes=20nuevos=20POR=20?= =?UTF-8?q?RUTA,=20en=20la=20tabla=20"CLIENTES=5FNUEVOS=5FX=5FRUTA",=20y?= =?UTF-8?q?=20si=20ya=20llegaron=20a=20limite,=20se=20"deshabilita"=20el?= =?UTF-8?q?=20boton=20en=20principal.=20-=20Se=20corrige=20que=20para=20Tr?= =?UTF-8?q?ade=20Spending,=20estaba=20todavia=20la=20ruta=20y=20almacen=20?= =?UTF-8?q?en=20duro.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- B4A/B4XMainPage.bas | 57 ++++++++--- B4A/C_Cliente.bas | 19 +++- B4A/C_NuevoCliente.bas | 12 ++- B4A/C_Principal.bas | 41 +++++++- B4A/C_deviceLinker.bas | 193 ++++++++++++++++++++++++++++++++++++++ B4A/DBRequestManagerW.bas | 4 +- B4A/KelloggsV4.b4a | 64 +++++++------ B4A/KelloggsV4.b4a.meta | 35 +++---- B4A/kms_helperSubs.bas | 20 +++- 9 files changed, 369 insertions(+), 76 deletions(-) create mode 100644 B4A/C_deviceLinker.bas 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.