manual c#

47
Programación C# .net Parte 3: Aplicación Sistema de ventas en C#.net – trabajando con capas Introducción En el siguiente manual vamos a desarrollar un sistema de ventas usando el lenguaje de programación C# y como base de datos vamos a usar el SQL Server 2008 y también crearemos un reporte con Crystal Report. La base de datos que vamos a crear es una base de datos con fines didácticos, dado que nos faltaría crear más tablas, como la tabla cliente, categoría, unidad de medida, etc. Pero si nos explayamos mucho nos quedaría muy largo el tutorial. Además en el ejemplo no se explica cómo disminuir un stock, debido a que eso siempre se les pide a los alumnos universitario que investiguen como hacerlo, pero si quieren una ayudita lo pueden hacer creando Triggers en la base de datos. 2. Desarrollo En esta primera parte del tutorial vamos a crear la base de datos en SQL Server 2008, la base de datos se llamara BDTutorial 3 Diseño de la base de datos La base de datos tendría las siguientes tablas: Venta, Producto y DetalleVenta Además la columna "codigoVenta" de la tabla "Venta" tiene un valor de identidad, eso quiere decir que su valor es auto incremental que comienza en uno e incrementa de uno en uno. Lo mismo sucedería con la columna "codigoProducto" de la tabla Producto. Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Upload: david-molina

Post on 08-Sep-2014

260 views

Category:

Documents


11 download

TRANSCRIPT

Page 1: manual C#

Programación C# .net

Parte 3: Aplicación Sistema de ventas enC#.net – trabajando con capas

IntroducciónEn el siguiente manual vamos a desarrollar un sistema de ventas usando el lenguaje de programación C# y como base de datos vamos a usar el SQL Server 2008 y también crearemos un reporte con Crystal Report. La base de datos que vamos a crear es una base de datos con fines didácticos, dado que nos faltaría crear más tablas, como la tabla cliente, categoría, unidad de medida, etc. Pero si nos explayamos mucho nos quedaría muy largo el tutorial. Además en el ejemplo no se explica cómo disminuir un stock, debido a que eso siempre se les pide a los alumnos universitario que investiguen como hacerlo, pero si quieren una ayudita lo pueden hacer creando Triggers en la base de datos.

2. Desarrollo

En esta primera parte del tutorial vamos a crear la base de datos en SQL Server 2008, la base de datos se llamara BDTutorial

3 Diseño de la base de datos

La base de datos tendría las siguientes tablas: Venta, Producto y DetalleVenta

Además la columna "codigoVenta" de la tabla "Venta" tiene un valor de identidad, eso quiere decir que su valor es auto incremental que comienza en uno e incrementa de uno en uno.Lo mismo sucedería con la columna "codigoProducto" de la tabla Producto.

Creando los procedimientos almacenados

Un procedimiento almacenado (stored procedure en inglés) es un programa (o procedimiento) el cual es almacenado físicamente en una base de datos. Su implementación varía de un manejador de bases de datos a otro. La ventaja de un procedimiento almacenado es que al ser ejecutado, en respuesta a una petición de usuario, es ejecutado directamente en el motor de bases de datos, el cual usualmente corre en un servidor separado. Como tal, posee acceso directo a los datos que necesita manipular y sólo necesita

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 2: manual C#

Programación C# .net

enviar sus resultados de regreso al usuario, deshaciéndose de la sobrecarga resultante de comunicar grandes cantidades de datos salientes y entrantes.

Procedimientos Almacenados para la tabla Producto

/*----------------------------------------------------PROCEDIMIENTO ALMACENADO UTILIZADO PARA INSERTAR UN PRODUCTO A LA BASE DE DATOS----------------------------------------------------*/CREATE PROC dbo.spI_Producto @codigoProducto int = Null OUTPUT, @nombre varchar(100) = Null, @precio decimal(18, 2) = NullASinsert into Producto( nombre, precio)VALUES(@nombre,@precio)--Obteniendo el codigo autogenerado de producto SET @codigoProducto = @@IDENTITY;GO/*----------------------------------------------------PROCEDIMIENTO ALMACENADO UTILIZADO PARA ACTUALIZAR UNPROCEDUCTO A LA BASE DE DATOS----------------------------------------------------*/CREATE PROC dbo.spU_Producto @codigoProducto int = Null, @nombre varchar(100) = Null, @precio decimal(18, 2) = NullAS

UPDATE ProductoSET nombre = @nombre, precio = @precioWHERE codigoProducto = @codigoProductoGO/*----------------------------------------------------PROCEDIMIENTO ALMACENADO UTILIZADO PARA OBTENER TODOSLOS PRODUCTOS DE LA BASE DE DATOS----------------------------------------------------*/CREATE PROC dbo.spF_Producto_AllASSELECT p.codigoProducto, p.nombre, p.precioFROM Producto p

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 3: manual C#

Programación C# .net

ORDER BY P.nombre

Procedimientos Almacenados para la tabla Venta

/*----------------------------------------------------PROCEDIMIENTO ALMACENADO UTILIZADO PARA INSERTAR UNA VENTA A LA BASE DE DATOS----------------------------------------------------*/CREATE PROC dbo.spI_Venta @codigoVenta int = Null OUTPUT, @cliente varchar(100) = NullAS

insert into Venta( cliente, fecha)VALUES(@cliente,GETDATE())--Obteniendo el codigo autogenerado de la venta SET @codigoVenta = @@IDENTITYGO

/*----------------------------------------------------PROCEDIMIENTO ALMACENADO UTILIZADO PARA OBTENER EL REPORTE DE LA VENTA DE LA BASE DE DATOS----------------------------------------------------*/CREATE PROCEDURE dbo.spF_Venta_One @codigoVenta intASSELECT v.codigoVenta AS CodigoVenta, v.cliente AS Cliente, v.fecha AS Fecha, d.codigoProducto AS CodigoProducto, p.nombre AS Nombre, p.precio AS Precio, d.cantidad AS Cantidad, d.descuento AS Descuento, p.precio*d.cantidad AS Parcial, ((p.precio*d.cantidad)-d.descuento) AS SubTotal, ( SELECT SUM((dT.cantidad * pT.precio)-dT.descuento) AS TotalPagar FROM DetalleVenta AS dT INNER JOIN Producto AS pT ON dT.codigoProducto = pT.codigoProducto WHERE dT.codigoVenta=v.codigoVenta ) AS TotalPagarFROM Venta AS v INNER JOIN DetalleVenta AS d ON v.codigoVenta = d.codigoVenta INNER JOIN

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 4: manual C#

