71710860 C 3 Capas Buenisimo

35
1 C# - Aplicación de Escritorio, Sistemas de Ventas Parte I - Creación de la Base Datos 1. Entorno SQL Server 2008 Visual Studio 2008 2. Introducción En el siguiente tutorial 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 tambien 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 mas tablas, como la tabla cliente, categoría, unidad de medida, etc pero si nos explayamos mucho nos quedaría muy largo el tutorial. Ademas en el ejemplo no se explica como 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. 3. 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.1. Diseño de la base de datos La base de datos tendría las siguientes tablas: Venta, Producto y DetalleVenta Ademas 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.

Transcript of 71710860 C 3 Capas Buenisimo

Page 1: 71710860 C 3 Capas Buenisimo

1

C# - Aplicación de Escritorio, Sistemas de Ventas Parte I - Creación de la Base Datos

1. Entorno

SQL Server 2008

Visual Studio 2008

2. Introducción

En el siguiente tutorial 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 tambien 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 mas tablas, como la tabla cliente, categoría, unidad de medida, etc pero si nos explayamos

mucho nos quedaría muy largo el tutorial. Ademas en el ejemplo no se explica como 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.

3. 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.1. Diseño de la base de datos

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

Ademas 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.

Page 2: 71710860 C 3 Capas Buenisimo

2

Lo mismo sucedería con la columna "codigoProducto" de la tabla Producto

3.2. Creando los procedimientos almacenados

Según Wikipedia 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 enviar

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

entrantes.

3.2.1. Procedimientos Almacenados para la tabla Producto

/*

----------------------------------------------------

CREADO:

POR :HENRY JOE WONG URQUIZA

FECHA:22FEB2011

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) = Null

AS

insert into Producto

(

nombre,

precio

)

VALUES(

@nombre,

@precio

)

--Obteniendo el codigo autogenerado de producto

SET @codigoProducto = @@IDENTITY;

GO

/*

Page 3: 71710860 C 3 Capas Buenisimo

3

----------------------------------------------------

CREADO:

POR :HENRY JOE WONG URQUIZA

FECHA:22FEB2011

PROCEDIMIENTO ALMACENADO UTILIZADO PARA ACTUALIZAR UN

PROCEDUCTO A LA BASE DE DATOS

----------------------------------------------------

*/

CREATE PROC dbo.spU_Producto

@codigoProducto int = Null,

@nombre varchar(100) = Null,

@precio decimal(18, 2) = Null

AS

UPDATE Producto

SET

nombre = @nombre,

precio = @precio

WHERE

codigoProducto = @codigoProducto

GO

/*

----------------------------------------------------

CREADO:

POR :HENRY JOE WONG URQUIZA

FECHA:22FEB2011

PROCEDIMIENTO ALMACENADO UTILIZADO PARA OBTENER TODOS

LOS PRODUCTOS DE LA BASE DE DATOS

----------------------------------------------------

*/

CREATE PROC dbo.spF_Producto_All

AS

SELECT

p.codigoProducto,

p.nombre,

p.precio

FROM

Producto p

ORDER BY

P.nombre

3.2.2. Procedimientos Almacenados para la tabla Venta

/*

----------------------------------------------------

CREADO:

POR :HENRY JOE WONG URQUIZA

FECHA:22FEB2011

PROCEDIMIENTO ALMACENADO UTILIZADO PARA INSERTAR UNA

VENTA A LA BASE DE DATOS

----------------------------------------------------

*/

CREATE PROC dbo.spI_Venta

@codigoVenta int = Null OUTPUT,

@cliente varchar(100) = Null

AS

insert into Venta

(

cliente,

fecha

)

VALUES(

@cliente,

GETDATE()

)

--Obteniendo el codigo autogenerado de la venta

SET @codigoVenta = @@IDENTITY

Page 4: 71710860 C 3 Capas Buenisimo

4

GO

/*

----------------------------------------------------

CREADO:

POR :HENRY JOE WONG URQUIZA

FECHA:22FEB2011

PROCEDIMIENTO ALMACENADO UTILIZADO PARA OBTENER EL

REPORTE DE LA VENTA DE LA BASE DE DATOS

----------------------------------------------------

*/

CREATE PROCEDURE dbo.spF_Venta_One

@codigoVenta int

AS

SELECT

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 TotalPagar

FROM

