En esta sección ya daremos el último paso para guardar la factura, en este caso nos falta guardar en la tabla ventas, luego descontar de inventario los productos y agregar al Kardex el movimiento.
Pero antes vamos a agregar el código que falta al llenar LlenarGridProductos
Impuesto = CCur(msGrid.TextMatrix(Filas, 7)) ' If G_Empresa_Regimen = "Común" And Impuesto > 0 Then ' TotalImpuesto = TotalImpuesto + Impuesto ' End If
El Procedimiento completo quedaría de la siguiente manera, dejo marcada las lineas nuevas con la palabra “Nueva”:
Sub LlenarGridProductos() Dim Sql As String Dim Columnas As Integer Columnas = 9 Sql = "SELECT tblDetalle_Venta.Id_detalle, tblDetalle_Venta.IdProducto, tblProductos.CodigoPro, tblProductos.NombrePro, tblDetalle_Venta.Cantidad_dv, tblDetalle_Venta.P_Venta_dv, tblDetalle_Venta.Impuesto_dv, 0 as Subtotal, tblDetalle_Venta.Descuento_dv " _ & " FROM tblProductos INNER JOIN tblDetalle_Venta ON tblProductos.IdProducto = tblDetalle_Venta.IdProducto WHERE tblDetalle_Venta.Num_VentaTemp = " & ConsecutivoTemp Call LlenarGrid(msGrid, Sql, Columnas) msGrid.ColWidth(0) = 0 msGrid.ColWidth(1) = 0 'ID msGrid.ColWidth(2) = 0 'item msGrid.ColWidth(3) = 900 'codigo msGrid.ColWidth(4) = 4300 'nombre msGrid.ColWidth(5) = 800 'cantidad msGrid.ColWidth(6) = 1300 'preciov msGrid.ColWidth(7) = 1300 'imp msGrid.ColWidth(8) = 1300 'subtotal msGrid.ColWidth(9) = 1300 'Desc msGrid.TextMatrix(0, 2) = "IdPro" msGrid.TextMatrix(0, 3) = "Código" msGrid.TextMatrix(0, 4) = "Nombre Producto" msGrid.TextMatrix(0, 5) = "Cant" msGrid.TextMatrix(0, 6) = "Precio V" msGrid.TextMatrix(0, 7) = "Impuesto" msGrid.TextMatrix(0, 8) = "Subtotal" msGrid.TextMatrix(0, 9) = "Descuento" msGrid.ColAlignment(5) = flexAlignCenterCenter TotalVenta = 0 TotalDescuento = 0 TotalImpuesto = 0 For Filas = 1 To msGrid.Rows - 1 Cantidad = msGrid.TextMatrix(Filas, 5) PrecioVp = CCur(msGrid.TextMatrix(Filas, 6)) DescuentoP = CCur(msGrid.TextMatrix(Filas, 9)) SubTotal = (Cantidad * PrecioVp) - DescuentoP Impuesto = CCur(msGrid.TextMatrix(Filas, 7)) ' Nueva If G_Empresa_Regimen = "Común" And Impuesto > 0 Then ' Nueva TotalImpuesto = TotalImpuesto + Impuesto ' Nueva End If ' Nueva msGrid.TextMatrix(Filas, 6) = Format(msGrid.TextMatrix(Filas, 6), "currency") msGrid.TextMatrix(Filas, 7) = Format(msGrid.TextMatrix(Filas, 7), "currency") msGrid.TextMatrix(Filas, 8) = Format(SubTotal, "currency") msGrid.TextMatrix(Filas, 9) = Format(msGrid.TextMatrix(Filas, 9), "currency") TotalVenta = TotalVenta + SubTotal TotalDescuento = TotalDescuento + DescuentoP Next Filas txtSubTotalFact.Text = Format((TotalVenta - TotalImpuesto), "currency") 'Nueva txtTotalFactura.Text = Format(TotalVenta, "currency") txtTotalDescuento.Text = Format(TotalDescuento, "currency") txtImpuestoFact.Text = Format(TotalImpuesto, "currency") ' Nueva NArticulos.Text = msGrid.Rows - 1 End Sub
El Siguiente paso es crear la ventana de cambio que no es mas que un Frame con campos donde pedimos los datos con que el cliente va a pagar quedaría de la siguiente manera:
El Frame se le da la propiedad BorderStyle = 0 – None y se da un color de fondo &H00FFC0C0& para el borde use el control Shape con un BorderWith de 5 y color de borde &H009A620E&
El control cmbTipoPago tiene 3 item en su lista:
- Efectivo
- Tarjeta
- Efectivo y Tarjeta
Las opciones de Pago tiene el siguiente código:
Sub AbrirVentanaCambio() 'Call DesactivarBotones framVentanCambio.Top = 4200 framVentanCambio.Visible = True cmbTipoPago.ListIndex = 0 txtNumReciboTarjeta.Text = 0 txtValorTarjeta.Text = 0 txtVECambio.Text = 0 txtCambio.Text = 0 cmbTipoPago.SetFocus End Sub Sub CalcularCambioEfectivo() If txtCambio.Text <> "" Then If Me.txtAbonoFact.Text <> "" Then If CCur(Me.txtAbonoFact.Text) > 0 Then Valor = CCur(txtAbonoFact.Text) End If Else Valor = CCur(Me.txtTotalFactura.Text) End If If Me.cmbTipoPago.ListIndex = 2 Then Valor = CCur(txtTotalFactura.Text) - Me.txtValorTarjeta End If Cambio = txtVECambio - Valor If Cambio >= 0 Then txtCambio = Format(Cambio, "currency") Else ' txtVPCambio.SetFocus End If End If End Sub Private Sub cmbTipoPago_Click() If cmbTipoPago.ListIndex = 0 Then 'efectivo txtNumReciboTarjeta.Visible = False txtValorTarjeta.Visible = False lblNumReciboP.Visible = False lblValorTarjetaP.Visible = False ElseIf cmbTipoPago.ListIndex = 1 Then 'tarjeta txtNumReciboTarjeta.Visible = True lblNumReciboP.Visible = True txtValorTarjeta.Visible = False lblValorTarjetaP.Visible = False Else 'ambos txtNumReciboTarjeta.Visible = True txtValorTarjeta.Visible = True lblNumReciboP.Visible = True lblValorTarjetaP.Visible = True End If End Sub Private Sub cmbTipoPago_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then If cmbTipoPago.ListIndex = 0 Then txtVECambio.SetFocus End If If cmbTipoPago.ListIndex >= 1 Then txtNumReciboTarjeta.SetFocus End If End If End Sub Private Sub txtNumReciboTarjeta_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then If txtNumReciboTarjeta = "" Then txtNumReciboTarjeta.Text = "0" End If If cmbTipoPago.ListIndex = 1 Then txtVECambio.SetFocus Else txtValorTarjeta.SetFocus End If End If End Sub Private Sub txtValorTarjeta_GotFocus() txtValorTarjeta.SelStart = 0 txtValorTarjeta.SelLength = Len(txtValorTarjeta.Text) End Sub Private Sub txtValorTarjeta_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then txtVECambio.SetFocus End If End Sub Private Sub txtValorTarjeta_LostFocus() txtValorTarjeta.Text = Format(txtValorTarjeta.Text, "currency") End Sub Private Sub txtVECambio_GotFocus() txtVECambio.Text = CCur(txtVECambio.Text) txtVECambio.SelStart = 0 txtVECambio.SelLength = Len(txtVECambio.Text) End Sub Private Sub txtVECambio_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then Call CalcularCambioEfectivo txtCambio.SetFocus End If End Sub Private Sub txtCambio_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then Call Finalizar_Guardado_Factura End If End Sub
Al abrir la ventana de cambio necesitamos 2 procedimientos uno para desactivar los botones y los otros campos del formulario y otro para volverlo a activar:
Sub ActivarBotones() cmdNuevaFact.Enabled = True cmdIngresarPro.Enabled = True cmdGuardarFact.Enabled = True cmdBorrarPro.Enabled = True cmdFactAbiertas.Enabled = True cmdSalir.Enabled = True Frame1.Enabled = True 'clientes Frame2.Enabled = True 'producto End Sub Sub DesactivarBotones() cmdNuevaFact.Enabled = False cmdIngresarPro.Enabled = False cmdGuardarFact.Enabled = False cmdBorrarPro.Enabled = False cmdFactAbiertas.Enabled = False cmdSalir.Enabled = False Frame1.Enabled = False 'clientes Frame2.Enabled = False 'producto End Sub
El paso a seguir ya es guardar la factura y para ellos hay que guardar el encabezado de la factura en la tabla tblVentas que lleva la siguiente estructura:
Para guardar la factura necesitamos el últmo numero que se ingreso en la tabla para eso usamos una Función que nos devuelva ese dato:
Function Ultima_Factura_Venta() Dim RecordSetNumFact As New ADODB.RecordSet Dim Sql As String Sql = "SELECT Max(Num_Factura) AS UltimoNumero FROM tblVentas ORDER BY Max(Num_Factura) DESC;" Set RecordSetNumFact = ConexionADO.Execute(Sql) If RecordSetNumFact.RecordCount > 0 Then If IsNull(RecordSetNumFact("UltimoNumero")) = False Then Ultima_Factura_Venta = RecordSetNumFact("UltimoNumero") + 1 Else Ultima_Factura_Venta = 1 End If Else Ultima_Factura_Venta = 1 End If End Function
Después de esto si procedemos a terminar de guardar la factura:
Sub Finalizar_Guardado_Factura() Num_Factura = Ultima_Factura_Venta() 'Ultima venta FechaHora = txtFechaApro.Text & " " & Time 'fecha y hora Comentario = "-" If txtObervacionesPro.Text <> "" Then 'comentario Comentario = txtObervacionesPro.Text End If 'Se guarda en la tabla ventas Sql = "Insert Into tblVentas (Num_Factura, FechaHora, TipoFact, Dias, TotalFactura, EstadoFact, Comentario, Efectivo, Cambio, IdCliente, IdUsuario) " _ & " VALUES (" & Num_Factura & ",'" & FechaHora & "'," & Me.cmdTipoFact.ListIndex & "," & txtDias.Text & ",'" & CCur(txtTotalFactura) & "',1,'" & Comentario & "','" & CCur(txtVECambio.Text) & "','" & CCur(txtCambio.Text) & "'," & CodigoCliente & "," & Glo_IdUsuario & ")" ConexionADO.Execute Sql 'A los productos del detalle se les asigna el numero de factura Sql = "Update tblDetalle_Venta set Num_Factura = '" & Num_Factura & "', Num_VentaTemp = '0' where Num_VentaTemp = " & ConsecutivoTemp ConexionADO.Execute Sql '*************** Consulta que resta todos los articulos de inventario Sql = "UPDATE tblProductos as ar INNER JOIN tblDetalle_Venta as d ON ar.IdProducto = d.IdProducto SET ar.ExistPro = (ar.ExistPro - d.Cantidad_dv) where d.Num_Factura = " & Num_Factura ConexionADO.Execute Sql '/*//*********************** crear el historial de cada articulo en el kardex Sql = "INSERT INTO tblKardex (Fecha, IdProducto, Detalle, D_C, Cantidad, Costo,Cant_Saldo) Select '" & FechaHora & "', dt.IdProducto, 'Venta de Mercancia según Fra. N° " & Num_Factura & " '," _ & Num_Factura & ", dt.Cantidad_dv * -1, dt.P_Costo_dv, (Select ExistPro from tblProductos where IdProducto = dt.IdProducto) from tblDetalle_Venta as dt Where dt.Num_Factura = " & Num_Factura ConexionADO.Execute Sql ConsecutivoTemp = UltimaVentaTemp Call LlenarGridProductos MsgBox "Venta Guardada", vbInformation, "Guardar" Call LimpiarVenta End Sub
En el código anterior notamos varias consultas que parecen hasta extrañas o complicadas pero es la manera mas eficiente de hacer la actualización de producto y registrar el detalle en el Kardex.
'*************** Consulta que resta todos los articulos de inventario Sql = "UPDATE tblProductos as ar INNER JOIN tblDetalle_Venta as d ON ar.IdProducto = d.IdProducto SET ar.ExistPro = (ar.ExistPro - d.Cantidad_dv) where d.Num_Factura = " & Num_Factura ConexionADO.Execute Sql
La consulta anterior relacionamos la tabla Productos y Detalle_Venta por medio de campo IdProducto y hacemos una actualización donde tomamos la existencia actual del producto en la tabla tblProductos y la Restamos de la Cantidad Vendida de la tabla Detalle_Venta esta sola consulta resta todos los productos que estén en el detalle de venta filtrados por el Num_Factura (Número de Factura) dejando actualizada la tabla tblProductos.
Sql = "INSERT INTO tblKardex (Fecha, IdProducto, Detalle, D_C, Cantidad, Costo,Cant_Saldo) Select '" & FechaHora & "', dt.IdProducto, 'Venta de Mercancia según Fra. N° " & Num_Factura & " '," _ & Num_Factura & ", dt.Cantidad_dv * -1, dt.P_Costo_dv, (Select ExistPro from tblProductos where IdProducto = dt.IdProducto) from tblDetalle_Venta as dt Where dt.Num_Factura = " & Num_Factura
La consulta anterior lo que haces es tomar cada producto del Detalle_Venta filtrados por el numero de factura y agregarlo a la tabla tblKardex para llevar un registro del movimiento del producto.
Cómo es una salida de inventario multiplica el campo Cantidad_dv por -1 para que quede un valor negativo y por ultimo tomo el valor de la existencia actual del producto y tambien lo guardo en el kardex quedando de la siguiente manera.
Después de guardar la Venta Se limpian los campos del formulario y se pone el foco en el código del producto dejando todo listo para la siguiente factura:
Sub LimpiarVenta() txtTotalFactura.Text = 0 txtImpuestoFact.Text = 0 txtSubTotalFact.Text = 0 txtTotalDescuento.Text = 0 NArticulos.Text = 0 txtObervacionesPro.Text = "" CodigoCliente = 1 txtAbonoFact.Text = 0 txtDias.Text = 0 cmdTipoFact.ListIndex = 0 End Sub
En la próxima lección se trabajara la impresión de la factura usando el control DataReport