Programación C# .net

Producto AS p ON d.codigoProducto = p.codigoProductoWHERE v.codigoVenta=@codigoVentaORDER BY Nombre

GO

/*----------------------------------------------------PROCEDIMIENTO ALMACENADO UTILIZADO PARA OBTENER TODAS LAS VENTAS DE LA BASE DE DATOS----------------------------------------------------*/CREATE PROCEDURE dbo.spF_Venta_AllASSELECT v.codigoVenta AS CodigoVenta, v.cliente AS Cliente, v.fecha AS Fecha, d.codigoProducto AS CodigoProducto, p.nombre AS Nombre, p.precio AS Precio, d.cantidad AS Cantidad, d.descuento AS Descuento, p.precio*d.cantidad AS Parcial, ((p.precio*d.cantidad)-d.descuento) AS SubTotal, ( SELECT SUM((dT.cantidad * pT.precio)-dT.descuento) AS TotalPagar FROM DetalleVenta AS dT INNER JOIN Producto AS pT ON dT.codigoProducto = pT.codigoProducto WHERE dT.codigoVenta=v.codigoVenta ) AS TotalPagarFROM Venta AS v INNER JOIN DetalleVenta AS d ON v.codigoVenta = d.codigoVenta INNER JOIN Producto AS p ON d.codigoProducto = p.codigoProductoORDER BY CodigoVenta, Nombre

Procedimientos Almacenados para la tabla DetalleVenta

/*----------------------------------------------------PROCEDIMIENTO ALMACENADO UTILIZADO PARA INSERTAR UN DETALLE DE VENTA A LA BASE DE DATOS----------------------------------------------------*/CREATE PROC dbo.spI_DetalleVenta @codigoVenta int = Null, @codigoProducto int = Null, @cantidad decimal(18, 2) = Null, @descuento decimal(18, 2) = NullASinsert into DetalleVenta( codigoVenta, codigoProducto,

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 5: manual C#

Programación C# .net

cantidad, descuento)VALUES( @codigoVenta, @codigoProducto, @cantidad, @descuento)

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 6: manual C#

Programación C# .net

Trabajando con Capas

Programación por capas

La programación por capas es un estilo de programación en el que el objetivo primordial es la separación de la lógica de negocios de la lógica de diseño. La ventaja principal de este estilo es que el desarrollo se puede llevar a cabo en varios niveles y, en caso de que sobrevenga algún cambio, sólo se ataca al nivel requerido sin tener que revisar entre código mezclado. Un buen ejemplo de este método de programación sería el modelo de interconexión de sistemas abiertos

Programación en tres capas

Capa de presentación: es la que ve el usuario (también se la denomina "capa de usuario"), presenta el sistema al usuario, le comunica la información y captura la información del usuario en un mínimo de proceso (realiza un filtrado previo para comprobar que no hay errores de formato). Esta capa se comunica únicamente con la capa de negocio. También es conocida como interfaz gráfica y debe tener la característica de ser "amigable" (entendible y fácil de usar) para el usuario.

Capa de negocio: es donde residen los programas que se ejecutan, se reciben las peticiones del usuario y se envían las respuestas tras el proceso. Se denomina capa de negocio (e incluso de lógica del negocio) porque es aquí donde se establecen todas las reglas que deben cumplirse. Esta capa se comunica con la capa de presentación, para recibir las solicitudes y presentar los resultados, y con la capa de datos, para solicitar al gestor de base de datos para almacenar o recuperar datos de él. También se consideran aquí los programas de aplicación.

Capa de datos: es donde residen los datos y es la encargada de acceder a los mismos. Está formada por uno o más gestores de bases de datos que realizan todo el almacenamiento de datos, reciben solicitudes de almacenamiento o recuperación de información desde la capa de negocio.

Creando el proyecto

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 7: manual C#

Programación C# .net

Primero debemos de crear un proyecto con Visual Studio 2008, para eso abrimos el Visual Studio 2008 y nos vamos al menú de "Archivo-->Nuevo Proyecto". A nuestro proyecto le pondremos de nombre "SistemaVentas"

Agregando la Capa de Datos

Debemos de agregar a nuestro proyecto la capa de datos, para eso nos vamos al menú de "Archivo-->Agregar Nuevo Proyecto"

Y le pondremos como nombre "CapaDatos"

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 8: manual C#

Programación C# .net

Agregando configuración de Datos

La cadena de conexión la vamos a guardar en los datos de configuración de la aplicación. Para ello usaremos la ficha configuración de las propiedades de CapaDatos. Tal como podemos ver en la figura debajo, le asignaremos ConexionBD y en ámbito seleccionaremos “aplicación”; esto hará que se añada a nuestro Proyecto capaDatos un fichero llamado app.config que será el que contenga todos los valores añadidos con el ámbito de aplicación; esos valores solo serán de lectura.

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 9: manual C#

Programación C# .net

La clase Conexión

Para agregar una clase en C# debemos hacer clic derecho en la Capa de Datos y seleccionar la opción "Agregar-->Clase" y la clase que creamos se llamara "Conexión", que se encargara de guardar la cadena de conexión para poder conectarnos con nuestra base de datos que está en SQL Server 2008 y la cual se llama BDTutorial.

La clase Conexión tendrá el siguiente código en C#

using System;using System.Collections.Generic;using System.Linq;using System.Text;using CapaDatos.Properties;

