diff --git a/B4A/C_Cliente.bas b/B4A/C_Cliente.bas index c0ceeed..5d63af9 100644 --- a/B4A/C_Cliente.bas +++ b/B4A/C_Cliente.bas @@ -969,7 +969,8 @@ Sub Guardar_Click Else b_inicioFinVenta.Visible = False Starter.enVenta = False -' LogColor(">>>>>> EN VENTA: " & Starter.enVenta, Colors.red) + LogColor(">>>>>> ABORDO: " & Starter.enVenta, Colors.red) + Subs.bitacora(Subs.fechanormal(DateTime.Now), usuario, Id_Almacen, ruta_tienda, "Venta Abordo", "0", "", Subs.fechanormal(DateTime.Now), Starter.lat_gps, Starter.lon_gps, precision, "", "") Subs.iniciaActividad("principal") B4XPages.ShowPageAndRemovePreviousPages("Principal") End If @@ -4050,6 +4051,7 @@ Private Sub l_ubicacion2_LongClick End Sub Sub JobDone(Job As HttpJob) + Log("JOBDONE CLIENTE") If Job.Success = False Then ' ToastMessageShow("Error: " & Job.ErrorMessage, True) LogColor("Error: " & Job.tag & " : " & Job.ErrorMessage, Colors.red) diff --git a/B4A/C_Productos.bas b/B4A/C_Productos.bas index 551d94c..e85b50f 100644 --- a/B4A/C_Productos.bas +++ b/B4A/C_Productos.bas @@ -100,11 +100,13 @@ Sub Class_Globals Dim dispAbordo As String Private l_avisoAbordo As Label Private l_infoPedido As Label + Dim promosC As Promociones End Sub 'You can add more parameters here. Public Sub Initialize As Object kh.Initialize(Me, "kh", Starter.skmt) + promosC.Initialize(Me, "promosC", Starter.skmt) Return Me End Sub @@ -325,6 +327,7 @@ Sub lv_catalogos_ItemClick (Position As Int, Value As Object) For i=0 To c2.RowCount -1 c2.Position=i Private tm As Map = Subs.procesaPromocion(c2.GetString("CAT_GP_ID"), clienteId) +' promosC.procesaPromocion(c2.GetString("CAT_GP_ID"), clienteId) If tm.Get("status") = "ok" Then 'Solo muestrala si hay producto. lv_promos.AddTwoLines(c2.GetString("CAT_GP_NOMBRE"),"# " & c2.GetString("CAT_GP_ALMACEN") & " $ " & c2.GetString("CAT_GP_PRECIO") & " F:" & tm.Get("mp").As(Map).Get("prodsFijosCant") & " V:" & tm.Get("mp").As(Map).Get("prodsVariablesCant")) End If diff --git a/B4A/C_Promos.bas b/B4A/C_Promos.bas index 6877687..d15c745 100644 --- a/B4A/C_Promos.bas +++ b/B4A/C_Promos.bas @@ -47,6 +47,7 @@ End Sub 'You can add more parameters here. Public Sub Initialize As Object +' promosC.Initialize(Me, "promosC", Starter.skmt) Return Me End Sub diff --git a/B4A/Files/cacahuates.png b/B4A/Files/cacahuates.png new file mode 100644 index 0000000..0af2b0f Binary files /dev/null and b/B4A/Files/cacahuates.png differ diff --git a/B4A/Files/cacahuates_blanco.png b/B4A/Files/cacahuates_blanco.png new file mode 100644 index 0000000..626a703 Binary files /dev/null and b/B4A/Files/cacahuates_blanco.png differ diff --git a/B4A/Files/cacahuates_blanco2.png b/B4A/Files/cacahuates_blanco2.png new file mode 100644 index 0000000..6e3d9ee Binary files /dev/null and b/B4A/Files/cacahuates_blanco2.png differ diff --git a/B4A/Files/cacahuates_blanco3.png b/B4A/Files/cacahuates_blanco3.png new file mode 100644 index 0000000..f01cd51 Binary files /dev/null and b/B4A/Files/cacahuates_blanco3.png differ diff --git a/B4A/Files/cacahuates_chico.png b/B4A/Files/cacahuates_chico.png new file mode 100644 index 0000000..ecf0bbb Binary files /dev/null and b/B4A/Files/cacahuates_chico.png differ diff --git a/B4A/Files/cacahuates_original.jpeg b/B4A/Files/cacahuates_original.jpeg new file mode 100644 index 0000000..d29c608 Binary files /dev/null and b/B4A/Files/cacahuates_original.jpeg differ diff --git a/B4A/Files/cacahuates_original2.bmp b/B4A/Files/cacahuates_original2.bmp new file mode 100644 index 0000000..14ef40a Binary files /dev/null and b/B4A/Files/cacahuates_original2.bmp differ diff --git a/B4A/Files/cacahuates_original2.jpg b/B4A/Files/cacahuates_original2.jpg new file mode 100644 index 0000000..050819e Binary files /dev/null and b/B4A/Files/cacahuates_original2.jpg differ diff --git a/B4A/Files/cacahuates_original3.bmp b/B4A/Files/cacahuates_original3.bmp new file mode 100644 index 0000000..aff191a Binary files /dev/null and b/B4A/Files/cacahuates_original3.bmp differ diff --git a/B4A/KelloggsV4.b4a b/B4A/KelloggsV4.b4a index cd6ce90..53a14b9 100644 --- a/B4A/KelloggsV4.b4a +++ b/B4A/KelloggsV4.b4a @@ -868,11 +868,12 @@ Module22=foto Module23=kms_helperSubs Module24=ManageExternalStorage Module25=MAPA_RUTAS -Module26=SD_Spinner -Module27=Starter -Module28=Subs -Module29=Tracker +Module26=Promociones +Module27=SD_Spinner +Module28=Starter +Module29=Subs Module3=C_Cliente +Module30=Tracker Module4=C_Clientes Module5=C_Historico Module6=C_Mapas @@ -881,13 +882,13 @@ Module8=C_NoVenta Module9=C_NuevoCliente NumberOfFiles=410 NumberOfLibraries=29 -NumberOfModules=29 +NumberOfModules=30 Version=12.8 @EndOfDesignText@ #Region Project Attributes #ApplicationLabel: Kelloggs Venta #VersionCode: 3000 - #VersionName: 4.05.08 + #VersionName: 4.05.09 #SupportedOrientations: portrait #CanInstallToExternalStorage: False #BridgeLogger:true diff --git a/B4A/KelloggsV4.b4a.meta b/B4A/KelloggsV4.b4a.meta index aa6c1f1..fbe9f15 100644 --- a/B4A/KelloggsV4.b4a.meta +++ b/B4A/KelloggsV4.b4a.meta @@ -22,6 +22,7 @@ ModuleBookmarks27= ModuleBookmarks28= ModuleBookmarks29= ModuleBookmarks3= +ModuleBookmarks30= ModuleBookmarks4= ModuleBookmarks5= ModuleBookmarks6= @@ -52,6 +53,7 @@ ModuleBreakpoints27= ModuleBreakpoints28= ModuleBreakpoints29= ModuleBreakpoints3= +ModuleBreakpoints30= ModuleBreakpoints4= ModuleBreakpoints5= ModuleBreakpoints6= @@ -82,12 +84,13 @@ ModuleClosedNodes27= ModuleClosedNodes28= ModuleClosedNodes29= ModuleClosedNodes3= +ModuleClosedNodes30= ModuleClosedNodes4= ModuleClosedNodes5= ModuleClosedNodes6= ModuleClosedNodes7= ModuleClosedNodes8= ModuleClosedNodes9= -NavigationStack=C_Cliente,B_IMP2_Click,1101,0,C_Cliente,Imprime_ticket,1565,6,C_Cliente,Bt_GuardarBoleta_Click,3674,0,C_Principal,SUBIR_INFO_PEDIDO,2841,1,C_Cliente,b_inicioFinVenta_Click,4212,3,C_NoVenta,Class_Globals,1,0,Visual Designer,principal.bal,-100,3,Visual Designer,noventa.bal,-100,1,C_NoVenta,GUARDA_Click,85,1,Subs,bitacora,1704,6 +NavigationStack=C_Cliente,JobDone,4047,5,Subs,bitacora,1716,0,Promociones,restaFijosPromo,328,1,C_Productos,lv_catalogos_ItemClick,302,5,C_Cliente,Bt_GuardarBoleta_Click,3674,0,C_Cliente,BP_DOE_R1_Click,4205,0,C_Cliente,b_inicioFinVenta_Click,4215,0,Visual Designer,cliente.bal,-100,2,C_Cliente,Guardar_Click,959,6,Main,Globals,26,0 SelectedBuild=0 -VisibleModules=1,27,11,3,12,4,28,29,8 +VisibleModules=1,28,11,3,12,4,29,8,26,13 diff --git a/B4A/Promociones.bas b/B4A/Promociones.bas new file mode 100644 index 0000000..4151d35 --- /dev/null +++ b/B4A/Promociones.bas @@ -0,0 +1,458 @@ +B4A=true +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=12.8 +@EndOfDesignText@ +Sub Class_Globals + Dim ruta As String + Dim almacen As String + Dim cliente As String + Dim db As SQL + Private EventName As String 'ignore + Private CallBack As Object 'ignore +End Sub + +'Initializes the object. You can add parameters to this method if needed. +Public Sub Initialize (vCallback As Object, vEventName As String, db0 As SQL) As Object + EventName = vEventName + CallBack = vCallback + db = db0 + Log("PROMOS INIT") + db.ExecNonQuery("CREATE TABLE IF NOT EXISTS PROMOCIONES_INFO (P_ID TEXT, P_ESTATUS TEXT, P_MAXXCLIENTE NUMERIC, P_MAXRECURRENTE NUMERIC, P_MAXPROMOS NUMERIC, HISTORICO TEXT, P_TIPOS TEXT, P_PRODSFIJOS TEXT, P_PRODSFIJOS_CANT NUMERIC, P_PRODSFIJOS_PIEZAS TEXT, P_PRODSFIJOS_PRECIOS TEXT, P_PRODSVARIABLES TEXT, P_PRODSVARIABLES_CANT NUMERIC, P_PRODSVARIABLES_PRECIOS TEXT, P_PRODSVARIABLES_REQUERIDOS NUMERIC)") + db.ExecNonQuery("DELETE FROM PROMOCIONES_INFO") + Return Me +End Sub + + +Sub procesaPromocion(idPromo As String, cliente0 As String) As Map 'ignore + Private thisLog As Boolean = False 'Si es verdadero, muestra los logs de este sub. + cliente = cliente0 + Private inicioContador As String = DateTime.Now + Private maxPromos As Int = 0 + If thisLog Then LogColor($"********* Iniciamos revision de Promo ${idPromo} *********"$, Colors.red) + +' LogColor("**************************** " & traeInfoFromPromo("P_PRODSFIJOS", idPromo), Colors.blue) +' Private d As List = traeListFromPromo("P_PRODSFIJOS", idPromo) +' Log(d.Get(0)) + + 'Obtenemos el mapa con toda la info de la promoción. +' Private pm As Map = traePromo(idPromo, cliente) + traePromo(idPromo, cliente0) +' If thisLog Then LogColor(pm, Colors.Blue) +' If thisLog Then LogColor("|" & pm.Get("maxPromos") & "|", Colors.Blue) +' Log("|"&revisaMaxPromosProdsFijosPorInventario(pm)&"|") + If revisaMaxPromosProdsFijosPorInventario(idPromo) < 1 Then db.ExecNonQuery($"update PROMOCIONES_INFO set P_ESTATUS = 'ko' where P_ID = '${idPromo}'"$) + Log($"resultado = ${traeInfoFromPromo("P_ESTATUS", idPromo)}"$) + If traeInfoFromPromo("P_ESTATUS", idPromo) = "ok" Then 'Si encontramos la promoción, entonces ... + 'Buscamos el máximo de promociones permitidas. + maxPromos = traeMaxPromos(idPromo) +' If thisLog Then LogColor($"Promociones permitidas=${mp}"$, Colors.Blue) +' If thisLog Then Log("Promos vendidas: " & traePromosVendidas(idPromo, cliente)) + If maxPromos < 1 Then + If thisLog Then LogColor("Ya se vendieron las promos PERMITIDAS para el cliente", Colors.red) + Return CreateMap("status":"ko") ' , "mp":pm + End If + 'Restamos del inventario (mapa) las piezas necesarias para los productos fijos. + + Private inventarioSinFijos As Map = restaFijosPromo(idPromo, CreateMap()) + If thisLog Then LogColor("inventariosfijos="&inventarioSinFijos, Colors.Magenta) +' If inventarioSinFijos.Get("resultado") = "ok" Then +' 'Revisamos que los productos variables requeridos sean menos que el inventario total (mapa). +' Private pv As Boolean = alcanzanLosVariablesParaPromo(pm, inventarioSinFijos) +' If thisLog Then Log("Alcanzan los variables? --> " & pv) +' If pv Then Return CreateMap("status":"ok", "mp":pm) Else Return CreateMap("status":"ko", "mp":pm) +' Else +' If thisLog Then LogColor("NO HAY INVENTARIO SUFICIENTE " & idPromo, Colors.red) +' Return CreateMap("status":"ko", "mp":pm) +' End If + + + Else + Return CreateMap("status":"ko") ' , "mp":pm + End If + ' Si tenemos suficiente inventario para los variables mostramos la promocion, si no ... + ' break 'NO HAY INVENTARIO SUFICIENTE PARA LA PROMOCION. + LogColor("TIEMPO DE PROCESO ESTA PROMO: " & ((DateTime.Now-inicioContador)/1000), Colors.Red) +End Sub + +'Regresa un mapa con la información de la promo. +'Regresa: {id, maxXcliente, maxRecurrente, maxPromos, historico, +' productos={idProducto={idProducto, preciosimptos, precio, almacen, tipo, piezas, usuario, fecha, regalo, clasif}} 'Mapa con los productos de la promo y los datos de cada uno. +' tipos={idProducto=tipo} 'Mapa con id y tipo del producto, 0 si es fijo y 1 si es variable. +' prodsFijos={idProducto,idProducto} 'Lista con los ids de los productos fijos. +' prodsVariables={idProducto,idProducto} 'Lista con los ids de los productos variables. +' resultado="OK" 'Ok si existe la promocion. +' prodsVariablesRequeridos=5} 'Cantidad de productos variables requeridos para la promoción. +Sub traePromo(promo As String, cliente0 As String) As Map + Private thisLog As Boolean = True + If thisLog Then LogColor("############# traePromoC: "&promo, Colors.red) + Private inicioContador As String = DateTime.Now + Private c As Cursor = Starter.skmt.ExecQuery("Select * from promos_comp where cat_pa_id = '"& promo&"'") 'Obtenemos las el maximo de promocioones a otorgar. + Private siHistorico As String = 0 +' Private promoMap As Map + Private prodsFijos, prodsFijosPrecios, prodsFijosPiezas, prodsVariables, prodsVariablesPrecios As List +' promoMap.Initialize + prodsFijos.Initialize + prodsFijosPrecios.Initialize + prodsFijosPiezas.Initialize + prodsVariables.Initialize + prodsVariablesPrecios.Initialize + c.Position = 0 +' promoMap = CreateMap("id":promo, "maxXcliente":0, "maxRecurrente":0, "maxPromos":0) 'Ponemos el DEFAULT en CERO. + Private yaExistePromo As Cursor = db.ExecQuery($"SELECT P_ID from PROMOCIONES_INFO where P_ID = '${promo}'"$) + If yaExistePromo.RowCount > 0 Then + db.ExecNonQuery($"update PROMOCIONES_INFO set P_MAXXCLIENTE = 0, P_MAXRECURRENTE = 0, P_MAXPROMOS = 0 where P_ID = '${promo}'"$) + Else + db.ExecNonQuery($"insert into PROMOCIONES_INFO (P_ID, P_MAXXCLIENTE, P_MAXRECURRENTE, P_MAXPROMOS) values ('${promo}', 0, 0, 0)"$) + End If + If c.RowCount > 0 Then +' promoMap = CreateMap("id":promo, "maxXcliente":c.GetString("CAT_PA_MAXPROMCLIE"), "maxRecurrente":c.GetString("CAT_PA_MAXPROMREC"), "maxPromos":c.GetString("CAT_PA_MAXPROM")) + db.ExecNonQuery($"update PROMOCIONES_INFO set P_MAXXCLIENTE = ${c.GetInt("CAT_PA_MAXPROMREC")}, P_MAXRECURRENTE = ${c.GetInt("CAT_PA_MAXPROMREC")}, P_MAXPROMOS = ${c.GetInt("CAT_PA_MAXPROM")} where P_ID = '${promo}'"$) +' Log($"update PROMOCIONES_INFO set P_MAXXCLIENTE = ${c.GetInt("CAT_PA_MAXPROMREC")}, P_MAXRECURRENTE = ${c.GetInt("CAT_PA_MAXPROMREC")}, P_MAXPROMOS = ${c.GetInt("CAT_PA_MAXPROM")} where P_ID = '${promo}'"$) + End If + '######### PROMOCIONES SEGMENTADAS ########## +' Si la promo esta en la lista, SOLO los clientes que la tengan la pueden ver. + Private ps As Cursor = Starter.skmt.ExecQuery($"select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${cliente0}' "$) +' Log($"select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${cliente0}' "$) + Log($"PROMOS SEGMENTADAS DISPONIBLES: ${ps.RowCount}"$) + If ps.RowCount > 0 Then + ps.Position = 0 + db.ExecNonQuery($"update PROMOCIONES_INFO set P_MAXXCLIENTE = 0, P_MAXRECURRENTE = 0, P_MAXPROMOS = 0 where P_ID = '${promo}'"$) 'Si es segmentada la ponemos en cero, porque SOLO le debe de aparecer a ciertos clientes. +' promoMap = CreateMap("id":promo, "maxXcliente":0, "maxRecurrente":0, "maxPromos":0) 'Si es segmentada la ponemos en cero, porque SOLO le debe de aparecer a ciertos clientes. + LogColor($">>> PROMO "${promo}" SEGMENTADA PARA EL CLIENTE ${ps.GetString("HCCP_CLIENTE")}"$, Colors.Magenta) +' Select hccp_cliente As valido from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${traecliente}' + Private ps2 As Cursor = Starter.skmt.ExecQuery($"Select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${cliente0}' and HCCP_CANT > HCCP_CANT_VENDIDA"$) +' Log($"Select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${traeCliente}' and HCCP_CANT > HCCP_CANT_VENDIDA"$) + Log($"registros:${ps2.RowCount}"$) + If ps2.RowCount > 0 Then + ps2.Position = 0 +' Log($"registros:${ps2.RowCount}, cliente: ${ps2.GetString("HCCP_CLIENTE")} cant:${ps2.GetString("HCCP_CANT")}, Vendidas: ${ps2.GetString("HCCP_CANT_VENDIDA")}"$) + db.ExecNonQuery($"update PROMOCIONES_INFO set P_MAXXCLIENTE = ${(ps2.getint("HCCP_CANT")-ps2.GetInt("HCCP_CANT_VENDIDA"))}, P_MAXRECURRENTE = ${ps2.GetString("HCCP_CANT")}, P_MAXPROMOS = ${ps2.GetString("HCCP_CANT")} where P_ID = '${promo}'"$) 'Si es segmentada SOLO le aparece a ciertos clientes. +' Log($"update PROMOCIONES_INFO set P_MAXXCLIENTE = ${(ps2.GetString("HCCP_CANT")-ps2.GetString("HCCP_CANT_VENDIDA"))}, P_MAXRECURRENTE = ${ps2.GetString("HCCP_CANT")}, P_MAXPROMOS = ${ps2.GetString("HCCP_CANT")} where P_ID = '${promo}'"$) +' promoMap = CreateMap("id":promo, "maxXcliente":(ps2.GetString("HCCP_CANT")-ps2.GetString("HCCP_CANT_VENDIDA")), "maxRecurrente":ps2.GetString("HCCP_CANT"), "maxPromos":ps2.GetString("HCCP_CANT")) 'Si es segmentada SOLO le aparece a ciertos clientes. + End If + End If +' Log(promoMap) +' Log($"P_MAXXCLIENTE = ${(ps2.GetString("HCCP_CANT")-ps2.GetString("HCCP_CANT_VENDIDA"))}, P_MAXRECURRENTE = ${ps2.GetString("HCCP_CANT")}, P_MAXPROMOS = ${ps2.GetString("HCCP_CANT")}'"$) +' ########## TERMINA PROMOS SEGMENTADAS ########## + c = Starter.skmt.ExecQuery("Select count(*) as hist from HIST_PROMOS where HP_CLIENTE = '"& cliente0 & "' and HP_CODIGO_PROMOCION = '" & promo & "'") 'Revisamos si hay historico de la promoción. + c.Position = 0 + If c.GetString("hist") > 0 Then siHistorico = 1 + db.ExecNonQuery($"update PROMOCIONES_INFO set HISTORICO = ${siHistorico} where P_ID = '${promo}'"$) +' promoMap.Put("historico", siHistorico) + c = Starter.skmt.ExecQuery("Select * from CAT_DETALLES_PAQ where CAT_DP_ID = '"& promo & "'") 'Obtenemos los detalles de la promoción. + c.Position = 0 + If c.RowCount > 0 Then + Private prods, tipos As Map + prods.Initialize + tipos.Initialize + For i = 0 To c.RowCount -1 + c.Position=i + prods.Put(c.GetString("CAT_DP_IDPROD"), CreateMap("idProducto":c.GetString("CAT_DP_IDPROD"), "precioSimptos":c.GetString("CAT_DP_PRECIO_SIMPTOS"), "precio":c.GetString("CAT_DP_PRECIO"), "tipo":c.GetString("CAT_DP_TIPO"), "piezas":c.GetString("CAT_DP_PZAS"), "regalo":c.GetString("CAT_DP_REGALO"), "clasif":c.GetString("CAT_DP_CLASIF"))) + tipos.Put(c.GetString("CAT_DP_IDPROD"), c.GetString("CAT_DP_TIPO")) + If c.GetString("CAT_DP_TIPO") = "0" Then + prodsFijos.Add(c.GetString("CAT_DP_IDPROD")) + prodsFijosPrecios.Add(c.GetString("CAT_DP_PRECIO")) + prodsFijosPiezas.Add(c.GetString("CAT_DP_PZAS")) + End If + If c.GetString("CAT_DP_TIPO") = "1" Then + prodsVariables.Add(c.GetString("CAT_DP_IDPROD")) + prodsVariablesPrecios.Add(c.GetString("CAT_DP_PRECIO")) + End If +' If thisLog Then Log($"id:${c.GetString("CAT_DP_IDPROD")}, tipo:${c.GetString("CAT_DP_TIPO")}"$) + Next + db.ExecNonQuery($"update PROMOCIONES_INFO set P_TIPOS = '${tipos}', P_PRODSFIJOS = '${prodsFijos}', P_PRODSFIJOS_CANT = ${prodsFijos.Size}, P_PRODSFIJOS_PRECIOS = '${prodsFijosPrecios}', P_PRODSFIJOS_PIEZAS = '${prodsFijosPiezas}', P_PRODSVARIABLES = '${prodsVariables}', P_PRODSVARIABLES_CANT = ${prodsVariables.Size}, P_PRODSVARIABLES_PRECIOS = '${prodsVariablesPrecios}', P_ESTATUS = 'ok' where P_ID = '${promo}'"$) +' promoMap.Put("productos", prods) 'Mapa con los productos de la promocion (id, precio, almacen, tipo, piezas, etc.) +' promoMap.Put("tipos", tipos) 'Mapa con los productos de la promoción y su tipo (fijo o variable). +' promoMap.Put("prodsFijos", prodsFijos) 'Lista de los productos fijos de la promoción. +' promoMap.Put("prodsFijosCant", prodsFijos.Size) +' promoMap.Put("prodsFijosPrecios", prodsFijosPrecios) +' promoMap.Put("prodsFijosPiezas", prodsFijosPiezas) +' promoMap.Put("prodsVariables", prodsVariables) 'Lista de los productos variables de la promoción. +' promoMap.Put("prodsVariablesCant", prodsVariables.Size) +' promoMap.Put("prodsVariablesPrecios", prodsVariablesPrecios) +' promoMap.Put("resultado", "ok") + Else +' promoMap.Put("resultado", "No hay datos de la promoción.") + db.ExecNonQuery($"update PROMOCIONES_INFO set P_ESTATUS = 'No hay datos de la promoción.' where P_ID = '${promo}'"$) + End If + c = Starter.skmt.ExecQuery("Select CAT_GP_STS, CAT_GP_NOMBRE from CAT_GUNAPROD2 where CAT_GP_ID = '"& promo & "'") 'Obtenemos las piezas requeridas de productos variables para la promoción. + c.Position = 0 + Private pvr As String = 0 + If c.RowCount > 0 Then + c.Position = 0 + pvr = c.GetString("CAT_GP_STS") +' promoMap.Put("prodsVariablesRequeridos", pvr) 'Cantidad de productos variables requeridos para la promoción. +' promoMap.put("descripcion", c.GetString("CAT_GP_NOMBRE")) + db.ExecNonQuery($"update PROMOCIONES_INFO set P_PRODSVARIABLES_REQUERIDOS = ${pvr} where P_ID = '${promo}'"$) 'Cantidad de productos variables requeridos para la promoción. + End If + c.Close +' If thisLog Then Log($"Inv variables: ${cuantosVariablesDisponiblesDB(promo)}"$) +' If thisLog Then Log($"Inv dispo: ${traemosInventarioDisponibleParaPromo(promo)}"$) +' If thisLog Then LogColor($"Promo ${promo}: ${promoMap}"$, Colors.Blue) + If thisLog Then LogColor("TIEMPO para traePromo -=" & promo & "=- : " & ((DateTime.Now-inicioContador)/1000), Colors.Red) +' Return promoMap +End Sub + + +'Regresa cuantas promos alcanzan con los productos FIJOS que hay en inventario. +Sub revisaMaxPromosProdsFijosPorInventario(id As String) As Int + +' Private pm As Map = CreateMap() '' XXXXXXXX + + Private thisLog As Boolean = True + Private invFijoXpromo As Map + Private t As List + Private c As ResultSet = db.ExecQuery($"select P_PRODSFIJOS, P_PRODSFIJOS_PIEZAS from PROMOCIONES_INFO where P_ID = '${id}'"$) + t.Initialize + t.Add(traeMaxPromos(id)) ' Agregamos a la lista las promos maximas permitidas (recurrente, cliente y promo). + invFijoXpromo.Initialize +' If thisLog Then LogColor($"pm=${pm}"$, Colors.Blue) + Private invDispParaPromo As Map = traemosInventarioDisponibleParaPromo(id) + If thisLog Then Log(">>>>> " & $"invDispParaPromo=${invDispParaPromo}"$) + Private prodsFijosPiezas As List = traeListFromPromo("P_PRODSFIJOS_PIEZAS", id) + Private idProdsFijos As List = traeListFromPromo("P_PRODSFIJOS", id) + Log($"${idProdsFijos},${prodsFijosPiezas}"$) + For p = 0 To idProdsFijos.Size -1 'Generamos una lista con las promos disponibles por producto (dividimos el inventario total entre las piezas requeridas). + Private thisInvDisp As Int = 0 + Log($"|${invDispParaPromo.Get("3800025096")}|"$) + Private tmpId As String = idProdsFijos.Get(p) + Log($"### ThisP = |${idProdsFijos.Get(p)}| -> |${invDispParaPromo.Get(tmpId)}| -> |${invDispParaPromo.Get(idProdsFijos.Get(p).As(String))}|"$) + If invDispParaPromo.Get(idProdsFijos.Get(p).As(String)) <> Null Then + thisInvDisp = invDispParaPromo.Get(idProdsFijos.Get(p).As(String)) + Log($"thisInvDisp = ${thisInvDisp}"$) + End If + If thisLog Then Log($"id=${idProdsFijos.Get(p)}, inv=${thisInvDisp}, pzas=${prodsFijosPiezas.Get(p)}"$) + If thisLog Then Log($"${(thisInvDisp / prodsFijosPiezas.Get(p))}"$) + Private x() As String = Regex.Split("\.", $"${(thisInvDisp / prodsFijosPiezas.Get(p))}"$) 'Separamos el resultado de la division por el punto decimal. + If thisLog Then Log(x(0)) + t.Add(x(0).As(Int)) 'Solo guardamos la parte del entero de la division. + Next + t.Sort(True) 'Ordenamos la lista para que en el lugar 0 este el resultao mas pequeño. + If thisLog Then LogColor($"prodsFijos=${idProdsFijos}"$, Colors.Blue) + If thisLog Then LogColor($"prodsFijosPiezasReq=${prodsFijosPiezas}"$, Colors.Blue) + If thisLog Then LogColor($"invFijoXpromo=${invFijoXpromo}"$, Colors.Blue) + If thisLog Then LogColor("Max promos de prodsFijos POR inventario = " & t.Get(0), Colors.red) +' LogColor(">>>>>> " & t.Get(0), Colors.red) + Return t.Get(0) 'Regresamos el resultado mas pequeño. +End Sub + +'Regresa cuantas promos alcanzan con los productos VARIABLES que hay en inventario. +'La cantidad de promos disponibles se calcula DESPUES de descontar los productos fijos, y si las +'promos por productos fijos llega al maximo, aunque se puedan mas de producos variables, solo se +'regresa el maximo por productos fijos. Ej. si las promos por variables es 10, pero el maximo por +'fijos es 5, entonces regresamos 5. +Sub revisaMaxPromosProdsVariablesPorInventario(pm As Map) As Int 'ignore + Private thisLog As Boolean = True + If thisLog Then Log("======================================================") + If thisLog Then Log("======================================================") + Private invFijoXpromo As Map + invFijoXpromo.Initialize + Private totalProdsVariablesDisponibles As Int = 0 + If thisLog Then LogColor($"pm=${pm}"$, Colors.Blue) + Private invDispParaPromo As Map = traemosInventarioDisponibleParaPromo(pm.Get("id")) + If thisLog Then Log($"invDispParaPromo=${invDispParaPromo}"$) + Private maxPromos As String = traeMaxPromos(pm) + Private maxPromosXFijos As Int = revisaMaxPromosProdsFijosPorInventario(pm) + Private idProdsVariables As List = pm.Get("prodsVariables") + Private prodsVariablesRequeridos As Int = pm.Get("prodsVariablesRequeridos") + Private prodsFijosPiezas As List = pm.Get("prodsFijosPiezas") + Private idProdsFijos As List = pm.Get("prodsFijos") + For p = 0 To idProdsFijos.Size -1 'Generamos mapa con los productos fijos y piezas requeridas por promo. + invFijoXpromo.Put(idProdsFijos.Get(p), prodsFijosPiezas.Get(p)) + Private idEsteProd As String = idProdsFijos.Get(p) + Private invEsteProd As Int = invDispParaPromo.Get(idEsteProd) + Private pzasReqEsteProd As Int = prodsFijosPiezas.Get(p) + If thisLog Then Log($"id=${idEsteProd}, inv=${invEsteProd}, pzas=${pzasReqEsteProd}"$) +' invDispParaPromo.Put( idEsteProd, (invEsteProd - (1)) ) + Next + If thisLog Then LogColor($"MaxPromos=${maxPromos}, promosXFijos=${maxPromosXFijos}"$, Colors.Blue) + If thisLog Then LogColor($"prodsFijos=${idProdsFijos}"$, Colors.Blue) + If thisLog Then LogColor($"prodsFijosPiezasReq=${prodsFijosPiezas}"$, Colors.Blue) + If thisLog Then LogColor($"prodsVariables=${idProdsVariables}${CRLF}Variables Req=${prodsVariablesRequeridos} "$, Colors.Blue) + If thisLog Then LogColor($"invFijoXpromo=${invFijoXpromo}"$, Colors.Blue) + If thisLog Then Log($"Prods variables disponibles = ${totalProdsVariablesDisponibles}"$) + Private maxPromosXVariables As Int = 0 + For x = 1 To maxPromosXFijos + If thisLog Then Log("=====================================================") + If thisLog Then Log("=====================================================") + For i = 0 To idProdsFijos.Size - 1 + If thisLog Then Log($"FIJO - ${idProdsFijos.Get(i)}, ${invDispParaPromo.Get(idProdsFijos.Get(i))} - ${prodsFijosPiezas.Get(i).As(Int)*(i+1)}"$) + invDispParaPromo.Put(idProdsFijos.Get(i), invDispParaPromo.Get(idProdsFijos.Get(i)).As(Int) - prodsFijosPiezas.Get(i).As(Int)*(i+1)) 'Restamos las piezas de los productos fijos del inventario disponible. + Next + If thisLog Then LogColor("Inv disponible despues de restar fijos = " & invDispParaPromo, Colors.Blue) + + totalProdsVariablesDisponibles = 0 + For i = 0 To idProdsVariables.Size - 1 'Obtenemos total de productos variables disponibes. + If invDispParaPromo.ContainsKey(idProdsVariables.Get(i)) Then + totalProdsVariablesDisponibles = totalProdsVariablesDisponibles + invDispParaPromo.Get(idProdsVariables.Get(i)) + End If + Next + 'Revisamos variables. + If thisLog Then Log($"Var disponibles - var requeridos : ${totalProdsVariablesDisponibles} - ${prodsVariablesRequeridos*x}"$) + totalProdsVariablesDisponibles = totalProdsVariablesDisponibles - (prodsVariablesRequeridos*x) + If thisLog Then Log("prodsVariables disponibles despues de promo = " & totalProdsVariablesDisponibles) + If totalProdsVariablesDisponibles < 0 Then Exit 'Ya no hay inventario disponible. + maxPromosXVariables = x + Next + 'Restamos fijos. +' LogColor("Max promos de prodsVariables POR inventario = " & maxPromosXVariables, Colors.red) + Return maxPromosXVariables +End Sub + + +'Regresa un mapa con el inventario disponible por producto para la promoción (desde la base de datos). +Sub traemosInventarioDisponibleParaPromo(promo As String) As Map 'ignore + Private c As Cursor + c = Starter.skmt.ExecQuery2("SELECT CAT_GP_ID, CAT_GP_ALMACEN FROM CAT_GUNAPROD2 WHERE CAT_GP_ID IN (select CAT_DP_IDPROD FROM CAT_DETALLES_PAQ WHERE CAT_DP_ID = ?)", Array As String(promo)) +' Private prodInv As Map +' prodInv.Initialize + Private prods As Map + prods.Initialize + If c.RowCount > 0 Then + For i=0 To c.RowCount -1 + c.Position=i + prods.Put(c.GetString("CAT_GP_ID"), c.GetString("CAT_GP_ALMACEN")) +' Log($"prod:${c.GetString("CAT_GP_ID")}, inventario:${c.GetString("CAT_GP_ALMACEN")}"$) + Next +' prodInv.Put("inventarios", prods) + End If + Return prods +End Sub + +'Resta los productos fijos del inventario de la promoción (mapa) y regresa un mapa con el nuevo inventario. +'Hay que darle como parametro un mapa (traePromo(promo)) con toda la informacion de la promocion. +'Regresa en el mapa la llave "resultado" que nos da "ok" o "No hay suficiente producto para la promocion". +Sub restaFijosPromo(idPromo As String, promoMap As Map) As Map 'ignore + Private thisLog As Boolean = True 'Si es verdadero, muestra los logs de este sub. + Private inventariosDisponiblesParaEstaPromo As Map = traemosInventarioDisponibleParaPromo(idPromo) 'Obtenemos un mapa con el inventario disponible para cada producto de la promocion desde la base de datos. + + + If thisLog Then LogColor(inventariosDisponiblesParaEstaPromo, Colors.red) + If thisLog Then LogColor("Inventario inicial antes de FIJOS: "&inventariosDisponiblesParaEstaPromo, Colors.Gray) 'Inventario inicial. + Private i As Int + Private prodsmap As Map = promoMap.Get("productos") 'Obtenemos un mapa con todos los productos de la promoción. + Private prodsFijos As List = traeListFromPromo("P_PRODSFIJOS", idPromo) 'Obtenemos un a lista con los productos fijos de la promoción. + If thisLog Then LogColor("ProdsFijos -> " & prodsFijos, Colors.red) + inventariosDisponiblesParaEstaPromo.Put("resultado", "No hay suficiente producto para la promocion.") 'Valor por default + Log($"Prods fijos requeridos ${prodsFijos.Size}"$) + If prodsFijos.Size = 0 Then inventariosDisponiblesParaEstaPromo.Put("resultado", "ok") 'Si no lleva prods fijos la promo, entonces ponemos FIJOS OK. + For p = 0 To prodsFijos.Size - 1 + Private t As String = prodsFijos.Get(p) 'Obtenemos el Id de este producto desde la lista de productos fijos. + Private p2 As Map = prodsmap.Get(t) 'Obtenemos un mapa con los datos de este producto (id, precio, almacen, tipo, piezas, etc.) + If thisLog Then Log($"T: ${t}, prod ${p2.Get("idProducto")}, piezas: ${p2.Get("piezas")}"$) 'Producto y piezas requeridas + If thisLog Then Log("inventariosDisponiblesParaEstaPromo="&inventariosDisponiblesParaEstaPromo) + If inventariosDisponiblesParaEstaPromo.ContainsKey(t) Then 'Si el mapa del inventario contiene el id del producto entonces ... + i = inventariosDisponiblesParaEstaPromo.get(t) 'Obtenemos del mapa el inventario de este producto. + Private nuevoInv As Int = NumberFormat2((i - promoMap.Get("prodsFijosPiezas").As(List).get(p)), 1, 0,0,False) + If thisLog Then Log($"Nuevo inventario de ${t}: ${i}-${promoMap.Get("prodsFijosPiezas").As(List).get(p)} = ${nuevoInv}"$) 'El nuevo inventario. + inventariosDisponiblesParaEstaPromo.Put(t, $"${nuevoInv}"$) 'Restamos del inventario las piezas requeridas para la promoción y guardamos el nuevo inventario en el mapa. + inventariosDisponiblesParaEstaPromo.Put("resultado", "ok") + Else 'Si en el mapa no esta el id del producto, entonces no tenemos inventario. + inventariosDisponiblesParaEstaPromo.Put("resultado", "No hay suficiente producto para la promocion.") + If thisLog Then LogColor("Sin suficiente inventario fijo: " & t, Colors.Blue) + Exit + End If + If i - p2.Get("piezas") < 0 Then + inventariosDisponiblesParaEstaPromo.Put("resultado", "No hay suficiente producto para la promocion.") 'Si el inventario de este producto sale negativo, quiere decir que no tenemos suficiente inventario para la promoción. + Exit + End If + Next + If thisLog Then LogColor("Inventario final despues de FIJOS: "&inventariosDisponiblesParaEstaPromo, Colors.blue) 'Inventario final. + Return inventariosDisponiblesParaEstaPromo +End Sub + +'Revisa si tenemos los productos variables requeridos para la promoción (mapa). +'Hay que darle como parametro un mapa (traePromo(promo)) con toda la informacion de la promocion. +Sub alcanzanLosVariablesParaPromo(promoMap As Map, inventarioSinFijos As Map) As Boolean 'ignore + Private thisLog As Boolean = False 'Si es verdadero, muestra los logs de este sub. + If thisLog Then LogColor("Inventario inicial: "&inventarioSinFijos, Colors.Gray) 'Inventario inicial. + Private totalProdsVariables As Int = 0 +' Private prodsmap As Map = promoMap.Get("productos") 'Obtenemos un mapa con todos los productos de la promoción. + Private prodsVariables As List = promoMap.get("prodsVariables") 'Obtenemos un a lista con los productos variables de la promoción. + For p = 0 To prodsVariables.Size - 1 + Private t As String = prodsVariables.Get(p) 'Obtenemos el Id de este producto desde la lista de productos fijos. + If inventarioSinFijos.ContainsKey(t) Then 'Si existe el producto en la lista del inventario, entonces ... + Private p2 As Int = inventarioSinFijos.Get(t) 'Obtenemos el inventario disponible este producto. + If thisLog Then Log($"prod ${t}, hay: ${p2}"$) 'Producto y piezas requeridas + totalProdsVariables = totalProdsVariables + p2 + End If + Next + If thisLog Then Log("Total prods variables=" & totalProdsVariables & ", requeridos=" & promoMap.Get("prodsVariablesRequeridos")) + Private res As Boolean = False + If totalProdsVariables >= promoMap.Get("prodsVariablesRequeridos") Then res = True 'Si el total de inventario de productos variables (totalProdsVariables) es mayor o igual a los productos requeridos entonces regresamos TRUE + Return res +End Sub + +'Regresa el numero máximo de promociones permitidas, tomando en cuenta recurrentes, clientes y maxPromos. +Sub traeMaxPromos(idPromo As String) As Int + Private thisLog As Boolean = True 'Si es verdadero, muestra los logs de este sub. + Private maxPromos As List + Private mp0, mp As String = "0" + maxPromos.Initialize + Private hccp As Cursor = db.ExecQuery($"select HCCP_CANT from HIST_CLIENTE_CANT_PROMOS where HCCP_CLIENTE = '${cliente}' and HCCP_PROMO = '${idPromo}'"$) + If thisLog Then LogColor("==== HISTORICO:"&traeInfoFromPromo("HISTORICO", idPromo), Colors.Red) +' If thisLog Then Log(pm) + + + If traeInfoFromPromo("HISTORICO", idPromo) = "1" Then maxPromos.Add(traeInfoFromPromo("P_MAXRECURRENTE", idPromo).As(Int)) 'Si hay historico, agregamos maxRecurrente + If traeInfoFromPromo("P_MAXPROMOS", idPromo) <> "null" Then maxPromos.Add(traeInfoFromPromo("P_MAXPROMOS", idPromo).As(Int)) 'Agregamos maxPromos + If traeInfoFromPromo("P_MAXXCLIENTE", idPromo) <> "null" Then maxPromos.Add(traeInfoFromPromo("P_MAXXCLIENTE", idPromo).As(Int)) 'Agregamos maxXcliente + If hccp.RowCount > 0 Then 'Agregamos promos HCCP + hccp.Position = 0 + maxPromos.Add(hccp.GetInt("HCCP_CANT")) + End If +' Log($"|${traeInfoFromPromo("HISTORICO", idPromo)}|${traeInfoFromPromo("P_MAXPROMOS", idPromo)}|${traeInfoFromPromo("P_MAXXCLIENTE", idPromo)}|"$) +' Log(maxPromos) + maxPromos.Sort(True) + If thisLog Then Log($">>>>> Max promos : ${maxPromos}"$) + mp = 0 + If maxPromos.Size > 0 Then + mp0 = maxPromos.Get(0) +' Log(mp0) + mp = mp0 - traePromosVendidas(idPromo) + If thisLog Then Log($"Max Promos (${mp0}) - promos vendidas (${(traePromosVendidas(idPromo)).As(Int)}) = ${mp}"$) + End If + Return mp 'Regresamos el numero mas pequeño de las opciones. +End Sub + +'Regresa la cantidad de promos que se le han vendido al cliente. +Sub traePromosVendidas(idPromo As String) As Int + Private c As Cursor + Private pv As Int = 0 + c=db.ExecQuery($"select sum(PE_CANT) as cuantas from PEDIDO where PE_PROID = '${idPromo}' and PE_CLIENTE = '${cliente}'"$) + If c.RowCount > 0 Then + c.Position = 0 + If c.GetString("cuantas") <> Null Then pv = c.GetString("cuantas") + End If + Return pv +End Sub + +Sub traeInfoFromPromo(col As String, idPromo As String) As String + Private res As String = "" + Private c As ResultSet = db.ExecQuery($"select ${col} from PROMOCIONES_INFO where P_ID = '${idPromo}'"$) +' Log($"select ${col} from PROMOCIONES_INFO where P_ID = '${idPromo}'"$) + Do While c.NextRow + res = c.GetString(col) + Loop + Return res +End Sub + +'Regresa una lista de la BD, en la BD se guarda como string y esta funcion la convierte en lista nuevamente. +Sub traeListFromPromo(col As String, promo As String) As List + Private res As List + Private s As String + Private c As ResultSet = db.ExecQuery($"select ${col} from PROMOCIONES_INFO where P_ID = '${promo}'"$) + Do While c.NextRow + s = c.GetString(col) + Loop + If s.StartsWith("[") And s.EndsWith("]") Then + Private j As JSONParser + j.Initialize(s) + res.Initialize2(j.NextArray) + Else + res.Initialize + End If + Return res +End Sub \ No newline at end of file diff --git a/B4A/Subs.bas b/B4A/Subs.bas index 4ecf79e..61538e2 100644 --- a/B4A/Subs.bas +++ b/B4A/Subs.bas @@ -1020,24 +1020,24 @@ Sub traePromo(promo As String, cliente As String) As Map If c.RowCount > 0 Then promoMap = CreateMap("id":promo, "maxXcliente":c.GetString("CAT_PA_MAXPROMCLIE"), "maxRecurrente":c.GetString("CAT_PA_MAXPROMREC"), "maxPromos":c.GetString("CAT_PA_MAXPROM")) '######### PROMOCIONES SEGMENTADAS ########## ' Si la promo esta en la lista, SOLO los clientes que la tengan la pueden ver. - Private ps As Cursor = Starter.skmt.ExecQuery($"select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}'"$) + Private ps As Cursor = Starter.skmt.ExecQuery($"select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${cliente}'"$) ' Log($"select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}'"$) Log($"PROMOS SEGMENTADAS DISPONIBLES: ${ps.RowCount}"$) If ps.RowCount > 0 Then ps.Position = 0 promoMap = CreateMap("id":promo, "maxXcliente":0, "maxRecurrente":0, "maxPromos":0) 'Si es segmentada la ponemos en cero, porque SOLO le debe de aparecer a ciertos clientes. - Log($">>> PROMO "${promo}" SEGMENTADA PARA EL CLIENTE ${ps.GetString("HCCP_CLIENTE")}"$) + If thisLog Then Log($">>> PROMO "${promo}" SEGMENTADA PARA EL CLIENTE ${ps.GetString("HCCP_CLIENTE")}"$) ' Select hccp_cliente As valido from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${traecliente}' Private ps2 As Cursor = Starter.skmt.ExecQuery($"Select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${traeCliente}' and HCCP_CANT > HCCP_CANT_VENDIDA"$) ' Log($"Select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${traeCliente}' and HCCP_CANT > HCCP_CANT_VENDIDA"$) - Log($"registros:${ps2.RowCount}"$) +' Log($"registros:${ps2.RowCount}"$) If ps2.RowCount > 0 Then ps2.Position = 0 - Log($"registros:${ps2.RowCount}, cliente: ${ps2.GetString("HCCP_CLIENTE")} cant:${ps2.GetString("HCCP_CANT")}"$) + If thisLog Then Log($"registros:${ps2.RowCount}, cliente: ${ps2.GetString("HCCP_CLIENTE")} cant:${ps2.GetString("HCCP_CANT")}"$) promoMap = CreateMap("id":promo, "maxXcliente":(ps2.GetString("HCCP_CANT")-ps2.GetString("HCCP_CANT_VENDIDA")), "maxRecurrente":ps2.GetString("HCCP_CANT"), "maxPromos":ps2.GetString("HCCP_CANT")) 'Si es segmentada SOLO le aparece a ciertos clientes. End If End If - Log(promoMap) + If thisLog Then Log(promoMap) ' ########## TERMINA PROMOS SEGMENTADAS ########## c = Starter.skmt.ExecQuery("Select count(*) as hist from HIST_PROMOS where HP_CLIENTE = '"& cliente & "' and HP_CODIGO_PROMOCION = '" & promo & "'") 'Revisamos si hay historico de la promoción. c.Position = 0 @@ -1074,6 +1074,7 @@ Sub traePromo(promo As String, cliente As String) As Map promoMap.Put("prodsVariablesCant", prodsVariables.Size) promoMap.Put("prodsVariablesPrecios", prodsVariablesPrecios) promoMap.Put("resultado", "ok") + Else promoMap.Put("resultado", "No hay datos de la promoción.") End If @@ -1231,6 +1232,9 @@ Sub procesaPromocion(idPromo As String, cliente As String) As Map 'ignore If thisLog Then LogColor($"********* Iniciamos revision de Promo ${idPromo} *********"$, Colors.red) 'Obtenemos el mapa con toda la info de la promoción. Private pm As Map = traePromo(idPromo, cliente) + + B4XPages.MainPage.productos.promosC.traePromo(idPromo, cliente) + If thisLog Then LogColor(pm, Colors.Blue) ' If thisLog Then LogColor("|" & pm.Get("maxPromos") & "|", Colors.Blue) ' Log("|"&revisaMaxPromosProdsFijosPorInventario(pm)&"|")