Crear un punto de venta con ASP.NET y SQL Server (Parte 3)

Pantalla de Ventas
Agregamos un nuevo WebForm, llamado ventas.aspx como se muestra:

Le daremos el siguiente diseño:

El código HTML para lograr ese diseño:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ventas.aspx.cs" Inherits="ventas" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Punto de Venta Web</title>
    <link href="StyleSheet.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript">
        //NO SALIR de esta pantalla
        window.history.forward(1);
        //Solo numeros
        var nav4 = window.Event ? true : false;
        function acceptNum(evt) {
            // NOTE: Backspace = 8, Enter = 13, '0' = 48, '9' = 57, '.' = 46
            var key = nav4 ? evt.which : evt.keyCode;
            return (key <= 13 || (key >= 48 && key <= 57) || key == 46);
        }
</script>
</head>
<body>
    <form id="frmVentas" runat="server">
    <div style="min-height:300px; width:580px;">
    <div style="position:absolute; top:40px; background-color:#ADD8E6; width:150px; left:400px; text-align:right; height:50px; font-size:20pt; bottom: 480px; vertical-align:middle;"> <asp:Label ID="lblTOTAL" runat="server" Text="$ 0.00"></asp:Label></div>
    <fieldset style="min-height:300px; " >
        <legend>Ventas</legend>
        <table style="margin:10px;">
            <tr>
                <td>Clave:</td>
                <td>Cantidad:</td>
                <td rowspan="2">
                    <asp:Button ID="btnAgregar" ValidationGroup="Add" OnClick="btnAgregar_Click"  
                    Height="50" runat="server" Text="Agregar" />
                </td>
            </tr>
            <tr>
                <td>
                    <asp:TextBox ID="txtID_PRODUCTO" MaxLength="50" runat="server"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="reqtxtID_PRODUCTO" ValidationGroup="Add" 
                    ControlToValidate="txtID_PRODUCTO"  runat="server" ErrorMessage="*"></asp:RequiredFieldValidator>
                </td>
                <td>
                    <asp:TextBox ID="txtCANTIDAD" MaxLength="10" Width="90" runat="server"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="reqtxtCANTIDAD" ValidationGroup="Add"  
                    ControlToValidate="txtCANTIDAD" runat="server" ErrorMessage="*"></asp:RequiredFieldValidator>
                </td>
            </tr>
        </table>
        <asp:GridView ID="grdVentas" AutoGenerateColumns="False" 
        OnRowDataBound="grdVentas_RowDataBound" 
        Width="100%" ShowFooter="True" runat="server">
        <Columns>            
            <asp:BoundField HeaderText="Clave" DataField="id_producto">
            <ItemStyle HorizontalAlign="Left" />
            <HeaderStyle HorizontalAlign="Left" />
            </asp:BoundField>
            <asp:BoundField HeaderText="Descripcion" DataField="producto" >
            <ItemStyle HorizontalAlign="Left" />
            <HeaderStyle HorizontalAlign="Left" />
            </asp:BoundField>
            <asp:BoundField HeaderText="Cantidad" DataField="cantidad" HtmlEncode="False" 
            DataFormatString="{0:N0}"  >
            <ItemStyle HorizontalAlign="Right" />
            <HeaderStyle HorizontalAlign="Right" />
            </asp:BoundField>
            <asp:BoundField HeaderText="Precio" DataField="p_venta" HtmlEncode="False" 
            DataFormatString="{0:C}" >
            <ItemStyle HorizontalAlign="Right" />
            <HeaderStyle HorizontalAlign="Right" />
            </asp:BoundField>
            <asp:BoundField HeaderText="Total" DataField="TOTAL" HtmlEncode="False" 
            DataFormatString="{0:C}" >
            <ItemStyle HorizontalAlign="Right" />
            <HeaderStyle HorizontalAlign="Right" />
            </asp:BoundField>
        </Columns>
        <EmptyDataTemplate>
            <h2>No hay registros.</h2>
            <br />
            <b>Instrucciones para agregar articulos:</b><br /><br />
            1. Proporcione la clave del articulo<br />
            2. Proporcione la cantidad<br />
            3. Presione "Agregar"
        </EmptyDataTemplate>
        </asp:GridView>
        <table style="width:100%">
            <tr>
                <td style="text-align:center;">
                    <asp:Button ID="btnGrabar" OnClick="btnGrabar_Click" Width="100" 
                    Height="50"  runat="server" Text="Grabar" />
                    <asp:Button ID="btnCancelar" OnClick="btnCancelar_Click" Width="100" 
                    Height="50" runat="server" Text="Cancelar" />
                </td>
            </tr>
        </table>
        <asp:Label ID="lblMessage" runat="server" Text=""></asp:Label>
    </fieldset>
    </div>
    </form>