namespace CapaDatos{ public class Conexion { //La base de datos se llama BDTutorial //La ubicacion de base de datos esta de modo local y en una instancia que se llama SQLEXPRESS2008 //Se llama a la configuración hecha en la capaDatos. public static string cn = Settings.Default.ConexionBD; }}

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 10: manual C#

Programación C# .net

La clase Producto

Esta clase se encarga de conectar la tabla Producto con C#

using System;using System.Collections.Generic;using System.Text;//Impotaciones necesariasusing System.Data;using System.Data.SqlClient;

namespace CapaDatos{

public class Producto { private int var_codigoProducto; private string var_nombre; private decimal var_precio;

//Constructor vacio public Producto() {

}

//Constructor con parametros public Producto( int codigoProducto, string nombre, decimal precio ) { this.var_codigoProducto = codigoProducto; this.var_nombre = nombre; this.var_precio = precio; }

//Metodo utilizado para insertar un Producto public string Insertar(Producto varProducto) { string rpta = ""; SqlConnection sqlCon = new SqlConnection(); try { //1. Establecer la cadena de conexion sqlCon.ConnectionString = Conexion.cn; //2. Abrir la conexion de la BD sqlCon.Open(); //3. Establecer el comando SqlCommand sqlCmd = new SqlCommand(); sqlCmd.Connection = sqlCon; sqlCmd.CommandText = "spI_Producto"; sqlCmd.CommandType = CommandType.StoredProcedure;

//4. Agregar los parametros al comando//Establecemos los valores para el parametro @codigoProducto del Procedimiento Almacenado

SqlParameter sqlParcodigoProducto = new SqlParameter();

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 11: manual C#

Programación C# .net

sqlParcodigoProducto.ParameterName = "@codigoProducto"; sqlParcodigoProducto.SqlDbType = SqlDbType.Int;

//Le declaramos que el parametro es de salida, porque obtendremos el codigo generado por la base de datos

sqlParcodigoProducto.Direction = ParameterDirection.Output;sqlCmd.Parameters.Add(sqlParcodigoProducto); //Agregamos el parámetro al comando//Establecemos los valores para el parametro @nombre del Procedimiento Almacenado

SqlParameter sqlParnombre = new SqlParameter(); sqlParnombre.ParameterName = "@nombre"; sqlParnombre.SqlDbType = SqlDbType.VarChar; sqlParnombre.Size = 100; sqlParnombre.Value = varProducto.nombre;

sqlCmd.Parameters.Add(sqlParnombre); //Agregamos el parametro al comando

//Establecemos los valores para el parametro @precio del Procedimiento Almacenado

SqlParameter sqlParprecio = new SqlParameter(); sqlParprecio.ParameterName = "@precio"; sqlParprecio.SqlDbType = SqlDbType.Decimal; sqlParprecio.Precision=18; sqlParprecio.Scale=2; sqlParprecio.Value = varProducto.precio;

sqlCmd.Parameters.Add(sqlParprecio); //Agregamos el parametro al comando

//5. Ejecutamos el commandorpta = sqlCmd.ExecuteNonQuery() == 1 ? "OK" : "No se inserto el producto de forma correcta";

} catch (Exception ex) { rpta = ex.Message; } finally { //6. Cerramos la conexion con la BD if (sqlCon.State == ConnectionState.Open) sqlCon.Close(); } return rpta; }

//Metodo utilizado para actualizar un Producto public string Actualizar(Producto varProducto) { string rpta = ""; SqlConnection sqlCon = new SqlConnection(); try { //1. Establecer la cadena de conexion sqlCon.ConnectionString = Conexion.cn; //2. Abrir la conexion de la BD sqlCon.Open();

//3. Establecer el comando SqlCommand sqlCmd = new SqlCommand(); sqlCmd.Connection = sqlCon;

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 12: manual C#

Programación C# .net

sqlCmd.CommandText = "spU_Producto"; sqlCmd.CommandType = CommandType.StoredProcedure;

//4. Agregar los parametros al comando//Establecemos los valores para el parametro @codigoProducto del Procedimiento Almacenado

SqlParameter sqlParcodigoProducto = new SqlParameter(); sqlParcodigoProducto.ParameterName = "@codigoProducto"; sqlParcodigoProducto.SqlDbType = SqlDbType.Int; sqlParcodigoProducto.Value = varProducto.codigoProducto; sqlCmd.Parameters.Add(sqlParcodigoProducto); //Agregamos el parametro al comando

//Establecemos los valores para el parametro @nombre del Procedimiento Almacenado SqlParameter sqlParnombre = new SqlParameter(); sqlParnombre.ParameterName = "@nombre"; sqlParnombre.SqlDbType = SqlDbType.VarChar; sqlParnombre.Size = 100; sqlParnombre.Value = varProducto.nombre; sqlCmd.Parameters.Add(sqlParnombre); //Agregamos el parametro al comando

//Establecemos los valores para el parametro @precio del Procedimiento Almacenado SqlParameter sqlParprecio = new SqlParameter(); sqlParprecio.ParameterName = "@precio"; sqlParprecio.SqlDbType = SqlDbType.Decimal; sqlParprecio.Precision = 18; sqlParprecio.Scale = 2; sqlParprecio.Value = varProducto.precio; sqlCmd.Parameters.Add(sqlParprecio); //Agregamos el parametro al comando

//5. Ejecutamos el commando rpta = sqlCmd.ExecuteNonQuery() == 1 ? "OK" : "No se actualizo el producto de forma correcta";

} catch (Exception ex) { rpta = ex.Message; } finally { //6. Cerramos la conexion con la BD if (sqlCon.State == ConnectionState.Open) sqlCon.Close(); } return rpta; }

//Metodo utilizado para obtener todos los productos de la base de datos public DataTable ObtenerProducto() { DataTable dtProducto = new DataTable("Producto"); SqlConnection sqlCon = new SqlConnection(); try { //1. Establecer la cadena de conexion sqlCon.ConnectionString = Conexion.cn;

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 13: manual C#

Programación C# .net

//2. Establecer el comando SqlCommand sqlCmd = new SqlCommand(); sqlCmd.Connection = sqlCon;//La conexion que va a usar el comando sqlCmd.CommandText = "spF_Producto_All";//El comando a ejecutar sqlCmd.CommandType = CommandType.StoredProcedure;//Decirle al comando que va a ejecutar una sentencia SQL

//3. No hay parametros

//4. El DataAdapter que va a ejecutar el comando y es el encargado de llena el DataTable SqlDataAdapter sqlDat = new SqlDataAdapter(sqlCmd); sqlDat.Fill(dtProducto);//Llenamos el DataTable } catch (Exception ex) { dtProducto = null; } return dtProducto; }

#region Metodos Get y Set public int codigoProducto { get { return var_codigoProducto; } set { var_codigoProducto = value; } } public string nombre { get { return var_nombre; } set { var_nombre = value; } } public decimal precio { get { return var_precio; } set { var_precio = value; } } #endregion

}}

Clase DetalleVenta

Esta clase se encarga de conectar la tabla DetalleVenta con C#

using System;using System.Collections.Generic;using System.Text;//Impotaciones necesariasusing System.Data;using System.Data.SqlClient;

namespace CapaDatos{ public class DetalleVenta {

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 14: manual C#

Programación C# .net

private int var_codigoVenta; private int var_codigoProducto; private decimal var_cantidad; private decimal var_descuento;

//Constructor vacio public DetalleVenta() {

}

//Constructor con parametros public DetalleVenta( int codigoVenta , int codigoProducto , decimal cantidad , decimal descuento ) { this.var_codigoVenta=codigoVenta; this.var_codigoProducto=codigoProducto; this.var_cantidad=cantidad; this.var_descuento=descuento; }

//Método utilizado para insertar un DetalleVenta//Le pasamos la conexion y la transaccion por referencia, debido a que esos datos lo obtenemos//de la clase Venta y no deberiamos crear una nueva Conexion o una nueva Transaccion//sino la creada por la clase Venta

public string Insertar(DetalleVenta varDetalleVenta, ref SqlConnection sqlCon, ref SqlTransaction sqlTra) { string rpta = ""; try { //1. Establecer el comando SqlCommand sqlCmd = new SqlCommand(); sqlCmd.Connection = sqlCon; sqlCmd.Transaction = sqlTra; sqlCmd.CommandText = "spI_DetalleVenta"; sqlCmd.CommandType = CommandType.StoredProcedure;

//4. Agregar los parametros al comando//Establecemos los valores para el parametro @codigoVenta del Procedimiento Almacenado

SqlParameter sqlParcodigoVenta = new SqlParameter(); sqlParcodigoVenta.ParameterName = "@codigoVenta"; sqlParcodigoVenta.SqlDbType = SqlDbType.Int; sqlParcodigoVenta.Value = varDetalleVenta.codigoVenta; sqlCmd.Parameters.Add(sqlParcodigoVenta); //Agregamos el parametro al comando //Establecemos los valores para el parametro @codigoProducto del Procedimiento Almacenado SqlParameter sqlParcodigoProducto = new SqlParameter(); sqlParcodigoProducto.ParameterName = "@codigoProducto"; sqlParcodigoProducto.SqlDbType = SqlDbType.Int; sqlParcodigoProducto.Size = 4;

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 15: manual C#

Programación C# .net

sqlParcodigoProducto.Value = varDetalleVenta.codigoProducto; sqlCmd.Parameters.Add(sqlParcodigoProducto); //Agregamos el parametro al comando //Establecemos los valores para el parametro @cantidad del Procedimiento Almacenado SqlParameter sqlParcantidad = new SqlParameter(); sqlParcantidad.ParameterName = "@cantidad"; sqlParcantidad.SqlDbType = SqlDbType.Decimal; sqlParcantidad.Precision = 18; sqlParcantidad.Scale = 2; sqlParcantidad.Value = varDetalleVenta.cantidad; sqlCmd.Parameters.Add(sqlParcantidad); //Agregamos el parametro al comando //Establecemos los valores para el parametro @descuento del Procedimiento Almacenado SqlParameter sqlPardescuento = new SqlParameter(); sqlPardescuento.ParameterName = "@descuento"; sqlPardescuento.SqlDbType = SqlDbType.Decimal; sqlParcantidad.Precision = 18; sqlParcantidad.Scale = 2; sqlPardescuento.Value = varDetalleVenta.descuento; sqlCmd.Parameters.Add(sqlPardescuento); //Agregamos el parametro al comando

//5. Ejecutamos el commando rpta = sqlCmd.ExecuteNonQuery() == 1 ? "OK" : "No se inserto el detalle de venta de forma correcta";

} catch (Exception ex) { rpta = ex.Message; } return rpta; }

#region Metodos Get y Set public int codigoVenta { get { return var_codigoVenta; } set { var_codigoVenta = value; } } public int codigoProducto { get { return var_codigoProducto; } set { var_codigoProducto = value; } } public decimal cantidad { get { return var_cantidad; } set { var_cantidad = value; } } public decimal descuento { get { return var_descuento; } set { var_descuento = value; } } #endregion

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 16: manual C#

Programación C# .net

}}