Venta AS v INNER JOIN

DetalleVenta AS d ON v.codigoVenta = d.codigoVenta INNER JOIN

Producto AS p ON d.codigoProducto = p.codigoProducto

WHERE

v.codigoVenta=@codigoVenta

ORDER BY

Nombre

GO

/*

----------------------------------------------------

CREADO:

POR :HENRY JOE WONG URQUIZA

FECHA:22FEB2011

PROCEDIMIENTO ALMACENADO UTILIZADO PARA OBTENER TODAS

LAS VENTAS DE LA BASE DE DATOS

----------------------------------------------------

*/

CREATE PROCEDURE dbo.spF_Venta_All

AS

SELECT

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,

(

Page 5: 71710860 C 3 Capas Buenisimo

5

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 TotalPagar

FROM

Venta AS v INNER JOIN

DetalleVenta AS d ON v.codigoVenta = d.codigoVenta INNER JOIN

Producto AS p ON d.codigoProducto = p.codigoProducto

ORDER BY

CodigoVenta, Nombre

3.2.3. Procedimientos Almacenados para la tabla DetalleVenta

/*

----------------------------------------------------

CREADO:

POR :HENRY JOE WONG URQUIZA

FECHA:22FEB2011

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) = Null

AS

insert into DetalleVenta

(

codigoVenta,

codigoProducto,

cantidad,

descuento

)

VALUES(

@codigoVenta,

@codigoProducto,

@cantidad,

@descuento

)

Page 6: 71710860 C 3 Capas Buenisimo

6

C# - Aplicación de Escritorio, Sistemas de Ventas Parte II - Creación de la Capa de Datos

1. Entorno

SQL Server 2008

Visual Studio 2008

2. Introducción

2.1. 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

2.2. 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.

3. Desarrollo

3.1. Creando el proyecto

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"

Page 7: 71710860 C 3 Capas Buenisimo

7

3.2. Agregando la Capa de Datos

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

Y le pondremos como nombre "CapaDatos"

3.3. La clase Conexion

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 "Conexion", que se encargara de guardar la cadena de conexión para poder conectarnos con nuestra base de datos que

esta en SQL Server 2008 y la cual se llama BDTutorial.

Page 8: 71710860 C 3 Capas Buenisimo

8

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

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

//Desarrollado por Henry Joe Wong Urquiza

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 SQL2008

//Utiliza seguridad integrada para conectarse a la base de datos

public static string cn = "Data Source=.\\SQL2008;Initial Catalog=BDTutorial;Integrated

Security=True";

}

}

3.2. La clase Producto

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

using System;

using System.Collections.Generic;

using System.Text;

//Impotaciones necesarias

using System.Data;

using System.Data.SqlClient;

//Desarrollado por Henry Joe Wong Urquiza

namespace CapaDatos

{

public class Producto

{

Page 9: 71710860 C 3 Capas Buenisimo

9

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();

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 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 inserto el producto de forma correcta";

}

Page 10: 71710860 C 3 Capas Buenisimo

10

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;

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;

}

Page 11: 71710860 C 3 Capas Buenisimo

11

//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;

//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

}

}

3.3. Clase DetalleVenta

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

using System;

using System.Collections.Generic;

using System.Text;

//Impotaciones necesarias

using System.Data;

using System.Data.SqlClient;

//Desarrollado por Henry Joe Wong Urquiza

namespace CapaDatos

{

public class DetalleVenta

Page 12: 71710860 C 3 Capas Buenisimo

12

{

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;

}

//Metodo 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;

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";

Page 13: 71710860 C 3 Capas Buenisimo

13

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

}

}

3.4. Clase Venta

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

using System;

using System.Collections.Generic;

using System.Text;

//Impotaciones necesarias

using System.Data;

using System.Data.SqlClient;

//Desarrollado por Henry Joe Wong Urquiza

namespace CapaDatos

{

public class Venta

{

private int var_codigoVenta;

private string var_cliente;

private DateTime var_fecha;

//Constructor vacio

public Venta()

{

Page 14: 71710860 C 3 Capas Buenisimo

14

}

//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

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

Page 15: 71710860 C 3 Capas Buenisimo

15

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();

}

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

Page 16: 71710860 C 3 Capas Buenisimo

16

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

//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

}

}

4. Resumen

Al final deberíamos tener las siguientes clases

Page 17: 71710860 C 3 Capas Buenisimo

17

C# - Aplicación de Escritorio, Sistemas de Ventas Part III - Creación de la Capa de Negocios

1. Entorno

Visual Studio 2008

SQL Server 2008

2. Introducción

Ya vimos que en la Parte II del tutorial creamos 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.

3. Desarrollo

3.1. Creando el proyecto

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

3.2. Agregando al referencia con la Capa de Datos

Debemos de establecer la comunicacion 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"

Page 18: 71710860 C 3 Capas Buenisimo

18

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

3.3. 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 Datos

using CapaDatos;

//Desarollado por Henry Joe Wong Urquiza

namespace CapaNegocios

{

public class NegProducto

Page 19: 71710860 C 3 Capas Buenisimo

19

{

//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();

}

}

}

3.4. 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;

//Desarollado por Henry Joe Wong Urquiza

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;

}

}

}

}

3.5. Clase NegVenta

using System;

using System.Collections.Generic;

Page 20: 71710860 C 3 Capas Buenisimo

20

using System.Linq;

using System.Text;

using System.Data;

//Para que se comunique con la Capa de Datos

using CapaDatos;

//Desarollado por Henry Joe Wong Urquiza

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()

{

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);

}

}

}

4. Resumen

Al final deberíamos tener las siguientes clases

Page 21: 71710860 C 3 Capas Buenisimo

21

C# - Aplicación de Escritorio, Sistemas de Ventas Part IV - Creación de la Capa de Presentación

1. Entorno

SQL Server 2008

Visual Studio 2008

2. Introducción

En el tutorial en la Parte II y en la Parte III hemos creado la capa de datos y la capa de negocios respectivamente de nuestra aplicación,

ahora solo nos falta crear nuestra capa de presentacion. La capa de presentacion puede ser una aplicacion del tipo escritorio, web, etc. Es

por eso que se utiliza la programacion en capas, debido a que no importa que cambiamos hagamos en alguna capa no se sentira en las

otras de manera brusca.

3. Desarrollo

3.1. 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"

3.2. 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"

Page 22: 71710860 C 3 Capas Buenisimo

22

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

3.3. 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

Page 23: 71710860 C 3 Capas Buenisimo

23

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

codigoProducto

o DataPropertyName = codigoProducto

o HeaderText = codigoProducto

o Visible = False

Nombre

o DataPropertyName = nombre

o HeaderText = Nombre

o Visible = True

Precio

o DataPropertyName = precio

o HeaderText = Precio

o Visible = True

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

Page 24: 71710860 C 3 Capas Buenisimo

24

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 Negocios

using CapaNegocios;

//Desarollado por Henry Joe Wong Urquiza

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();

}

//Para mostrar mensaje de confirmacion

private void mOK(string men)

{

MessageBox.Show(men, "MENSAJE", MessageBoxButtons.OK, MessageBoxIcon.Information);

Page 25: 71710860 C 3 Capas Buenisimo

25

}

//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)

{

//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

Page 26: 71710860 C 3 Capas Buenisimo

26

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;

}

//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;

}

}

}

3.4. 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

Page 27: 71710860 C 3 Capas Buenisimo

27

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

codigoProducto

o DataPropertyName = codigoProducto

o HeaderText = codigoProducto

o Visible = False

Nombre

o DataPropertyName = nombre

o HeaderText = Nombre

o Visible = True

Precio

o DataPropertyName = precio

o HeaderText = Precio

o 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 Negocios

using CapaNegocios;

//Desarollado por Henry Joe Wong Urquiza

Page 28: 71710860 C 3 Capas Buenisimo

28

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)

{

//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();

}

}

}

3.5. 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 ademas el componente dgvDetalle tiene los siguientes valores de propiedades:

Page 29: 71710860 C 3 Capas Buenisimo

29

AllowUserToAddRows = False

AllowUserToDeleteRows = False

MultiSelect = False

ReadOnly = True

SelectionMode = FullRowSelect

Y como columnas tiene

codigoProducto

o DataPropertyName = codigoProducto

o HeaderText = codigoProducto

o Visible = False

Producto

o DataPropertyName = Producto

o HeaderText = Producto

o Visible = True

Cantidad

o DataPropertyName = cantidad

o HeaderText = Cantidad

o Visible = True

PU

o DataPropertyName = PU

o HeaderText = PU

o Visible = True

Descuento

o DataPropertyName = Descuento

o HeaderText = Descuento

o Visible = True

SubTotal

o DataPropertyName = subTotal

o HeaderText = SubTotal

o 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 Negocios

using CapaNegocios;

//Desarollado por Henry Joe Wong Urquiza

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();

Page 30: 71710860 C 3 Capas Buenisimo

30

}

//Metodo que se ejecuta al cargar el formulario

private void frmRegistrarVenta_Load(object sender, EventArgs e)

{

this.Top = 0;

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

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

Page 31: 71710860 C 3 Capas Buenisimo

31

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;

//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

Page 32: 71710860 C 3 Capas Buenisimo

32

{

mError(rpta);

}

}

else

{

mError("No agregado ningun detalle");

}

}

}

}

4. Ejemplo de la Aplicación

http://www.youtube.com/watch?v=0pfs9l09ln4&feature=player_embedded

Page 33: 71710860 C 3 Capas Buenisimo

33

C# - Aplicación de Escritorio, Sistemas de Ventas Part V - Creación de Reporte (Crystal Report)

1. Entorno

SQL Server 2008

Visual Studio 2008

2. Introducción

Continuando con el tutorial del sistemas de ventas con C#, ahora crearemos el reporte con Crystal Report que nos mostrara el documento

creado producto de la venta que hemos realizado. Como este es un tutorial con un fin didáctico, para crear el reporte nosotros escribiremos

el código auto generado por la inserción de la venta, aunque lo ideal seria que desde la capa de negocios obtengamos el código que se

genero y se muestre el reporte de forma automática.

3. Desarrollo

3.1. Diseño del formulario

Ahora debemos de modificar nuestro formulario que hemos creado anteriormente que se llamaba frmRegistrarVenta. Si recordamos este

formulario tenia un Tab Control con dos pestañas, una que se llamaba Registrar y otro que se llama Reporte. Y justo en esta ultima

pestaña es donde vamos a poner nuestro reporte. Para poder mostrar los reportes en C#, debemos de agregar un componente que se llama

CrystalReportViewer que se encuentra en nuestro cuadro de herramientas en el grupo de Informe

Y luego en nuestro formulario hacemos el siguiente diseño

Page 34: 71710860 C 3 Capas Buenisimo

34

3.2. Creando nuestro DataSet

Para poder crear un reporte para Crystal Reporte, lo primero que se tiene que hacer es crear un DataSet en donde se almacenara todo

nuestro datos de la consulta y nos servira para llenar nuestro reporte y para eso les prepare el siguiente video para que puedan crear un

DataSet de la manera mas rápida y sencilla.

http://www.youtube.com/watch?v=B84OccrE-BM&feature=player_embedded

3.3. Creando nuestro Reporte en Crystal Report

Ahora debemos de diseñar nuestro reporte con la información que obtenemos de nuestro DataSet que hemos creado anteriormente, para

eso también les prepare otro vídeo.

http://www.youtube.com/watch?v=P0GzJiPlahg&feature=player_embedded

El reporte al final debería tener el siguiente diseño

.3.4. Código Fuente

Ahora nos vamos a ir al evento clic del botón "btnReporte" de nuestro formulario "frmRegistrarVenta" y pondremos el

siguiente código fuente

private void btnReporte_Click(object sender, EventArgs e)

{

try

{

//Creamos el documento

CrystalDecisions.CrystalReports.Engine.ReportDocument rpt=new

CrystalDecisions.CrystalReports.Engine.ReportDocument();

//Obtenemos el documento que se encuentra en nustra carpeta bin\debug\crReporte.rpt

rpt.Load( Application.StartupPath + "\\crReporte.rpt");

Page 35: 71710860 C 3 Capas Buenisimo

35

//Lleanamos el reporte con la información que obtenemos de la base de datos

rpt.SetDataSource(NegVenta.ObtenerVenta(Convert.ToInt32(this.txtCodigoVenta.Text)));

//Establecemos los datos al reporte

this.crvReporte.ReportSource=rpt;

//Refrescamos nuestro reporte

this.crvReporte.RefreshReport();

}

catch (Exception ex)

{

}

}

4. Ejemplo de la Aplicación

http://www.youtube.com/watch?v=K05Vq3n8oKY&feature=player_embedded