</body>
</html>
Luego creamos los siguientes procedimientos almacenados:
USE [pventa]
GO

/****** Object:  StoredProcedure [dbo].[proc_LISTA_TEMP_VENTAS]    Script Date: 09/08/2011 17:14:38 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[proc_LISTA_TEMP_VENTAS]
    @USER_LOGIN NVARCHAR(50)
AS
SELECT T.id_venta_detalle_tmp,P.id_producto, 
P.producto, T.cantidad,  T.p_venta,
(T.cantidad * T.p_venta) AS TOTAL
FROM productos P JOIN venta_detalle_tmp T ON P.id_producto=T.id_producto
JOIN unidad_medida M ON P.id_unidad_medida=M.id_unidad_medida
WHERE T.user_login=@USER_LOGIN

GO

USE [pventa]
GO

/****** Object:  StoredProcedure [dbo].[proc_TEMP_VENTAS]    Script Date: 09/08/2011 17:14:49 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[proc_TEMP_VENTAS]
    @USER_LOGIN NVARCHAR(50),  
    @ID_PRODUCTO NVARCHAR(50), 
    @CANTIDAD FLOAT
AS
/*GRABAR TMEP_VENTAS*/
BEGIN TRANSACTION tVTA
    DECLARE @PRECIO FLOAT,@IVA FLOAT,@EXISTENCIA FLOAT,@CANT FLOAT, @PORC_DESC FLOAT
    SELECT @EXISTENCIA=EXISTENCIA FROM productos WHERE ID_PRODUCTO=@ID_PRODUCTO
    SET @PORC_DESC=0
    SELECT TOP(1) @PRECIO = p_venta,@ID_PRODUCTO=ID_PRODUCTO FROM productos 
    WHERE ID_PRODUCTO=@ID_PRODUCTO
    IF @PRECIO IS NULL
        GOTO ERROR_A
    IF EXISTS(SELECT ID_PRODUCTO FROM venta_detalle_tmp 
    WHERE ID_PRODUCTO=@ID_PRODUCTO AND user_login=@USER_LOGIN)
    BEGIN
        --EDITAR
        SELECT @CANT = CANTIDAD FROM venta_detalle_tmp 
        WHERE ID_PRODUCTO=@ID_PRODUCTO AND user_login=@USER_LOGIN
        IF(@CANTIDAD<=(@EXISTENCIA-@CANT))
        BEGIN
            UPDATE venta_detalle_tmp 
            SET CANTIDAD = CANTIDAD + @CANTIDAD
            WHERE user_login = @USER_LOGIN
            AND ID_PRODUCTO=@ID_PRODUCTO AND user_login=@USER_LOGIN
        END
        ELSE
            GOTO ERROR_EXIST
    END
    ELSE
    BEGIN
        --INSERTAR
        IF(@CANTIDAD<=@EXISTENCIA)
        BEGIN
            INSERT  INTO venta_detalle_tmp(user_login,ID_PRODUCTO,CANTIDAD,p_venta)
            VALUES(@USER_LOGIN,@ID_PRODUCTO,@CANTIDAD,@PRECIO)
        END
        ELSE
            GOTO ERROR_EXIST
    END
    
    IF @@ERROR<> 0 GOTO ERROR