Clase Venta

Esta clase se encarga de conectar la tabla Venta con C#

using System;using System.Collections.Generic;using System.Text;//Impotaciones necesariasusing System.Data;using System.Data.SqlClient;

namespace CapaDatos{ public class Venta { private int var_codigoVenta; private string var_cliente; private DateTime var_fecha;

//Constructor vacio public Venta() {

}

//Constructor con parametros public Venta(int codigoVenta,string cliente,DateTime fecha) { this.var_codigoVenta=codigoVenta; this.var_cliente=cliente; this.var_fecha=fecha; }

//Metodo utilizado para insertar un Venta public string Insertar(Venta varVenta, List<DetalleVenta> detalles) { string rpta = ""; SqlConnection sqlCon = new SqlConnection();

try { //1. Establecer la cadena de conexion sqlCon.ConnectionString = Conexion.cn; //2. Abrir la conexion de la BD sqlCon.Open(); //3. Establecer la transaccion SqlTransaction sqlTra = sqlCon.BeginTransaction(); //4. Establecer el comando SqlCommand sqlCmd = new SqlCommand(); sqlCmd.Connection = sqlCon; sqlCmd.Transaction = sqlTra; sqlCmd.CommandText = "spI_Venta"; sqlCmd.CommandType = CommandType.StoredProcedure; //5. Agregar los parametros al comando //Establecemos los valores para el parametro @codigoVenta del Procedimiento Almacenado

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 17: manual C#

Programación C# .net

SqlParameter sqlParcodigoVenta = new SqlParameter(); sqlParcodigoVenta.ParameterName = "@codigoVenta"; sqlParcodigoVenta.SqlDbType = SqlDbType.Int; sqlParcodigoVenta.Direction = ParameterDirection.Output; sqlCmd.Parameters.Add(sqlParcodigoVenta); //Agregamos el parametro al comando //Establecemos los valores para el parametro @cliente del Procedimiento Almacenado SqlParameter sqlParcliente = new SqlParameter(); sqlParcliente.ParameterName = "@cliente"; sqlParcliente.SqlDbType = SqlDbType.VarChar; sqlParcliente.Size = 100; sqlParcliente.Value = varVenta.cliente; sqlCmd.Parameters.Add(sqlParcliente); //Agregamos el parametro al comando //6. Ejecutamos el commando rpta = sqlCmd.ExecuteNonQuery() == 1 ? "OK" : "No se inserto el detalle de venta de forma correcta"; if (rpta.Equals("OK")) { //Obtenemos el codigo de la venta que se genero por la base de datos this.codigoVenta=Convert.ToInt32(sqlCmd.Parameters["@codigoVenta"].Value); foreach(DetalleVenta det in detalles){ //Establecemos el codigo de la venta que se autogenero det.codigoVenta = this.codigoVenta; //Llamamos al metodo insertar de la clase DetalleVenta //y le pasamos la conexion y la transaccion que debe de usar rpta = det.Insertar(det, ref sqlCon, ref sqlTra); if (!rpta.Equals("OK")) { //Si ocurre un error al insertar un detalle de venta salimos del for break; } } } if (rpta.Equals("OK")) { //Se inserto todo los detalles y confirmamos la transaccion sqlTra.Commit(); } else { //Algun detalle no se inserto y negamos la transaccion sqlTra.Rollback(); }

} catch (Exception ex) { rpta = ex.Message; } finally { //6. Cerramos la conexion con la BD if (sqlCon.State == ConnectionState.Open) sqlCon.Close();

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 18: manual C#

Programación C# .net

} return rpta; }

