Bueno, la cosa es bastante sencilla.
Cuando hay varias reglas, hay que verificarlas antes de totalizar y las que se verifican justo al totalizar deben anotarse, para ello pueden establecerse variables que determina si una regla se usa o no y en consecuencia después tenerlas en cuenta. Otras reglas como esa que permite regalar el 5º artículo si se llevan 4, puede tratarse al instante, o justo antes de totalizar, yo te he puesto un ejemplo donde esta regla se lleva a cabo (el valor que lo determina) sobre la marcha y al totalizar se verifica dicho valor, las otras reglas se verifican justo al totalizar...
Hay cierta ambigüedad en el enunciado de las reglas, por ejemplo 2 o más reglas son acumulables ? yo he supuesto que si, porque nada dice lo contrario y en cuento a la regla de que si comprar 4 artículos se regala 1 adicional yo lo he interpretado como que compras 4 unidades del mismo artículo... estas ambigüedades tu las puedes conocer con exactitud, pero nadie más, de modo que tal vez tengas que corregir parte del código para que se ajuste a lo que quieres. Tampoc has determinado que hacer cuando alguien compra los 5 artículos, yo he optado por regalar 1 unidad (descontar el valor de su precio) de aquel de menor precio_unitario de los 5 artículos
El caso debe servirte como ejemplo para cualquier número de reglas, por complejas que estas sean, basta definirlas correcta y completamente y aplicarlas ordenadamente. No se debe tener prisas en obtener un total, este vendrá al final sólo cuando se hayan verificado todas las reglas...
He cambiado los nombres de los controles, porque en muchos casos ( y este es uno de ellos) meterlos en una matrizo colección simplifica y aclara elcódigo.
Los artículos forman una matriz de nombre 'CheArticulos(n)' donde n es el índice del artículo de 0 a 4 verticalmente, del mismo modo para el texto de precios se le ha llamado a la matriz de esos textos 'txtPrecioUnidad(n), ídem para los contrles de texto de las cantidades. txtCantidades(n).
Los textos de precios y el de total están bloqueados, se supone que ese valor se modifica por otro lado, aquí son de sólo lectura, para bloquearlos se utiliza la propiedad locked=true de dichos controles, para esclarecer que no cambiables se les cambió el color de fondo a un amarillo tenúe. Las cantidades sempre valen 0, están desactivados, sólo seactivan cuando su checkox de artículo corresopondiente es activado, cuando se desactiva su valor se pone a 0. El frame que contiene todo estos controles de texto se ha renombrado a: 'FraAdquirir'
Se ha añadido un frame, que detalla las promociones que se aplican, yaunque no se ve, cuando se aplica un descuento, aparece un label reflejando cuanto es la cantidad del descuento...
finalmente se han reordenado los contrles para tener mejor presencia. Este frame está desactivado (es de sólo lectura) .
El aspecto final se puede observar en la imagen.
el código (está comentado, pero...) se describe someramente en los siguientes bloques:
Declaraciones...
Dim Conexion As New ADODB.Connection
Dim RsArticulos As New ADODB.Recordset
Private Totales As Single
Private ArtiElegidos As Byte ' mantiene una cuenta de los diferentes artículos elegidos.
Private ArtiNocomputar As Boolean ' al activarse no debe ejecutarse elcódigo asociado...
Private RegaloVariedad As Boolean ' se aplica regalo del 5º ?
Private RegalarArticuloX As single ' señala que artículo se regala gratis (su precio). este valor se descuenta del total a pagar.
Private RegaloFidelidad(0 To 4) As Boolean ' se aplica regalo 1 adicional del artículo de al menos 4 ?
Private AplicarDescuento As Boolean ' se aplica un descuento ?
Private DescuentoPorcentaje As Single ' porcentaje de descuento que se aplica, se supone que esto se establece desde un panel de administración, aquí se especifica en el load.
Private VolumenParaDescuento As Single ' cantidad que determina que una vez alcanzada se aplica el descuento.
Código para los controles checkbox.... debe notarse que forman una matriz, véase el parámetro index, que se usa tanto para los checkbox como para los textos de precio y cantidad
Cada índice de la matriz checkbox cocunerda con la matriz de textbox de precios y de cantidades... obviamente.
' contabiliza cuantos diferentes artículos se adquieren, además
Private Sub CheArticulos_Click(Index As Integer)
Dim uso As Boolean
' sólo se ejecuta el código cuando no se está totalizando
If ArtiNocomputar = False Then
uso = (CheArticulos(Index).Value = 1)
txtPrecioUnidad(Index).Enabled = uso
txtCantidades(Index).Enabled = uso
If uso = True Then
ArtiElegidos = ArtiElegidos + (2 ^ Index) ' se recuerda que: 2 ^0= 1
txtCantidades(Index).BackColor = vbWhite
Else
ArtiElegidos = ArtiElegidos - (2 ^ Index)
txtCantidades(Index).Text = "0" ' DEBE BORRARSE para no alterar la suma al totalizar, por supuesto podría no borrarse si al totalizarse se verifica si el artículo está activado, pero es hacerlo más complicado y se presta a confusión.
txtCantidades(Index).BackColor = 14737632 'gris, desactivado
End If
End If
End Sub
Código del botón borrar, el botón se ha renombrado
' borra todo lo necesario, equivale a resetear
Private Sub cmdBorrar_Click()
Dim k As Byte
' borramos cantidades y desactivamos artículos elegidos
For k = 0 To 4
CheArticulos(k).Value = 0
txtCantidades(k).Text = "0"
txtCantidades(k).Enabled = False ' desactivado
txtCantidades(Index).BackColor = 14737632 'gris
Next
ArtiElegidos = 0
' borramos totales y descuento
TxtTotales.Text = "0.00"
Totales = 0
LabDescuento.Caption = "" ' este lab está en el frame de gratificaciones...
' borramos todas las promociones
For k = 0 To 2
ChePromociones(k).Value = 0
Next
For k = 0 To 4
RegaloFidelidad(k) = False
Next
RegaloVariedad = False
AplicarDescuento = False
RegalarArticuloX = 0
' se activa de nuevo la seleccion de adquisiciones.
FraAdquirir.Enabled = True
' se activa de nuevo computar cuando se marquen artículos.
ArtiNocomputar = False
End Sub
Codigo del boton total... se ha renombrado el botón
Aquí se realiza casi todo el código de cálculo...
Los controles chePromociones(n) ... están el frame gratiificaciones... junto con un label (labDescuento)
' aquí primero se verifican si se cumple alguna de las reglas.
' hay una 4ª regla deducible que señala si las promociones son adicionales o no. Es decir si puede darse más de 1 a la vez o no.
' como no se indica nada en contra se supone que sí.
Private Sub CmdTotalizar_Click()
Dim k As Byte, cantidad As Integer, precio As Single, Descuento As Single
' desactivamos posibilidades de cambios antes de empezar a calcular... Se activa de nuevo al borrar.
FraAdquirir.Enabled = False
ArtiNocomputar = True ' los cambios aplicados ahora al marcar artículos no ejecutan el código asociado en los checkbox...
' 1º determinar si se aplica regalo del 5º (regalo por variedad).
' 1 + 2 + 4 + 8 + 16 =31, el regalo se aplica cuando: ArtiElegidos = 31 - sólo 1 de esos sumandos
' Casos posibles para 5 artículos: 31-16=15 ;; 31-8=23 ;; 31-4=27 ;; 31-2=29 ;; 31-1=30
' y también si se eligió los 5 en cuyo caso se regala el de menor cuantía ? 31-0=31
Select Case ArtiElegidos
Case 0 ' no hay adquisiciones
Call cmdBorrar_Click
Exit Sub
Case 15, 23, 27, 29, 30, 31 ' se eligieron 4 artículos (o 5)
RegaloVariedad = True
ChePromociones(1).Value = 1
If ArtiElegidos < 31 Then ' si se eleigieron 4 artículos, regalar el 5º
Select Case ArtiElegidos
Case 15: k = 4 ' activamos el artículo 4 que es el que falta
Case 23: k = 3
Case 27: k = 2
Case 29: k = 1
Case 30: k = 0
End Select
' se regala este artículo. el 'K' avo de la matrizde artículos.
CheArticulos(k).Value = 1 'lo marcamos,
txtCantidades(k) = "1" ' señalamos en cantidad 1
RegalarArticuloX = Val(txtPrecioUnidad(k).Text) ' tomamos el valor que al totalizar se cuenta, pero al final se debe descontar.
Else ' el que adquiere compra todos los artículos (al menos 1 cantidad), se regala el de menor cuantía de los existentes...
' buscamos el precio de menor cuantía de los 5 artículos.
RegalarArticuloX = Val(txtPrecioUnidad(0).Text)
For k = 1 To 4
If Val(txtPrecioUnidad(k).Text) < RegalarArticuloX Then
RegalarArticuloX = Val(txtPrecioUnidad(k).Text)
End If
Next
End If
Case Else ' no hay promoción de regalar un 5º por tener 4 artículos.
RegaloVariedad = False
ChePromociones(1).Value = 0
RegalarArticuloX = 0
End Select
' 2º Determinar si se puede hacer un regalo por fidelidad
' esto se mira revisando la cantidad para cada artículo si tiene al menos 4 se le regala 1 más (se supone que por cada artículo que cumpla dicho requisito)
For k = 0 To 4
If Val(txtCantidades(k).Text) > 3 Then
RegaloFidelidad(k) = True ' activamos para tenerlo en cuenta al totalizar,
ChePromociones(2).Value = 1 ' marcamos la promoción
txtCantidades(k).Text = Val(txtCantidades(k).Text) + 1 ' sumamos 1 para asegurarse que sea entregado...
End If
Next
' 3º Descuento por volumen: (se suponen que las promociones son acumulables), este paso serealiza en 2
' en el primero se tiene calcula el total adquirido originalmente por el comprador + el regalo del 5º (si existe se desceunta al final).
' en el segundo se comprueba si se aplica el descuento por volummmmen de compra.
' 3ºA) totaliza las cantidades, descontando regalos_por_Fidelidad (la cantidad ya se sumó pero es gratis).
For k = 0 To 4
cantidad = Val(txtCantidades(k).Text)
precio = Val(txtPrecioUnidad(k).Text)
If RegaloFidelidad(k) = True Then ' aquí hay un regalo por variedad, se descuenta una unidad.
cantidad = cantidad - 1
End If
If cantidad > 0 Then
' total = total + (precio_1 * cantidad_del_Artículo)
Totales = Totales + (precio * cantidad)
End If
Next
' 1ºB, aplicar el descuento del 5º artículo, sino existe este valor es 0 y por tanto no cambia.
' NOTA: este regalo no puede constar como 'factura total', porque es regalado, no entra en factura ni en totales, y por tanto su valor no entra en desceuntos.
Totales = Totales - RegalarArticuloX
' se supone que las promociones son acumulables.
' 3ºB se verifica si se cumple la 3ª promoción
If Totales > VolumenParaDescuento Then
Descuento = ((Totales / 100) * DescuentoPorcentaje)
Totales = Totales - Descuento
AplicarDescuento = True
ChePromociones(0).Value = 1
Else
AplicarDescuento = False
ChePromociones(0).Value = 0
End If
' marcamos el valor total, las promociones aplicadas quedan reflejadas en el frame gratificaciones...
TxtTotales.Text = Totales
LabDescuento.Caption = "Descontado: " & CStr(Descuento)
End Sub
Finalmente el código de carga y fin del formulario (esta parte está sin terminar, te lo señalo con comentarios).
Private Sub Form_Load()
Conexion.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path & "DataAlmacen.mdb;Persist Security Info=False;Jet OLEDB:Database;"
Conexion.Open
RsArticulos.Open "select * from Artilculos ", Conexion
Call MostrarPrecios
DescuentoPorcentaje = 8 ' 8% es el valor de descuento.
VolumenParaDescuento = 150 ' es el valor que si se alcanza al totalizar, determina que se aplica el descuento.
End Sub
' los precios de los artículos están bloqueados, porque deben ser de sólo lectura.
' propiedad locked =true
' también está bloqueado preciototal
' los bloqueados se les cambió el color defondo, para expresar su valor no alterable desde interfaz de usuario.
Private Sub MostrarPrecios()
txtPrecioUnidad(0).Text = RsArticulos.Fields("Zapatillas").Value
txtPrecioUnidad(1).Text = RsArticulos.Fields("T-Shirts").Value
txtPrecioUnidad(2).Text = RsArticulos.Fields("Pantalones").Value
txtPrecioUnidad(3).Text = RsArticulos.Fields("Zapatos").Value
txtPrecioUnidad(4).Text = RsArticulos.Fields("Gorras").Value
End Sub
Private Sub cmdSalir_Click()
' pedir confirmación
' cerrar la base de datos antes de salir
End ' end no dispara el evento queryunload
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
' confirmar si se desea salir...
' confirmar si se descartan cambios y cerrar base de datos
End Sub
No hay código para el botón guardar.
Debes revisar el código, ya que sólo lo he probado por encima y quizás necesite algún ajuste o haya tenido algún despiste...
Si algo no te queda claro, pregunta.