COMMIT TRANSACTION tVTA
RETURN
ERROR:
    RAISERROR('No se puede agregar el registro,16,1)
    ROLLBACK TRANSACTION tVTA
    GOTO FIN
RETURN
ERROR_A:
    RAISERROR('El articulo no existe,16,1)
    ROLLBACK TRANSACTION tVTA
    GOTO FIN
RETURN
ERROR_EXIST:
    RAISERROR('No hay suficientes existencias,16,1)
    ROLLBACK TRANSACTION tVTA
    GOTO FIN
RETURN
FIN:


GO

USE [pventa]
GO

/****** Object:  StoredProcedure [dbo].[proc_VENTA]    Script Date: 09/08/2011 17:14:58 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[proc_VENTA]
    @USER_LOGIN NVARCHAR(50)
AS
BEGIN TRANSACTION tVTAs
    DECLARE @FOLIO_VENTA INT
    IF NOT EXISTS(SELECT ID_PRODUCTO FROM venta_detalle_tmp WHERE user_login=@USER_LOGIN )
        GOTO NOOPER
    --GRABAMOS LA VENTA
    INSERT INTO VENTA(user_login,fecha_registro) 
    VALUES(@USER_LOGIN,GETDATE())
    --OBTENEMOS EL FOLIO DE LA VENTA
    SELECT @FOLIO_VENTA=@@IDENTITY
    --INSERTAMOS EL DETALLE DE LA VENTA
    INSERT INTO VENTA_DETALLE(id_venta,ID_PRODUCTO,CANTIDAD,P_VENTA)
    SELECT @FOLIO_VENTA,ID_PRODUCTO,CANTIDAD,P_VENTA 
    FROM venta_detalle_tmp WHERE user_login=@USER_LOGIN 
    --ACTUALIZAMOS LAS EXISTENCIAS GENERALES
    UPDATE productos 
    SET productos.EXISTENCIA = 
     productos.EXISTENCIA-venta_detalle_tmp.[CANTIDAD]
     FROM venta_detalle_tmp 
     WHERE productos.ID_PRODUCTO = 
     venta_detalle_tmp.ID_PRODUCTO 
     AND venta_detalle_tmp.user_login= @USER_LOGIN
    --BORRAMOS LA TABLA TEMPORAL
    DELETE FROM venta_detalle_tmp  WHERE user_login = @USER_LOGIN
    IF @@ERROR <> 0
        GOTO ERROR
    SELECT @FOLIO_VENTA
COMMIT TRANSACTION tVTAs
RETURN
ERROR:
    RAISERROR('No se puede grabar la venta,16,1)
    ROLLBACK TRANSACTION tVTAs
    GOTO FIN
RETURN
NOOPER:
    RAISERROR('No hay registros en la lista de ventas,16,1)
    ROLLBACK TRANSACTION tVTAs
    GOTO FIN
RETURN	
FIN:

GO
Luego ponemos el código de ventas.aspx.cs:
double varTOTAL = 0;
protected void Page_Load(object sender, EventArgs e){
    try{
        if (!Page.IsPostBack){
            //leer datos
               
            txtCANTIDAD.Attributes.Add("onkeypress", "return acceptNum(event)");
                
            ReadData(User.Identity.Name);
        }
    }
    catch (Exception ex){
        lblMessage.Text = ex.Message;
    }
}
void ReadData(string prmUSER_NAME){
    lblMessage.Text = "";
    try{
        varTOTAL = 0;
        SqlConnection cnnReadData =
            new SqlConnection(clsMain.CnnStr);
        string varSQL = "EXECUTE [proc_LISTA_TEMP_VENTAS] '" + prmUSER_NAME + "'";
        SqlCommand cmdReadData = new SqlCommand(varSQL, cnnReadData);
        cnnReadData.Open();
        DataSet ds = new DataSet();
        SqlDataAdapter da = new SqlDataAdapter(varSQL, cnnReadData);
        da.Fill(ds, "DATOS");
        grdVentas.DataSource = ds.Tables["DATOS"];
        grdVentas.DataBind();
        ds.Dispose();
        cmdReadData.Dispose();
        cnnReadData.Close();
        cnnReadData.Dispose();
    }
    catch (Exception ex){
        lblMessage.Text = ex.Message;
    }
}
bool Temp_Ventas(string prmUSER_LOGIN, string prmID_PRODUCTO, double prmCANTIDAD){
    //Para cargar la venta TEMPORAL
    try{
        SqlConnection cnnTempVentas = new SqlConnection(clsMain.CnnStr);
        cnnTempVentas.Open();
        SqlCommand cmdTempVentas = new SqlCommand();
        cmdTempVentas.Connection = cnnTempVentas;
        cmdTempVentas.CommandText = "EXECUTE [proc_TEMP_VENTAS] '" + prmUSER_LOGIN + "','" + prmID_PRODUCTO + "'," + prmCANTIDAD + "";
        cmdTempVentas.ExecuteNonQuery();
        cnnTempVentas.Close();
        cmdTempVentas.Dispose();
        cnnTempVentas.Dispose();
        txtID_PRODUCTO.Text = "";
        txtCANTIDAD.Text = "1";
        return (true);

    }
    catch (Exception ex){
        lblMessage.Text = ex.Message;
        return (false);
    }
}
protected void grdVentas_RowDataBound(object sender, GridViewRowEventArgs e){
    if (e.Row.RowType == DataControlRowType.DataRow){
        // add the UnitPrice and QuantityTotal to the running total variables
        varTOTAL += Convert.ToDouble(DataBinder.Eval(e.Row.DataItem, "TOTAL"));

    }
    else if (e.Row.RowType == DataControlRowType.Footer){

        e.Row.Cells[3].Text = "TOTAL";
        e.Row.Cells[3].HorizontalAlign = HorizontalAlign.Right;
        e.Row.Cells[3].VerticalAlign = VerticalAlign.Top;
        // for the Footer, display the running totals
        e.Row.Cells[4].Text = varTOTAL.ToString("C");
        e.Row.Cells[4].HorizontalAlign = HorizontalAlign.Right;
        e.Row.Cells[4].VerticalAlign = VerticalAlign.Top;
        e.Row.Font.Bold = true;
        lblTOTAL.Text = varTOTAL.ToString("C");
        //establecemos en blanco las celdas que no tienen dato


    }
}
protected void btnAgregar_Click(object sender, EventArgs e){
    try {

        if (Temp_Ventas(User.Identity.Name,txtID_PRODUCTO.Text,
            Convert.ToDouble(txtCANTIDAD.Text))) {
            ReadData(User.Identity.Name);
        }
    }
    catch (Exception ex){
        lblMessage.Text = ex.Message;
    }
}
private int RealizaVenta(string prmUSER_LOGIN)
{

    try{
        int varTICKET = 0;
        SqlConnection cnnGrabar = new SqlConnection(clsMain.CnnStr);
        cnnGrabar.Open();
        SqlCommand cmdGrabar = new SqlCommand();
        cmdGrabar.Connection = cnnGrabar;
        cmdGrabar.CommandText = "EXECUTE [proc_VENTA] '" + prmUSER_LOGIN + "'";
        varTICKET = Convert.ToInt32(cmdGrabar.ExecuteScalar());
        //LIBERAMOS LOS RECUSROS
        cnnGrabar.Close();
        cnnGrabar.Dispose();
        cmdGrabar.Dispose();
        //mostramos la info                
        return (varTICKET);
    }
    catch (Exception ex){
        lblMessage.Text =ex.Message;
        return (0);
    }
}
private bool CancelarVenta(string prmUSER_LOGIN){
    try{
        SqlConnection cnnCancelar = new SqlConnection(clsMain.CnnStr);
        cnnCancelar.Open();
        SqlCommand cmdCancelar = 
            new SqlCommand( "DELETE FROM venta_detalle_tmp WHERE user_login = '"+prmUSER_LOGIN +"'",cnnCancelar);
        cmdCancelar.ExecuteNonQuery();
        cnnCancelar.Close();
        cnnCancelar.Dispose();
        cmdCancelar.Dispose();             
        return (true);
    }
    catch (Exception ex){
        lblMessage.Text = ex.Message;
        return (false);
    }
}
protected void btnGrabar_Click(object sender, EventArgs e){
    try {
        int varTICKET = RealizaVenta(User.Identity.Name);
        if (varTICKET != 0) {
            Response.Redirect("default.aspx");
        }
    }
    catch (Exception ex) {
        lblMessage.Text = ex.Message;
    }
}
protected void btnCancelar_Click(object sender, EventArgs e){
    try{
            
        if (CancelarVenta(User.Identity.Name)){
            Response.Redirect("default.aspx");
        }
    }
    catch (Exception ex) {
        lblMessage.Text = ex.Message;
    }
}
Antes de continuar, entremos ala base de datos y agreguemos unidades de medida y articulos.
Asi se ve nuestro formulario con articulos:

Anterior | Siguiente

2 comentarios:

  1. EL total me lo multiplica por dos en tu ejemplo a mi me daria 58

    ResponderEliminar
  2. tengo el siguiente error

    "A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)"

    alguien me podria ayudar

    saludos
    de antemano gracias

    ResponderEliminar