//Obtenemos la venta por el codigo generado public DataTable ObtenerVenta(int codigoVenta) { DataTable dtVenta = new DataTable("Venta"); SqlConnection sqlCon = new SqlConnection(); try { //1. Establecer la cadena de conexion sqlCon.ConnectionString = Conexion.cn;

//2. Establecer el comando SqlCommand sqlCmd = new SqlCommand(); sqlCmd.Connection = sqlCon;//La conexion que va a usar el comando sqlCmd.CommandText = "spF_Venta_One";//El comando a ejecutar sqlCmd.CommandType = CommandType.StoredProcedure;//Decirle al comando que va a ejecutar una sentencia SQL

//3. Agregar los parametros al comando //Establecemos los valores para el parametro @codigoVenta del Procedimiento Almacenado SqlParameter sqlParcodigoVenta = new SqlParameter(); sqlParcodigoVenta.ParameterName = "@codigoVenta"; sqlParcodigoVenta.SqlDbType = SqlDbType.Int; sqlParcodigoVenta.Value = codigoVenta; sqlCmd.Parameters.Add(sqlParcodigoVenta); //Agregamos el parametro al comando

//4. El DataAdapter que va a ejecutar el comando y es el encargado de llena el DataTable SqlDataAdapter sqlDat = new SqlDataAdapter(sqlCmd); sqlDat.Fill(dtVenta);//Llenamos el DataTable } catch (Exception ex) { dtVenta = null; } return dtVenta; }

//Obtener todas las ventas public DataTable ObtenerVenta() { DataTable dtVenta = new DataTable("Venta"); SqlConnection sqlCon = new SqlConnection(); try { //1. Establecer la cadena de conexion sqlCon.ConnectionString = Conexion.cn;

//2. Establecer el comando SqlCommand sqlCmd = new SqlCommand(); sqlCmd.Connection = sqlCon;//La conexion que va a usar el comando sqlCmd.CommandText = "spF_Venta_All";//El comando a ejecutar sqlCmd.CommandType = CommandType.StoredProcedure;//Decirle al comando que va a ejecutar una sentencia SQL

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 19: manual C#

Programación C# .net

//3. No hay parametros

//4. El DataAdapter que va a ejecutar el comando y es el encargado de llena el DataTable SqlDataAdapter sqlDat = new SqlDataAdapter(sqlCmd); sqlDat.Fill(dtVenta);//Llenamos el DataTable } catch (Exception ex) { dtVenta = null; } return dtVenta; }

#region Metodos Get y Set public int codigoVenta { get { return var_codigoVenta; } set { var_codigoVenta = value; } } public string cliente { get { return var_cliente; } set { var_cliente = value; } } public DateTime fecha { get { return var_fecha; } set { var_fecha = value; } } #endregion

}}

Resumen

Al final deberíamos tener las siguientes clases

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 20: manual C#

Programación C# .net

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 21: manual C#

Programación C# .net

Parte 4: Creación de la capa Negocios

Ya vimos anteriormente como crear la Capa de Dato de nuestro sistema, la cual es la encargada de comunicarse con la base de datos. Ahora nos tocaría desarrollar la Capa de Negocios que es la capa en la cual se implementa la lógica del negocio de la empresa como obtener descuentos, aumentos, etc.

Creando el proyecto

Ahora debemos de agregar a nuestro proyecto un proyecto del tipo biblioteca de clases que se llamara "CapaNegocios"

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 22: manual C#

Programación C# .net

Agregando al referencia con la Capa de Datos

Debemos de establecer la comunicación entre la Capa de Negocios y la Capa de Datos. Para eso hacemos clic derecho en nuestro proyecto que se llama "CapaNegocios" y nos vamos a la opcion de "Agregar Referencia"

Y de ahí seleccionamos que se comunique con el proyecto que se llama "CapaDatos"

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 23: manual C#

Programación C# .net

Clase NegProducto

La clase "NegProducto" se encarga de comunicarse con la clase "Producto" de la capa de datos

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data;//Para que se comunique con la Capa de Datosusing CapaDatos;namespace CapaNegocios{ public class NegProducto { //Metodo que llama al metodo Insertar de la Capa de Datos //de la clase Producto public static string Insertar(string Nombre, decimal Precio) { Producto pro = new Producto(); pro.nombre = Nombre; pro.precio = Precio; return pro.Insertar(pro); } //Metodo que llama al metodo Actualizar de la Capa de Datos //de la clase Producto public static string Actualizar(int CodigoProducto, string Nombre, decimal Precio) { Producto pro = new Producto(); pro.codigoProducto = CodigoProducto; pro.nombre = Nombre; pro.precio = Precio; return pro.Actualizar(pro); } //Metodo que se encarga de llamar al metodo ObtenerProducto //de la clase Producto public static DataTable ObtenerProducto() { return new Producto().ObtenerProducto(); } }}

