mirror of
https://github.com/KeymonSoft/Kelloggs_v4.git
synced 2026-04-17 18:26:11 +00:00
379 lines
16 KiB
QBasic
379 lines
16 KiB
QBasic
B4A=true
|
|
Group=Default Group
|
|
ModulesStructureVersion=1
|
|
Type=Class
|
|
Version=12.8
|
|
@EndOfDesignText@
|
|
'Class module: C_Promociones
|
|
Sub Class_Globals
|
|
Private sql As SQL
|
|
' Referencia a tu clase de Trade Spending (ajusta el tipo si se llama diferente)
|
|
Private ts As Object ' Lo dejo como Object para que no te marque error si no has copiado esa clase aun
|
|
|
|
' Variable local para el cliente actual (para no depender de Subs.traeCliente)
|
|
Private mClienteActual As String
|
|
|
|
End Sub
|
|
|
|
' Inicializa la clase.
|
|
' db: La conexión SQL (Starter.skmt)
|
|
' tradeSpending: La instancia de tu clase de TradeSpending (B4XPages.MainPage.promos.ts)
|
|
Public Sub Initialize(db As SQL, tradeSpendingInstance As Object)
|
|
sql = db
|
|
ts = tradeSpendingInstance
|
|
End Sub
|
|
|
|
' =============================================================================
|
|
' CONTROLADOR PRINCIPAL: ORQUESTADOR DE VALIDACIONES
|
|
' =============================================================================
|
|
Public Sub procesaPromocion(idPromo As String, cliente As String) As Map
|
|
Private thisLog As Boolean = True 'Si es verdadero, muestra los logs de este sub.
|
|
Private inicioContador As String = DateTime.Now
|
|
Private mp As Int = 0
|
|
|
|
If thisLog Then LogColor($"****************************************************************"$, Colors.RGB(142,0,255))
|
|
If thisLog Then LogColor($"********* Iniciamos revision de Promo ${idPromo} *********"$, Colors.RGB(142,0,255))
|
|
If thisLog Then LogColor($"****************************************************************"$, Colors.RGB(142,0,255))
|
|
|
|
Try
|
|
Private pm As TPromoLegacy = TraePromo(idPromo, cliente)
|
|
If thisLog Then LogColor(pm, Colors.Blue)
|
|
|
|
Private maxPromosXprodsFijos As Int = RevisaMaxPromosProdsFijos(pm)
|
|
If maxPromosXprodsFijos < 1 Then pm.Resultado = "0"
|
|
|
|
If thisLog Then LogColor($"***********************************************************************"$, Colors.Blue)
|
|
LogColor($"*** PROMOS DISPONIBLES X PRODS FIJOS (${idPromo}) = ${maxPromosXprodsFijos} ***"$, Colors.Blue)
|
|
If thisLog Then LogColor($"***********************************************************************"$, Colors.Blue)
|
|
|
|
If pm.Resultado = "ok" Then 'Si encontramos la promoción, entonces ...
|
|
mp = TraeMaxPromos(pm)
|
|
If mp < 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
|
|
|
|
Private inventarioSinFijos As Map = restaFijosPromo(pm)
|
|
If thisLog Then LogColor("inventariosfijos="&inventarioSinFijos, Colors.Magenta)
|
|
|
|
If inventarioSinFijos.Get("resultado") = "ok" Then
|
|
Private pv As Boolean = alcanzanLosVariablesParaPromo(pm, inventarioSinFijos)
|
|
|
|
If thisLog Then LogColor($"****************************************************"$, Colors.Blue)
|
|
If thisLog Then LogColor($"***** ¿ALCANZAN LOS VARIABLES? ==> ${IIf(pv, "SI", "NO")} *****"$, Colors.Blue)
|
|
If thisLog Then LogColor($"****************************************************"$, Colors.Blue)
|
|
|
|
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
|
|
|
|
LogColor("TIEMPO DE PROCESO ESTA PROMO: " & ((DateTime.Now-inicioContador)/1000), Colors.Red)
|
|
|
|
Catch
|
|
Log($"Promo ${idPromo} mal configurada"$)
|
|
ToastMessageShow($"Promo ${idPromo} mal configurada"$, True)
|
|
Log(LastException)
|
|
Return CreateMap("status":"ko", "mp":Null)
|
|
End Try
|
|
End Sub
|
|
|
|
' =============================================================================
|
|
' RUTINA PRINCIPAL: ARMA LA ESTRUCTURA (Clon de Subs.traePromo)
|
|
' =============================================================================
|
|
Public Sub TraePromo(promo As String, cliente As String) As TPromoLegacy
|
|
mClienteActual = cliente ' Guardamos el cliente para uso interno
|
|
|
|
Dim t As TPromoLegacy
|
|
t.Initialize
|
|
|
|
' Inicialización de Listas y Mapas (CRÍTICO para evitar Nulls)
|
|
t.ProdsFijos.Initialize
|
|
t.ProdsFijosPiezas.Initialize
|
|
t.ProdsFijosPrecios.Initialize
|
|
t.ProdsVariables.Initialize
|
|
t.ProdsVariablesPrecios.Initialize
|
|
t.Productos.Initialize
|
|
t.Tipos.Initialize
|
|
|
|
t.Id = promo
|
|
t.MaxXCliente = 0
|
|
t.MaxRecurrente = 0
|
|
t.MaxPromos = 0
|
|
|
|
' --- 1. LECTURA GENERAL ---
|
|
Dim c As Cursor = sql.ExecQuery("Select * from promos_comp where cat_pa_id = '"& promo&"'")
|
|
If c.RowCount > 0 Then
|
|
c.Position = 0
|
|
t.MaxXCliente = c.GetString("CAT_PA_MAXPROMCLIE")
|
|
t.MaxRecurrente = c.GetString("CAT_PA_MAXPROMREC")
|
|
t.MaxPromos = c.GetString("CAT_PA_MAXPROM")
|
|
End If
|
|
c.Close
|
|
|
|
' --- 2. SEGMENTACIÓN ---
|
|
Dim ps As Cursor = sql.ExecQuery($"select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}'"$)
|
|
If ps.RowCount > 0 Then
|
|
' Es segmentada -> Bloqueamos por defecto
|
|
t.MaxXCliente = "0"
|
|
t.MaxRecurrente = "0"
|
|
t.MaxPromos = "0"
|
|
|
|
Dim ps2 As Cursor = sql.ExecQuery($"Select * from HIST_CLIENTE_CANT_PROMOS where HCCP_PROMO = '${promo}' and HCCP_CLIENTE = '${cliente}' and HCCP_CANT > HCCP_CANT_VENDIDA"$)
|
|
If ps2.RowCount > 0 Then
|
|
ps2.Position = 0
|
|
t.MaxXCliente = (ps2.GetInt("HCCP_CANT") - ps2.GetInt("HCCP_CANT_VENDIDA"))
|
|
t.MaxRecurrente = ps2.GetString("HCCP_CANT")
|
|
t.MaxPromos = ps2.GetString("HCCP_CANT")
|
|
End If
|
|
ps2.Close
|
|
End If
|
|
ps.Close
|
|
|
|
' --- 3. HISTÓRICO ---
|
|
Dim siHistorico As String = "0"
|
|
c = sql.ExecQuery("Select count(*) as hist from HIST_PROMOS where HP_CLIENTE = '"& cliente & "' and HP_CODIGO_PROMOCION = '" & promo & "'")
|
|
c.Position = 0
|
|
If c.GetInt("hist") > 0 Then siHistorico = "1"
|
|
t.Historico = siHistorico
|
|
c.Close
|
|
|
|
' --- 4. DETALLES Y PRODUCTOS ---
|
|
c = sql.ExecQuery("Select * from CAT_DETALLES_PAQ where CAT_DP_ID = '"& promo & "'")
|
|
If c.RowCount > 0 Then
|
|
t.Resultado = "ok"
|
|
For i = 0 To c.RowCount -1
|
|
c.Position = i
|
|
Dim idProd As String = c.GetString("CAT_DP_IDPROD")
|
|
|
|
' Llenamos el mapa de productos (igual que el original para compatibilidad)
|
|
t.Productos.Put(idProd, CreateMap("idProducto":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")))
|
|
t.Tipos.Put(idProd, c.GetString("CAT_DP_TIPO"))
|
|
|
|
If c.GetString("CAT_DP_TIPO") = "0" Then
|
|
t.ProdsFijos.Add(idProd)
|
|
t.ProdsFijosPrecios.Add(c.GetString("CAT_DP_PRECIO"))
|
|
t.ProdsFijosPiezas.Add(c.GetString("CAT_DP_PZAS"))
|
|
End If
|
|
If c.GetString("CAT_DP_TIPO") = "1" Then
|
|
t.ProdsVariables.Add(idProd)
|
|
t.ProdsVariablesPrecios.Add(c.GetString("CAT_DP_PRECIO"))
|
|
End If
|
|
Next
|
|
Else
|
|
t.Resultado = "No hay datos de la promoción."
|
|
t.MensajeError = "Sin detalles"
|
|
End If
|
|
c.Close
|
|
|
|
' --- 5. VARIABLES REQUERIDAS ---
|
|
c = sql.ExecQuery("Select CAT_GP_STS, CAT_GP_NOMBRE from CAT_GUNAPROD2 where CAT_GP_ID = '"& promo & "'")
|
|
If c.RowCount > 0 Then
|
|
c.Position = 0
|
|
t.ProdsVariablesRequeridos = c.GetInt("CAT_GP_STS")
|
|
t.Descripcion = c.GetString("CAT_GP_NOMBRE")
|
|
Else
|
|
t.ProdsVariablesRequeridos = 0
|
|
End If
|
|
c.Close
|
|
|
|
Return t
|
|
End Sub
|
|
|
|
' =============================================================================
|
|
' LÓGICA DE CÁLCULO 1: FIJOS (Clon de Subs.revisaMaxPromosProdsFijosPorInventario)
|
|
' =============================================================================
|
|
Public Sub RevisaMaxPromosProdsFijos(pm As TPromoLegacy) As Int
|
|
Dim tLista As List
|
|
tLista.Initialize
|
|
|
|
' 1. Agregamos el máximo configurado
|
|
tLista.Add(TraeMaxPromos(pm))
|
|
|
|
' 2. Obtenemos inventario real
|
|
Dim invDispParaPromo As Map = TraemosInventarioDisponibleParaPromo(pm.Id)
|
|
|
|
Dim prodsFijosPiezas As List = pm.ProdsFijosPiezas
|
|
Dim idProdsFijos As List = pm.ProdsFijos
|
|
Dim idProdsFijosPrecios As List = pm.ProdsFijosPrecios
|
|
|
|
' 3. Iteramos sobre los fijos
|
|
For p = 0 To idProdsFijos.Size -1
|
|
Dim thisInvDisp As Int = 0
|
|
If invDispParaPromo.Get(idProdsFijos.Get(p)) <> Null Then
|
|
thisInvDisp = invDispParaPromo.Get(idProdsFijos.Get(p))
|
|
End If
|
|
|
|
Dim pzasReq As Int = prodsFijosPiezas.Get(p)
|
|
|
|
If pzasReq > 0 Then
|
|
Dim division As Double = thisInvDisp / pzasReq
|
|
Dim x() As String = Regex.Split("\.", $"${division}"$)
|
|
tLista.Add(x(0).As(Int))
|
|
|
|
' --- AQUI ESTA TU CAMBIO (DIRECTO Y SIN DOLOR) ---
|
|
' Nota: Cambié pm.Get("id") por pm.Id porque ahora es un Type
|
|
|
|
Dim maxTS As Int = B4XPages.MainPage.promos.ts.traeBonificacionesMaximas("bonificaciones", mClienteActual, idProdsFijos.Get(p), pzasReq, idProdsFijosPrecios.Get(p), pm.Id)
|
|
|
|
tLista.Add(maxTS)
|
|
' -------------------------------------------------
|
|
|
|
Else
|
|
Log($"Promo ${pm.Id} mal configurada (0 piezas requeridas en producto fijo)"$)
|
|
ToastMessageShow($"Promo ${pm.Id} mal configurada"$, True)
|
|
tLista.Add(0)
|
|
End If
|
|
Next
|
|
|
|
tLista.Sort(True)
|
|
Return tLista.Get(0)
|
|
End Sub
|
|
|
|
' =============================================================================
|
|
' LÓGICA DE CÁLCULO 2: MÁXIMOS (Clon de Subs.traeMaxPromos)
|
|
' =============================================================================
|
|
Public Sub TraeMaxPromos(pm As TPromoLegacy) As Int
|
|
Dim maxPromos As List
|
|
maxPromos.Initialize
|
|
|
|
' A. Histórico del Cliente (HCCP)
|
|
Dim hccp As Cursor = sql.ExecQuery($"select HCCP_CANT from HIST_CLIENTE_CANT_PROMOS where HCCP_CLIENTE = '${mClienteActual}' and HCCP_PROMO = '${pm.Id}'"$)
|
|
If hccp.RowCount > 0 Then
|
|
hccp.Position = 0
|
|
maxPromos.Add(hccp.GetInt("HCCP_CANT"))
|
|
End If
|
|
hccp.Close
|
|
|
|
' B. Trade Spending Variables
|
|
If ts <> Null Then
|
|
Dim maxPromosXDescPV As String = B4XPages.MainPage.promos.ts.maxPromosPorProdsVariables(pm.ProdsVariables, pm.Id)
|
|
maxPromos.Add(maxPromosXDescPV.As(Int))
|
|
End If
|
|
|
|
' C. Límites Generales
|
|
If pm.Historico = "1" And pm.MaxRecurrente <> "null" Then maxPromos.Add(pm.MaxRecurrente.As(Int))
|
|
If pm.MaxPromos <> "null" Then maxPromos.Add(pm.MaxPromos.As(Int))
|
|
If pm.MaxXCliente <> "null" Then maxPromos.Add(pm.MaxXCliente.As(Int))
|
|
|
|
maxPromos.Sort(True)
|
|
|
|
Dim mp As Int = 0
|
|
If maxPromos.Size > 0 Then
|
|
Dim mp0 As Int = maxPromos.Get(0)
|
|
' Restamos lo ya vendido
|
|
mp = mp0 - TraePromosVendidas(pm.Id, mClienteActual)
|
|
End If
|
|
|
|
Return mp
|
|
End Sub
|
|
|
|
' =============================================================================
|
|
' LÓGICA DE CÁLCULO 3: RESTA INVENTARIO FIJO (Clon de Subs.restaFijosPromo)
|
|
' =============================================================================
|
|
Public Sub restaFijosPromo(pm As TPromoLegacy) As Map
|
|
Private thisLog As Boolean = False 'Si es verdadero, muestra los logs de este sub.
|
|
Private inventariosDisponiblesParaEstaPromo As Map = TraemosInventarioDisponibleParaPromo(pm.Id) '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 = pm.productos 'Obtenemos un mapa con todos los productos de la promoción.
|
|
Private prodsFijos As List = pm.ProdsFijos 'Obtenemos una 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
|
|
|
|
If thisLog Then 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 - pm.ProdsFijosPiezas.Get(p)), 1, 0,0,False)
|
|
If thisLog Then Log($"Nuevo inventario de ${t}: ${i}-${pm.ProdsFijosPiezas.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
|
|
|
|
' =============================================================================
|
|
' LÓGICA DE CÁLCULO 4: VARIABLES (Clon de Subs.alcanzanLosVariablesParaPromo)
|
|
' =============================================================================
|
|
Public Sub alcanzanLosVariablesParaPromo(pm As TPromoLegacy, inventarioSinFijos As Map) As Boolean
|
|
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 prodsVariables As List = pm.ProdsVariables 'Obtenemos la 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=" & pm.ProdsVariablesRequeridos)
|
|
|
|
Private res As Boolean = False
|
|
If totalProdsVariables >= pm.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
|
|
|
|
' =============================================================================
|
|
' HELPERS PRIVADOS (Para hacer la clase portable sin depender de Subs.bas)
|
|
' =============================================================================
|
|
|
|
Private Sub TraePromosVendidas(promo As String, cliente As String) As Int
|
|
Dim c As Cursor
|
|
Dim pv As Int = 0
|
|
c = sql.ExecQuery($"select sum(PE_CANT) as cuantas from PEDIDO where PE_PROID = '${promo}' and PE_CLIENTE = '${cliente}'"$)
|
|
If c.RowCount > 0 Then
|
|
c.Position = 0
|
|
If c.GetString("cuantas") <> Null Then pv = c.GetInt("cuantas")
|
|
End If
|
|
c.Close
|
|
Return pv
|
|
End Sub
|
|
|
|
Private Sub TraemosInventarioDisponibleParaPromo(promo As String) As Map
|
|
Dim c As Cursor
|
|
c = sql.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))
|
|
Dim 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"))
|
|
Next
|
|
End If
|
|
c.Close
|
|
Return prods
|
|
End Sub |