Clase NegDetalleVenta

La clase "NegDetalleVenta" se encarga de establecer los descuentos de los detalles de venta. Si el subtotal supera los 50 soles, dolares, euros, etc se le aplica un descuento del 5% del detalle de la venta. Y eso se aplica en la Capa de Negocios debido a que pertenece a la lógica de la empresa.

using System;using System.Collections.Generic;using System.Linq;using System.Text;

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 24: manual C#

Programación C# .net

namespace CapaNegocios{ public class NegDetalleVenta { //Metodo utilizado para obtener el descuento del detalle de la venta //si la venta supera los 50 soles, dolares, euros, etc //se le hace un descuento del 5% del detalle de la venta public static decimal ObtenerDescuento(decimal cantidad, decimal pu) { if ((cantidad * pu) > 50) { decimal porcentaje = Convert.ToDecimal(0.05); decimal descuento = ((cantidad * pu) * porcentaje); return descuento; } else { return 0; } } }}

Clase NegVenta

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data;//Para que se comunique con la Capa de Datosusing CapaDatos;

namespace CapaNegocios{ public class NegVenta { //Metodo que llama al metodo Insertar de la Capa de Datos //de la clase Venta public static string Insertar(string cliente, DataTable dtDetalles) { Venta venta = new Venta(); venta.cliente = cliente; List<DetalleVenta> detalles=new List<DetalleVenta>(); foreach (DataRow row in dtDetalles.Rows) { DetalleVenta detalle = new DetalleVenta(); detalle.codigoProducto = Convert.ToInt32(row["codigoProducto"].ToString()); detalle.cantidad = Convert.ToDecimal(row["cantidad"].ToString()); detalle.descuento = NegDetalleVenta.ObtenerDescuento(detalle.cantidad, Convert.ToDecimal(row["PU"].ToString())); detalles.Add(detalle); } return venta.Insertar(venta, detalles); } //Metodo que se encarga de llamar al metodo ObtenerProducto //de la clase Venta public static DataTable ObtenerVenta()

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 25: manual C#

Programación C# .net

{ return new Venta().ObtenerVenta(); } //Metodo que se encarga de llamar al metodo ObtenerProducto //por codigo de la clase Venta public static DataTable ObtenerVenta(int codigoVenta) { return new Venta().ObtenerVenta(codigoVenta); } }}

Resumen

Al final deberíamos tener las siguientes clases

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 26: manual C#

Programación C# .net

Parte 5: Creación de la capa de Presentación Ya hemos creado la capa de datos y la capa de negocios respectivamente de nuestra aplicación, ahora solo nos falta crear nuestra capa de presentación. La capa de presentación puede ser una aplicación del tipo escritorio, web, etc. Es por eso que se utiliza la programación en capas, debido a que no importa que cambiamos hagamos en alguna capa no se sentirá en las otras de manera brusca.

Creando el Proyecto

Ahora debemos de agregar a nuestro proyecto un proyecto del tipo biblioteca de clases que se llamara "CapaPresentacion". No olvidar que debemos de ir a "Archivo-->Agregar-->Nuevo Proyecto"

Agregando la referencia con la Capa de Negocios

Debemos de establecer la comunicacion entre la Capa de Presentación y la Capa de Negocios. Para eso hacemos clic derecho en nuestro proyecto que se llama "CapaPresentacion" y nos vamos a la opcion de "Agregar Referencia"

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 27: manual C#

Programación C# .net

Y de ahí seleccionamos que se comunica con la Capa de Negocios

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 28: manual C#

Programación C# .net

Formulario frmMantenimientoProducto

En este formulario vamos a realizar un mantenimiento a la tabla Producto de nuestra Base de Datos que se llama BDTutorial y que esta diseñada en SQL Server 2008. A mantenimiento me refiero a los procesos de inserción, actualización y consulta de datos de la tabla Producto. Debemos de diseñar el siguiente formulario

En el cual el componente dgvProducto tiene los siguientes valores de propiedades:

AllowUserToAddRows = False AllowUserToDeleteRows = False MultiSelect = False ReadOnly = True SelectionMode = FullRowSelect

Y como columnas tiene

codigoProductoo DataPropertyName = codigoProductoo HeaderText = codigoProductoo Visible = False

Nombreo DataPropertyName = nombreo HeaderText = Nombreo Visible = True

Precioo DataPropertyName = precioo HeaderText = Precioo Visible = True

En la otra pestaña del tabControl tenemos los siguientes componentes:

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 29: manual C#

Programación C# .net

Y su código fuente del formulario seria

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;//Comunicarse con la Capa de Negociosusing CapaNegocios;

namespace CapaPresentacion{ public partial class frmMantenimientoProducto : Form { //Variable que nos indica si vamos a insertar un nuevo producto private bool nuevo = false; //Variable que nos indica si vamos a modificar un producto private bool modificar = false; //Constructor del formulario public frmMantenimientoProducto() { InitializeComponent(); } //Evento que se lanza cuando se va a mostrar el formulario private void frmMantenimientoProducto_Load(object sender, EventArgs e) { //Para ubicar al formulario en la parte superior del contenedor this.Top = 0; this.Left = 0; //Le decimos al DataGridView que no auto genere las columnas this.dgvProductos.AutoGenerateColumns = false; //Llenamos el DataGridView con la informacion de todos nuestros //productos this.dgvProductos.DataSource = NegProducto.ObtenerProducto(); //Deshabilita los controles this.habilitar(false); //Establece los botones this.botones();

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 30: manual C#

Programación C# .net

} //Para mostrar mensaje de confirmacion private void mOK(string men) { MessageBox.Show(men, "MENSAJE", MessageBoxButtons.OK, MessageBoxIcon.Information); } //Para mostrar mensaje de error private void mError(string men) { MessageBox.Show(men, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); } //Limpia los controles del formulario private void limpiar() { this.txtNombre.Text = string.Empty; this.nudPrecio.Value = 0; } //Habilita los controles de los formularios private void habilitar(bool valor) { this.txtNombre.ReadOnly = !valor; this.nudPrecio.Enabled = valor; } //Habilita los botones private void botones() { if (this.nuevo || this.modificar) { this.habilitar(true); this.btnNuevo.Enabled = false; this.btnGuardar.Enabled = true; this.btnModificar.Enabled = false; this.btnCancelar.Enabled = true; } else { this.habilitar(false); this.btnNuevo.Enabled = true; this.btnGuardar.Enabled = false; this.btnModificar.Enabled = true; this.btnCancelar.Enabled = false; } } //Evento clic del boton btnNuevo private void btnNuevo_Click(object sender, EventArgs e) { this.nuevo=true; this.modificar=false; this.botones(); this.limpiar(); this.txtCodigo.Text = string.Empty; this.txtNombre.Focus(); } //Evento clic del boton btnGuardar private void btnGuardar_Click(object sender, EventArgs e) { //La variable que almacena si se inserto o se modifico la tabla string rpta = ""; if(this.nuevo)

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 31: manual C#

Programación C# .net

{ //Vamos a insertar un producto rpta=NegProducto.Insertar(this.txtNombre.Text.Trim().ToUpper(), this.nudPrecio.Value);

}else { //Vamos a modificar un producto rpta=NegProducto.Actualizar(Convert.ToInt32(this.txtCodigo.Text), this.txtNombre.Text.Trim().ToUpper(), this.nudPrecio.Value); } //Si la respuesta fue OK, fue porque se modifico o inserto el Producto //de forma correcta if (rpta.Equals("OK")) { if (this.nuevo) { this.mOK("Se inserto de forma correcta al Producto"); } else { this.mOK("Se actualizo de forma correcta al Producto"); }

} else { //Mostramos el mensaje de error this.mError(rpta); } this.nuevo=false; this.modificar=false; this.botones(); this.limpiar(); this.dgvProductos.DataSource = NegProducto.ObtenerProducto(); this.txtCodigo.Text=""; } //Evento clic del boton btnModificar private void btnModificar_Click(object sender, EventArgs e) { //Si no ha seleccionado un producto no puede modificar if(!this.txtCodigo.Text.Equals("")) { this.modificar=true; this.botones(); } else { this.mError("Debe de buscar un producto para Modificar"); } } //Evento clic del boton btnCancelar private void btnCancelar_Click(object sender, EventArgs e) { this.nuevo=false; this.modificar=false; this.botones(); this.limpiar(); this.txtCodigo.Text=string.Empty;

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 32: manual C#

Programación C# .net

} //Evento double clic del DataGridView de Productos private void dgvProductos_DoubleClick(object sender, EventArgs e) { this.txtCodigo.Text = Convert.ToString(this.dgvProductos.CurrentRow.Cells["codigoProducto"].Value); this.txtNombre.Text = Convert.ToString(this.dgvProductos.CurrentRow.Cells["nombre"].Value); this.nudPrecio.Value = Convert.ToDecimal(this.dgvProductos.CurrentRow.Cells["precio"].Value); this.tabControl.SelectedIndex = 1; }

}}

Formulario frmSeleccionarProducto

Es un formulario del tipo modal que nos permitirá seleccionar un producto de nuestra base de datos para registrar la venta. Y tiene el siguiente diseño

En el cual el componente dgvProducto tiene los siguientes valores de propiedades:

AllowUserToAddRows = False AllowUserToDeleteRows = False MultiSelect = False ReadOnly = True SelectionMode = FullRowSelect

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 33: manual C#

Programación C# .net

Y como columnas tiene

codigoProductoo DataPropertyName = codigoProductoo HeaderText = codigoProductoo Visible = False

Nombreo DataPropertyName = nombreo HeaderText = Nombreo Visible = True

Precioo DataPropertyName = precioo HeaderText = Precioo Visible = True

Y como código fuente tiene lo siguiente

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;//Comunicarse con la Capa de Negociosusing CapaNegocios;////namespace CapaPresentacion{ public partial class frmSeleccionarProducto : Form { //El formulario padre private frmRegistrarVenta frame; //El constructor del formulario public frmSeleccionarProducto() { InitializeComponent(); } //Establece los valores del formulario padre public void estableceFormulario(frmRegistrarVenta frame) { this.frame = frame; } //Evento que se ejecuta cuando se muestra el formulario private void frmSeleccionarProducto_Load(object sender, EventArgs e) { //Que no se genere las columnas de forma automatica this.dgvProducto.AutoGenerateColumns = false; //Obtiene todos los productos y lo asigana al DataGridView this.dgvProducto.DataSource = NegProducto.ObtenerProducto(); } //Evento double clic del DataGridView private void dgvProducto_DoubleClick(object sender, EventArgs e)

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 34: manual C#

Programación C# .net

{ //Estableciendo los datos a las cajas de texto del formulario padre this.frame.codigoProductoSeleccionado = Convert.ToInt32(this.dgvProducto.CurrentRow.Cells["codigoProducto"].Value); this.frame.txtProducto.Text = Convert.ToString(this.dgvProducto.CurrentRow.Cells["nombre"].Value); this.frame.txtPrecio.Text = Convert.ToString(this.dgvProducto.CurrentRow.Cells["precio"].Value); //Cerrando el formulario this.Hide(); }

}}

Formulario frmRegistrarVenta

Este formulario es la parte principal del sistema en cual se registra la venta. Tener en cuenta que si el detalle de la venta es mayor a 50 soles, dolares, euros, etc se le aplica un descuento del 5% del sub total de la venta.  Debemos realizar el siguiente diseño del formulario.

En cual la accesibilidad de los controles txtProducto y txtPrecio es del tipo Internal y tiene la propiedad ReadOnly en True.

Y además el componente dgvDetalle tiene los siguientes valores de propiedades:

AllowUserToAddRows = False AllowUserToDeleteRows = False MultiSelect = False ReadOnly = True SelectionMode = FullRowSelect

Y como columnas tiene

codigoProducto

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 35: manual C#

Programación C# .net

o DataPropertyName = codigoProductoo HeaderText = codigoProductoo Visible = False

Productoo DataPropertyName = Productoo HeaderText = Productoo Visible = True

Cantidado DataPropertyName = cantidado HeaderText = Cantidado Visible = True

PUo DataPropertyName = PUo HeaderText = PUo Visible = True

Descuentoo DataPropertyName = Descuentoo HeaderText = Descuentoo Visible = True

SubTotalo DataPropertyName = subTotalo HeaderText = SubTotalo Visible = True

Y como código fuente tiene lo siguiente:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;//Comunicarse con la Capa de Negociosusing CapaNegocios;////namespace CapaPresentacion{ public partial class frmRegistrarVenta : Form { //DataTable que se encargara de guardar el detalle de la venta //de forma temporal private DataTable dtDetalle; //Codigo del producto seleccionado internal int codigoProductoSeleccionado = -1; //Variable que almacena el total de la venta private decimal totalPagar = 0; //El constructor de la clase public frmRegistrarVenta() { InitializeComponent(); } //Metodo que se ejecuta al cargar el formulario private void frmRegistrarVenta_Load(object sender, EventArgs e) { this.Top = 0;

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 36: manual C#

Programación C# .net

this.Left = 0; this.crearTabla(); this.WindowState = FormWindowState.Maximized; } //Limpia todos los controles del formulario private void limpiarControles() { this.txtCliente.Text = string.Empty; this.codigoProductoSeleccionado = -1; this.txtProducto.Text = string.Empty; this.txtPrecio.Text = string.Empty; this.nudCantidad.Value = 1; this.crearTabla(); this.lblTotalPagar.Text = "Total Pagar: S/. 0.00";

} //Crea la tabla de Detalle private void crearTabla() { //Crea la tabla con el nombre de Detalle this.dtDetalle = new DataTable("Detalle"); //Agrega las columnas que tendra la tabla this.dtDetalle.Columns.Add("codigoProducto", System.Type.GetType("System.Int32")); this.dtDetalle.Columns.Add("Producto", System.Type.GetType("System.String")); this.dtDetalle.Columns.Add("cantidad", System.Type.GetType("System.Decimal")); this.dtDetalle.Columns.Add("PU", System.Type.GetType("System.Decimal")); this.dtDetalle.Columns.Add("Descuento", System.Type.GetType("System.Decimal")); this.dtDetalle.Columns.Add("subTotal", System.Type.GetType("System.Decimal")); //Relacionamos nuestro datagridview con nuestro datatable this.dgvDetalle.DataSource = this.dtDetalle;

} //Para mostrar mensaje de error private void mError(string mensaje) { MessageBox.Show(this, mensaje, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Warning); } //Para mostrar mensaje de confirmación private void mOk(string mensaje) { MessageBox.Show(this, mensaje, "MENSAJE", MessageBoxButtons.OK, MessageBoxIcon.Information); } //Evento del clic del boton btnBuscar private void btnBuscar_Click(object sender, EventArgs e) { //Creamos una variable del tipo del formulario que deseamos abrir frmSeleccionarProducto frame = new frmSeleccionarProducto(); //Le pasamos como datos la información de nuestro formulario frame.estableceFormulario(this); //Mostrar el formulario que tiene los productos que hemos seleccionado frame.ShowDialog(); } //Evento clic del boton agregar

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 37: manual C#

Programación C# .net

private void btnAgregar_Click(object sender, EventArgs e) { //Valida que hemos seleccionado algun producto if (this.codigoProductoSeleccionado == -1) { this.mError("No ha seleccionado aun ningun producto"); } else { //Variable que va a indicar si podemos registrar el detalle bool registrar = true; foreach (DataRow row in dtDetalle.Rows) { if (Convert.ToInt32(row["codigoProducto"]) == this.codigoProductoSeleccionado) { registrar = false; this.mError("Ya se encuentra el producto en el detalle"); } } //Si podemos registrar el producto en el detalle if (registrar) { //Calculamos el sub total del detalle sin descuento decimal subTotal = Convert.ToDecimal(this.txtPrecio.Text) * nudCantidad.Value; //Obtenemos el descuento decimal descuento = NegDetalleVenta.ObtenerDescuento( nudCantidad.Value, Convert.ToDecimal(this.txtPrecio.Text)); //Actualizamos el sub total con el descuento correspondiente subTotal = subTotal - descuento; //Aumentamos el total a pagar this.totalPagar += subTotal; this.lblTotalPagar.Text = "Total Pagar: S/." + totalPagar.ToString("#0.00#");

//Agregamos al fila a nuestro datatable DataRow row = this.dtDetalle.NewRow(); row["codigoProducto"] = this.codigoProductoSeleccionado; row["Producto"] = this.txtProducto.Text; row["cantidad"] = this.nudCantidad.Value; row["PU"] = this.txtPrecio.Text ; row["Descuento"] = descuento; row["subTotal"] = subTotal; this.dtDetalle.Rows.Add(row); } } } //Evento click del boton quitar private void btnQuitar_Click(object sender, EventArgs e) { try { //Indice dila actualmente seleccionado y que vamos a eliminar int indiceFila = this.dgvDetalle.CurrentCell.RowIndex;

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 38: manual C#

Programación C# .net

//Fila que vamos a eliminar DataRow row = this.dtDetalle.Rows[indiceFila]; //Disminuimos el total a pagar this.totalPagar = this.totalPagar - Convert.ToDecimal(row["subTotal"].ToString()); this.lblTotalPagar.Text = "Total Pagar: S/." + totalPagar.ToString("#0.00#"); //Removemos la fila this.dtDetalle.Rows.Remove(row); } catch (Exception ex) { mError("No hay fila para remover"); } }

private void btnGuardar_Click(object sender, EventArgs e) { //Debe de tener por almenos un detalle para poder registrar if (this.dtDetalle.Rows.Count > 0) { string rpta = NegVenta.Insertar(this.txtCliente.Text, this.dtDetalle); if (rpta.Equals("OK")) { mOk("Se inserto de manera correcta la venta"); this.limpiarControles(); } else { mError(rpta); } } else { mError("No agregado ningun detalle"); } }

}}

Finalmente crearemos un MDI con el siguiente aspecto

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia

Page 39: manual C#

Programación C# .net

Parte 3: Aplicación Sistema de Ventas en C#.net trabajando con Capas - David Molina Hostia