You are on page 1of 45

Crear un punto de venta (1 de 10)

Inicio Anterior Siguiente Final


Pantalla de inicio de Sesin
Creamos un proyecto de Windows con el nombre proTienda_MATRICULA.
Despus creamos una base de datos en Access, la cual deber llamarse dbTienda_MATRICULA. Esta
base de datos debemos ponerla en el directorio Debug de nuestro proyecto. El directorio Debug se
encuentra dentro del Directorio Bin, el directorio Bin se encuentra en el directorio en donde creamos
nuestro proyecto.
En este ejemplo se utilizan imgenes y/o Iconos para darle una mejor presentacin al proyecto. No es
obligatorio utilizarlos, pero en caso de estar interesado en conseguirlos, puedes intentar descargarlos
desde la pgina de La Web del Programador.
Antes de realizar cualquier cosa, asegurmonos de organizar nuestro proyecto de la siguiente manera:

Organice su proyecto tal y cual se muestra en la figura, de esta manera evitaremos cometer errores en el
momento de programar.
Contenido:
Diseo de la base de datos
Diseo de las pantallas
Programacin
Diseo de la base de datos:

Tenemos 10 tablas.
Para la realizacin de este ejercicio solo utilizaremos la tabla USERS.
Como esta es una clase de Lenguaje de programacin, omitiremos al mximo las explicaciones relativas
a Desarrollo de Base de datos. Solo se hace la aclaracin que para los motivos educativos del presente
curso, la base de datos aqu mostrada tiene el diseo ptimo.

Antes de continuar, agregamos una referencia a System.configuration:

Diseo de las pantallas:


Agregamos una clase y dos formularios a nuestro proyecto, como se muestra enseguida:

El formulario Login (frmLogin), debe quedar como se muestra:

Le agregamos dos Labels, Dos TextBox y dos Button. Segn la siguiente tabla:

OBJETO PROPEDAD VALOR


Label
Label
TextBox
TextBox
Button
Button
Form

Name
Name
Name
Name
Name
Name
Name

lblUSER_NAME
lblPASSWORD
txtUSER_NAME
txtPASSWORD
btnOK
btnCANCEL
frmLogin

Programacin:
Antes quiero hacer la aclaracin de que al formulario mdiMain no se le har ningn diseo por el
momento.
Comenzaremos por escribir el cdigo para frmLogin.
Estructura del cdigo:
//Directivas Using
using System;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
/* Comentarios:
* Programador: Lic. Juan Gabriel Castillo T.
* Carrera:
Licenciado en Computacin Administrativa
* Matricula:
9921868
* Fecha:
14 de Marzo del 2025
* Materia:
Lenguaje Visual
*/
namespace proTienda_9921868.Forms
{
public partial class frmLogin : Form
{
public frmLogin()
{
//Contructor por defecto
InitializeComponent();
}
//Declaraciones
private void frmLogin_Load(object sender, EventArgs e)
{
//Form_Load
}
//Funciones y procedimientos
}
}

La seccin de las directivas using, agregaremos la siguiente instruccin:

using System.Data;
using System.Data.OleDb;

En la seccin Declaraciones, agregamos las siguientes variables (Algunas correspondientes a los campos
de la Tabla USERS):

//Declaraciones
int Intentos = 0;
public static bool _Logged = false;
public static string _USER_NAME = "";
public static string _PATERNO = "";
public static string _MATERNO = "";
public static string _NOMBRE = "";
public static bool _VENTAS = false;
public static bool _ADMINISTRAR = false;
public static bool _REPORTES = false;
public static bool _CATALOGOS = false;
public static bool _CONSULTAS = false;
public static bool _DESHACER_VENTA = false;

A continuacin, en la seccin Funciones y Procedimientos agregamos el siguiente cdigo:

private bool fnLogin(string prmUSER_NAME, string prmPASSWORD)


{
bool Retorno = false;
try
{
string varSQL = "SELECT USERS.USER_NAME, USERS.PATERNO, " +
" USERS.MATERNO, USERS.NOMBRE, USERS.VENTAS, " +
" USERS.ADMINISTRAR,USERS.REPORTES, " +
" USERS.CATALOGOS, USERS.CONSULTAS, " +
" USERS.DESHACER_VENTA " +
" FROM USERS " +
" WHERE USERS.USER_NAME='" + prmUSER_NAME + "' " +
" AND USERS.USER_PASSWORD ='" + prmPASSWORD + "'";
OleDbConnection cnnLogin =
new OleDbConnection(Class.clsMain.CnnStr);
cnnLogin.Open();
OleDbCommand cmdLogin = new OleDbCommand(varSQL, cnnLogin);
OleDbDataReader drLogin = cmdLogin.ExecuteReader();
while (drLogin.Read())
{
Retorno = true;
_USER_NAME = drLogin["USER_NAME"].ToString();
_PATERNO = drLogin["PATERNO"].ToString();
_MATERNO = drLogin["MATERNO"].ToString();
_NOMBRE = drLogin["NOMBRE"].ToString();
_VENTAS = Convert.ToBoolean(drLogin["VENTAS"]);
_ADMINISTRAR = Convert.ToBoolean(drLogin["ADMINISTRAR"]);
_REPORTES = Convert.ToBoolean(drLogin["REPORTES"]);
_CATALOGOS = Convert.ToBoolean(drLogin["CATALOGOS"]);
_CONSULTAS = Convert.ToBoolean(drLogin["CONSULTAS"]);
_DESHACER_VENTA =
Convert.ToBoolean(drLogin["DESHACER_VENTA"]);
}
drLogin.Close();
cnnLogin.Close();
cmdLogin.Dispose();
return (Retorno);
}
catch (Exception ex) {
MessageBox.Show("fnLogin\n" + ex.Message,
"Informacin del Sistema");
return (Retorno);
}
}

Hacemos doble click en el botn btnOK y agregamos el siguiente cdigo:

_Logged = fnLogin(txtUSER_NAME.Text, txtPASSWORD.Text);


if (Intentos >= 3)
{
_Logged = false;
MessageBox.Show("Demasiados intentos",
"Informacin del sistema");
this.Close();
}
if (_Logged)
this.Close();

Al botn btnCANCEL, le agregamos lo siguiente:

this.Close();

Ahora agregamos el cdigo de clsMain, que debe quedar como se muestra:

using System;
using System.Configuration;
using System.Windows.Forms;
using System.IO;
/* Comentarios:
* Programador: Lic. Juan Gabriel Castillo T.
* Carrera:
LCA
* Matricula:
9921868
* Fecha:
14 de Marzo del 2030
* Materia:
Lenguaje Visual
*/
namespace proTienda_9921868.Class{
class clsMain{
[STAThread]
static void Main()
{
Forms.frmLogin my_frmLogin = new Forms.frmLogin();
Application.Run(my_frmLogin);
if (Forms.frmLogin._Logged == true){
Forms.mdiMain my_mdiMain = new Forms.mdiMain();
Application.Run(my_mdiMain);
}
else{
Application.Exit();
}
}
public static string CnnStr {
get {
string Retorno = "";
string varFileName = "";
try{
varFileName =
ConfigurationManager.AppSettings["DataFile1"];
if (File.Exists(varFileName)){
Retorno =
"Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" +
varFileName + ";" +
"Persist Security Info=False";
}
else{
MessageBox.Show("El archivo de Base"+

" de datos no existe!",


"Informacin del sistema",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return (Retorno);
}
catch (Exception ex) {
MessageBox.Show(ex.Message,"Informacin del Sistema",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return (Retorno);
}
}
}
}
}

Explicaciones sobre el cdigo:

Generalizando.- Cuando un usuario intente ingresar a nuestra aplicacin le aparecer una pantalla de
Login para que intruduzca un nombre de usuario y una contrasea. Solo tendr 3 oportunidades para
ingresar antes de que se cierre la aplicacin. Si el usuario ingresa un nombre de usuario y contrasea
correctos, entonces entrar al sistema y ver la pantalla principal de la aplicacin.
Detalladamente.- Lo que hace la aplicacin es verificar que el usuario exista en la tabla USERS, si existe
significa que puede iniciar sesin en el sistema, y se cargan sus permisos a las variables. Tendremos un
contador para verificar la cantidad de veces que el usuario inetenta ingresar, en el momento que exceda
la cantidad de intentos permitidos la aplicacin se cerrar.
Podemos observar que utilizamos las intrucciones try-catch-finally, estas nos ayudarn para que en el
caso de que ocurra un error en nuestra aplicacin mientras es ejecutada, no tengamos mayores
problemas.
Utilizamos la propiedad State de la conexin, esta nos ayuda a saber si la conexin est abierta o cerrara.
La utilizamos para evitar el error de intentar abrir una conexin abierta o cerrar una conexin cerrada lo
cual es ilgico.
La funcin fnLogin recibe dos parametros (Usuario y Contrasea) y retorna un valor booleano (FalsoVerdadero). La utilizamos para organizar nuestro cdigo de tal manera que al ejecutarse la funcin
podamos saber:
True: Puede iniciar sesin y se cargan los datos del usuario a las variables
False: No puede iniciar sesin por error/desconocer al escribir su nombre de usuario y contrasea y se le
cuenta un intento de acceso.
Las variables public static, son variables globales y pueden ser leidas desde cualquier parte de la
aplicacin con escribir el nombre del objeto, un punto y el nombre de la variable. Por ejemplo, si
queremos saber apellido paterno el usuario haramos lo siguiente:
string varPATERNO = Forms.frmLogin._PATERNO;

Crear un punto de venta (2 de 10)


Inicio Anterior Siguiente Final
Utilidad para configurar la conexin a la base de datos
Continuamos con el proyecto proTienda_MATRICULA.
Contenido:
Diseo de las pantallas
Programacin
Diseo de las pantallas:

La aplicacin contaba ya con una clase y dos formularios, agregaremos un tercer formulario
(frmAppConfig) para que nuestro proyecto se organice as:

Nota: aqu se muestran otros formularios, los cuales debemos pasar por alto por el momento. Estos se
realizarn posteriormente.
El nuevo formulario (frmAppConfig), debe quedar como se muestra:

Le agregamos cinco Label, cinco TextBox y tres Button. Segn la siguiente tabla:

Programacin:
Antes quiero hacer la aclaracin de que al formulario mdiMain no se le har ningn diseo por el
momento.
Comenzaremos por escribir el cdigo para frmAppConfig.
Estructura del cdigo:
//Directivas Using
using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.IO;
/* Comentarios:
* Programador: Lic. Juan Gabriel Castillo T.
* Carrera:
Licenciado en Computacin Administrativa
* Matricula:
9921868
* Fecha:
15 de Marzo del 2025
* Materia:
Lenguaje Visual
*/
namespace proTienda_9921868.Forms
{
public partial class frmAppConfig : Form
{
public frmAppConfig()
{
//Contructor por defecto
InitializeComponent();
}
//Declaraciones
private void frmAppConfig_Load(object sender, EventArgs e)
{
//Form_Load
}
//Funciones y procedimientos
}
}

En la seccin Declaraciones, agregamos lo siguiente:

Hacemos doble clic al formulario y ponemos el siguiente cdigo en el Form_Load:


//Form_Load
txtFileName.Text =
ConfigurationManager.AppSettings["DataFile1"];
txtNombreNegocio.Text =
ConfigurationManager.AppSettings["NombreNegocio"];
txtRFC.Text =
ConfigurationManager.AppSettings["RFC"];
txtTelefono.Text =
ConfigurationManager.AppSettings["Telefono"];
txtDireccionFiscal.Text =
ConfigurationManager.AppSettings["DireccionFiscal"];

Hacemos doble click en el botn btnOK y agregamos el siguiente cdigo:


if (File.Exists(txtFileName.Text))
{
System.Configuration.Configuration config =
ConfigurationManager.
OpenExeConfiguration(ConfigurationUserLevel.None);
//Borramos la configuracin actual
config.AppSettings.Settings.Remove("DataFile1");
config.AppSettings.Settings.Remove("NombreNegocio");
config.AppSettings.Settings.Remove("RFC");
config.AppSettings.Settings.Remove("Telefono");
config.AppSettings.Settings.Remove("DireccionFiscal");
config.Save(ConfigurationSaveMode.Modified);
//Force a reload of the changed section.
ConfigurationManager.RefreshSection("appSettings");
//Grabamos la configuracin nueva
config.AppSettings.Settings.Add("DataFile1",
txtFileName.Text);
config.AppSettings.Settings.Add("NombreNegocio",
txtNombreNegocio.Text);
config.AppSettings.Settings.Add("RFC", txtRFC.Text);
config.AppSettings.Settings.Add("Telefono",
txtTelefono.Text);
config.AppSettings.Settings.Add("DireccionFiscal",
txtDireccionFiscal.Text);
// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);
//Force a reload of the changed section.
ConfigurationManager.RefreshSection("appSettings");
this.Close();
}
else {
MessageBox.Show("El archivo de Base de datos no existe!",
"Informacin del sistema",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}

Al botn btnCancel, le agregamos lo siguiente:


this.Close();

Al botn btnSearch, le ponemos el siguiente cdigo:


OpenFileDialog m_OpenFile = new OpenFileDialog();
m_OpenFile.Title =
"Buscar Base de datos de Microsoft Access";
m_OpenFile.Filter =

"Todos los archivos(*.*)|*.*|Base de datos Access (*.mdb)|*.mdb";


m_OpenFile.FilterIndex = 2;
if (m_OpenFile.ShowDialog() == DialogResult.OK)
{
txtFileName.Text = m_OpenFile.FileName.ToString();
}
else
{
btnOK.Enabled = false;
}

Despus abrimos el formulario frmLogin y le agregamos una LinkLabel (lblDataBase), para que el
formulario quede como se muestra:

Hacemos soble clic sobre lblDataBase y escribimos el siguiente cdigo:


Forms.frmAppConfig _frmAppConfig = new frmAppConfig();
_frmAppConfig.StartPosition = FormStartPosition.CenterScreen;
_frmAppConfig.ShowDialog();

De esta manera, cuando se haga clic sobre la etiqueta, se abrir frmAppConfig.


Ahora editamos el cdigo de clsMain, que debe quedar como se muestra (he marcado con negrita la
porcin de cdigo que fue afectado):
using System;
using System.Configuration;
using System.Windows.Forms;
using System.IO;
namespace proTienda_9921868.Class{
class clsMain{
[STAThread]
static void Main()
{
Forms.frmLogin my_frmLogin = new Forms.frmLogin();
Application.Run(my_frmLogin);
if (Forms.frmLogin._Logged == true){
Forms.mdiMain my_mdiMain = new Forms.mdiMain();
Application.Run(my_mdiMain);
}
else{
Application.Exit();
}
}
public static string CnnStr {
get {
string Retorno = "";
string varFileName = "";
try{
varFileName =
ConfigurationManager.AppSettings["DataFile1"];
if (File.Exists(varFileName)){
Retorno =
"Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" +

varFileName + ";" +
"Persist Security Info=False";
}
else{
MessageBox.Show("El archivo de Base"+
" de datos no existe!",
"Informacin del sistema",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
return (Retorno);
}
catch (Exception ex) {
MessageBox.Show(ex.Message,
"Informacin del Sistema",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return (Retorno);
}
}
}
}
}

Explicaciones sobre el cdigo:


Generalizando. Nuestra aplicacin podr leer la ruta de la base de datos en tiempo de ejecicin. Esto nos
da la gran posibilidad de poner nuestra aplicacin en red. Esto nos ayudar a que la base de datos pueda
estar localizada en cualquier parte de la Computadora o de la Red.
Detalladamente. Tenemos un formulario en el cual podemos, mediante un archivo XML, editar la ruta en
la cual se encuentra la Base de datos. Utilizamos objetos que nos permiten Explorar los archivos de
windows; parecido a si fueramos a abrir un documento de cualquier aplicacin de Microsoft Office.
Utilizamos un Archivo XML el cual es perfectamente legible a nuestros ojos, editable con cualquier editor
de texto y ligero en tamao.
Modificamos la variable CnnStr y la convertimos en Propiedad, eso nos da una posiblidad mayor en
cuanto a lo que podemos realizar.
La utilizacin de Propiedades (Properties) en lugar de Campos (Fields) o variables nos permite una mejor
administracin de cdigo adems de que nos acerca mas a la programacin Orienntada a Objetos.
De hecho, en estos momentos ya hemos realizado este tipo de desarrollo. Hemos creado la clase
frmLogin, la cual nos proporciona varias de las caractersticas de la programacin orientada a objetos.

Tambin creamos la clase clsMain

Lo mejor es que antes de programar podamos hacer nuestros diagramas de clase para tener una visin
mas clara de lo que tenemos que realizar. Para este proyecto ya me he adelantado en el anlisis para que
no tengamos que detenernos en esos aspectos. Se recomienda leer bibliografia sobre UML (Lenguaje
Unificado de Modelado) para entender los diagramas.

Crear un punto de venta (3 de 10)


Inicio Anterior Siguiente Final
Pantalla para administrar los usuarios del sistema
Continuamos con el proyecto proTienda_MATRICULA.
Contenido:
Diseo de las pantallas
Programacin
Recordemos que en el primer ejercicio creamos un formulario para que los usuarios inicien sesin en la
aplicacin. En esta ocasin crearemos un formulario que nos permita administrar a los usuarios que
tengan derecho a los recursos del sistema.
Diseo de las Pantallas:
Agregaremos un formulario al cual nombraremos frmUsers.
A continuacin agregaremos un ToolStrip al formulario recin creado, Etiquetas, Cajas de Texto y casillas
de verificacin como se muestra a continuacin.
El formulario frmUsers, deber quedar como se muestra:

Segn la informacin de la siguiente tabla:

Los botones del ToolStrip (barUsers), de izquierda a derecha:

Por un momento dejaremos este formulario para hacer algunas adecuaciones a mdiMain. Le
agregaremos un MenuStrip para que quede como se muestra a continuacin:

Segn la informacin de la siguiente tabla:

Los mens del MenuStrip debern ser como se muestra en la siguiente tabla:

Al men mnuArchivo se le agregarn tres submens, como se muestra en la siguiente imagen:

Segn la informacin de la siguiente tabla:

Al men mnuAdministrar se le agregar un submen, como se muestra en la siguiente imagen:

Segn la informacin de la siguiente tabla:

Programacin:
Empezamos con mdiMain. Hacemos sobre clic sobre el formulario y escribimos el siguiente cdigo en el
Form_Load:
//Form_Load
this.Text = "Mdulo de Control de Ventas, usuario: " +
frmLogin._NOMBRE + " " +
frmLogin._PATERNO + " " +

frmLogin._MATERNO;
mnuVentas.Enabled = frmLogin._VENTAS;
mnuAdministrar.Enabled = frmLogin._ADMINISTRAR;
mnuReportes.Enabled = frmLogin._REPORTES;
mnuConsultas.Enabled = frmLogin._CONSULTAS;
mnuCatalogos.Enabled = frmLogin._CATALOGOS;

El cdigo anterior se encarga de habilitar o deshabilitar los mens, siempre dependiendo de los permisos
que tenga el usuario que inici sesin en el sistema.
Hacemos doble clic sobre el submen Usuarios del sistema (mnuUsuarios), accedemos a su cdigo y le
ponemos el siguiente:
Forms.frmUsers _frmUsers = new frmUsers();
_frmUsers.MdiParent = this;
_frmUsers.StartPosition = FormStartPosition.Manual;
_frmUsers.Show();

Hacemos doble clic sobre el submen Salir del sistema (mnuSalir) para ponerle el siguiente cdigo:
this.Close();

Lo ms interesante que hemos logrado hasta aqu es la parte de los permisos. Si recordamos lo que
hicimos en frmLogin, en la funcin fnLogin, en la parte en donde le damos los valores para los permisos;
bueno, pues estos permisos se ven reflejados en esta pantalla. De esta manera podemos observar una
manera fcil de lograr que los objetos compartan sus valores y lograr que interactuen entre ellos.
Posteriormente podremos ver mejores muestras de interaccin entre los objetos, por ahora, puedo decir
que hemos aprendido a leer los valores contenidos en las variables public static.
Quiz para muchos es complicado comprender el cdigo aqu expuesto. Mis disculpas a todos aquellos
en quienes no he logrado hacer llegar la idea del cdigo que se presenta aqu. Ni el mas experto de los
programadores naci con el conocimiento, en algunas ocasiones nos vemos en la necesidad de practicar
con el cdigo de otros para poder salir adelante con el trabajo.
Me he dispuesto a preparar este tutorial para que se den cuenta todos los conocimientos que se requieren
para la realizacin de un simple punto de venta.
Ahora seguiremos con frmUsers. El cdigo aqu mostrado es simple aunque algo extenso. En la seccin
de las directivas:
using System.Data.OleDb;
using System.Data;

En la seccin de declaraciones:
//Las variables van aqui
static OleDbConnection cnnUsers;
static OleDbDataAdapter daUsers;
static OleDbCommandBuilder cbUsers;
DataSet dsUsers = new DataSet("dsUsers");
CurrencyManager cmUsers;

//Aqu el Form_Load
this.Closing +=
new System.ComponentModel.
CancelEventHandler(frmUsers_Closing);
cnnUsers = new OleDbConnection(Class.clsMain.CnnStr);
daUsers = new OleDbDataAdapter();
daUsers.SelectCommand = new OleDbCommand("SELECT *" +
" FROM USERS", cnnUsers);
cbUsers = new OleDbCommandBuilder(daUsers);
if (cnnUsers.State == ConnectionState.Open)
cnnUsers.Close();

cnnUsers.Open();
dsUsers.Clear();
daUsers.Fill(dsUsers, "USERS");
txtUSER_LOGIN.DataBindings.Add("Text", dsUsers,
"USERS.USER_NAME");
txtPASSWORD.DataBindings.Add("Text", dsUsers,
"USERS.USER_PASSWORD");
txtPATERNO.DataBindings.Add("Text", dsUsers,
"USERS.PATERNO");
txtMATERNO.DataBindings.Add("Text", dsUsers,
"USERS.MATERNO");
txtNOMBRE.DataBindings.Add("Text", dsUsers,
"USERS.NOMBRE");
chkADMINISTRAR.DataBindings.Add("Checked", dsUsers,
"USERS.ADMINISTRAR", false);
chkVENTAS.DataBindings.Add("Checked", dsUsers,
"USERS.VENTAS", true);
chkREPORTES.DataBindings.Add("Checked", dsUsers,
"USERS.REPORTES", true);
chkCATALOGOS.DataBindings.Add("Checked", dsUsers,
"USERS.CATALOGOS", true);
chkCONSULTAS.DataBindings.Add("Checked", dsUsers,
"USERS.CONSULTAS", true);
chkDESHACER_VENTA.DataBindings.Add("Checked", dsUsers,
"USERS.DESHACER_VENTA", true);
cmUsers = (CurrencyManager)this.BindingContext[dsUsers, "USERS"];
cnnUsers.Close();

teclear el siguiente cdigo, tal como se muestra:


void frmUsers_Closing(object sender,
System.ComponentModel.CancelEventArgs e){
try{
if (cnnUsers.State == ConnectionState.Open)
cnnUsers.Close();
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}

En btnNuevo:
//Agregar un registro
cmUsers.AddNew();

En btnCancelar:
//Cancelar
cmUsers.CancelCurrentEdit();

En btnGrabar:
//Grabar
try{
cmUsers.EndCurrentEdit();
if (cnnUsers.State == ConnectionState.Open)
cnnUsers.Close();
cnnUsers.Open();
daUsers.Update(dsUsers, "USERS");
cnnUsers.Close();
}
catch (Exception ex) {
MessageBox.Show(ex.Message + "" + ex.StackTrace);
}

En btnEliminar:
//Eliminar
try{
DialogResult Resp = new DialogResult();
Resp = MessageBox.Show("Desea Eliminar al usuario?",
"Eliminar", MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (Resp == DialogResult.Yes)
{
cmUsers.RemoveAt(cmUsers.Position);
if (cnnUsers.State == ConnectionState.Open)
cnnUsers.Close();
cnnUsers.Open();
daUsers.Update(dsUsers, "USERS");
cnnUsers.Close();
}
}
catch (Exception ex){
MessageBox.Show(ex.Message);
}

Para btnInicio:
//Navegar al 1er registro
cmUsers.Position = 0;

Para btnAnterior:
//Navegar un registro hacia atraz
cmUsers.Position -= 1;

Para btnSiguiente:
//Navergar un registro hacia adelante
cmUsers.Position += 1;

Para btnFinal:
//Navegar al ltimo registro
cmUsers.Position =
cmUsers.Count - 1;

Para btnCerrar:
this.Close();

Hasta aqu llegamos.

Crear un punto de venta (4 de 10)


Inicio Anterior Siguiente Final

Creacin de una Librera de Clases (Dll)


El objetivo de este ejercicio es mostrar al alumno la manera de crear sus propias Libreras de Clases.
Nos ubicamos en la parte en donde dice Solution proTienda_MATRICULA y con el botn derecho
seleccionamos Add>New Project...

Creamos una librera de clase llamada Ticket:

Borramos la clase que nos ofrece por defecto:

Agregamos una nueva clase llamada mPrintDocument:

Antes de continuar, agregamos varias referencias al nuevo proyecto (utilizando el botn derecho del
Mouse sobre References:

Una para System.Drawing

Y otra para System.Windows.Forms:


Nuestro proyecto quedar as:

Nota: en la imagen se muestran algunos formularios que aun no se han realizado. stos se desarrollarn
posteriormente.
Agregamos las siguientes directivas using (nicamente si no estn), para que quede mas o menos as:
using System.Drawing.Printing;
using System;
using System.Windows.Forms;

using System.Drawing;
namespace Ticket
{
class mPrintDocument
{
//Aqui ir todo el cdigo
}
}

En la parte que dice Aqu ir todo el cdigo poner lo siguiente:


//Aqui ir todo el cdigo
/// <summary>
/// Punto de entrada de la clase
/// </summary>
/// <param name=prmText">Texto que ser impreso</param>"
public mPrintDocument(string prmText){
//Constructor
InitializeComponent();
txtDocument.Text = prmText;
leftmargin = pdoc.DefaultPageSettings.Margins.Left;
topmargin = pdoc.DefaultPageSettings.Margins.Top;
}
private PrintDocument pdoc = new PrintDocument();
private TextBox txtDocument = new TextBox();
static int intCurrentChar;
private string text = "UAT-UAMCAV";
private int fontsize = 10;
private string fontname = "Courier New";
int leftmargin = 0;
int rightmargin = 0;
int topmargin = 0;
int bottommargin = 0;
protected void InitializeComponent(){
pdoc.PrintPage += new
PrintPageEventHandler(pDoc_PrintPage);
}
public string Text{
get{
return (text);
}
set{
text = value;
}
}
/// <summary>
/// Propiedad FontSize, Representa
/// el tamao de la fuente
/// </summary>
/// <value>Representa el tamao de la fuente</value>
public int FontSize{
set{
fontsize = value;
}
get{
return (fontsize);
}
}
/// <summary>
/// Propiedad FontName, Representa
/// el nombre de la fuente
/// </summary>
public string FontName{
set{
fontname = value;
}
get{
return (fontname);
}
}
/// <summary>

/// Representa la distancia entre el contenido


/// y el borde izquierdo de la pgina
/// </summary>
public int LeftMargin{
set{
leftmargin = value;
}
get{
return (leftmargin);
}
}
/// <summary>
/// Representa la distancia entre el contenido
/// y el borde derecho de la pgina
/// </summary>
public int RightMargin{
set{
rightmargin = value;
}
get{
return (rightmargin);
}
}
/// <summary>
/// Representa la distancia entre el contenido
/// y el borde superior de la pgina
/// </summary>
public int TopMargin{
set{
topmargin = value;
}
get{
return (topmargin);
}
}
/// <summary>
/// Representa la distancia entre el contenido y
/// el borde inferior de la pgina
/// </summary>
public int BottomMargin{
set{
bottommargin = value;
}
get{
return (bottommargin);
}
}
/// <summary>
/// Mostrar en pantalla
/// </summary>
public void PrintPreview(){
PrintPreviewDialog ppd = new PrintPreviewDialog();
try{
ppd.Document = pdoc;
ppd.ShowDialog();
}
catch{
MessageBox.Show("Error al intentar cargar " +
"la vista preeliminar el documento", this.Text,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// Mandar directamente a la impresora
/// </summary>
public void Print(){
PrintDialog dialog = new PrintDialog();
dialog.Document = pdoc;
if (dialog.ShowDialog() == DialogResult.OK){
pdoc.Print();
}
}

void pDoc_PrintPage(object sender, PrintPageEventArgs e){


Font font = new Font(fontname, fontsize);
int intPrintAreaHeight;
int intPrintAreaWidth;
intPrintAreaHeight = pdoc.DefaultPageSettings.PaperSize.Height pdoc.DefaultPageSettings.Margins.Top pdoc.DefaultPageSettings.Margins.Bottom;
intPrintAreaWidth = pdoc.DefaultPageSettings.PaperSize.Width pdoc.DefaultPageSettings.Margins.Left pdoc.DefaultPageSettings.Margins.Right;
if (pdoc.DefaultPageSettings.Landscape){
int intTemp = intPrintAreaHeight;
intPrintAreaHeight = intPrintAreaWidth;
intPrintAreaWidth = intTemp;
}
int intLineCount = (int)(intPrintAreaHeight / font.Height);
RectangleF rectPrintingArea = new RectangleF(leftmargin, topmargin,
intPrintAreaWidth, intPrintAreaHeight);
StringFormat fmt = new StringFormat(StringFormatFlags.LineLimit);
int intLinesFilled;
int intCharsFitted;
e.Graphics.MeasureString(txtDocument.Text.Substring(intCurrentChar), font,
new SizeF(intPrintAreaWidth, intPrintAreaHeight), fmt,
out intCharsFitted, out intLinesFilled);
e.Graphics.DrawString(txtDocument.Text.Substring(intCurrentChar), font,
Brushes.Black, rectPrintingArea, fmt);
intCurrentChar += intCharsFitted;
if (intCurrentChar < (txtDocument.Text.Length - 1)){
e.HasMorePages = true;
}
else{
e.HasMorePages = false;
intCurrentChar = 0;
}
}

Una vez terminado lo anterior, nos vamos donde dice proTienda_MATRICULA y, con el botn derecho
del mouse, seleccionamos Add Reference como se muestra a continuacin:

Nos vamos a la pestaa Projects y seleccionamos Ticket

Le damos OK.
Nuestro proyecto, finalmente quedar as:

El objetivo principal de la Librera Ticket es poder mandar a la pantalla el ticket correspondiente a la venta,
pero en realidad se podr imprimir prcticamente cualquier texto. En el ejercicio 5 podremos comprobarlo.

Crear un punto de venta (5 de 10)

Inicio Anterior Siguiente Final


Consulta de ventas
Lo que haremos en esta ocasin es una pantalla para consultar ventas.
1. Agregar un formulario con el nombre frmConsultaVentas
2. Agregar un ListView con el nombre lvListaVentas

Propiedades del ListView:


Name= lvListaVentas
Dock=Fill
GridLines=True
Creamos este procedimiento:
private void Encabezados()
{
lvListaVentas.View = View.Details;
lvListaVentas.Columns.Add("Ticket", 90,
HorizontalAlignment.Left);
lvListaVentas.Columns.Add("Fecha", 175,
HorizontalAlignment.Left);
lvListaVentas.Columns.Add("Caja", 50,
HorizontalAlignment.Center);
lvListaVentas.Columns.Add("Cajero", 175,
HorizontalAlignment.Left);
lvListaVentas.Columns.Add("Total", 150,
HorizontalAlignment.Right);
}

Luego agregamos este otro procedimiento:


private void ReadData(){
//Este procedimiento lee los datos
//que se tranferirn y los mostrar en forma de
//lista en el ListView
try{
string varSQL = "SELECT V.FOLIO, V.FECHA,"+
" V.ID_CAJA as CAJA, "+
" U.NOMBRE + ' ' +" +
" U.PATERNO + ' ' + U.MATERNO as CAJERO,"+
" SUM(DV.CANTIDAD * DV.P_UNITARIO) AS TOTAL" +
" FROM USERS U INNER "+
" JOIN (CAT_PRODUCTOS P INNER JOIN "+
" (VENTAS V INNER "+
" JOIN DETALLE_VENTAS DV ON V.FOLIO = DV.FOLIO) "+

" ON P.ID_PRODUCTO = DV.ID_PRODUCTO)"+


" ON U.USER_NAME = V.USER_NAME"+
" GROUP BY V.FOLIO, V.FECHA, V.ID_CAJA, U.NOMBRE,"+
" U.PATERNO, U.MATERNO";
double varTOTAL = 0;
//Si la conexion esta abierta la cerramos
//en caso contrario, la abrimos
OleDbConnection cnnReadData =
new OleDbConnection(Class.clsMain.CnnStr);
if (cnnReadData.State == ConnectionState.Open)
cnnReadData.Close();
else cnnReadData.Open();
int I = 0;
OleDbCommand cmdReadData =
new OleDbCommand(varSQL, cnnReadData);
OleDbDataReader drReadData;
drReadData = cmdReadData.ExecuteReader();
lvListaVentas.Items.Clear();
while (drReadData.Read()){
lvListaVentas.Items.
Add(drReadData["FOLIO"].ToString());
lvListaVentas.Items[I].
SubItems.Add(drReadData["FECHA"].ToString());
lvListaVentas.Items[I].
SubItems.Add(drReadData["CAJA"].ToString());
lvListaVentas.Items[I].
SubItems.Add(drReadData["CAJERO"].ToString());
lvListaVentas.Items[I].
SubItems.Add(String.Format("{0:C}",
drReadData["TOTAL"]));
varTOTAL += Convert.ToDouble(drReadData["TOTAL"]);
I += 1;
}
//Agregamos un registro ms
if (I != 0) {
lvListaVentas.Items.Add("");
lvListaVentas.Items[I].SubItems.Add("");
lvListaVentas.Items[I].SubItems.Add("");
lvListaVentas.Items[I].SubItems.Add("Gran Total:");
lvListaVentas.Items[I].
SubItems.Add(String.Format("{0:C}", varTOTAL));
}
drReadData.Close();
cmdReadData.Dispose();
cnnReadData.Close();
}
catch (Exception ex){
MessageBox.Show(ex.Message, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

Agregamos el siguiente cdigo en el FormLoad:


Encabezados();
ReadData();

Listo!!!!

Crear un punto de venta (6 de 10)


Inicio Anterior Siguiente Final
Bsqueda de productos

Lo que vamos a hacer hoy es una pantalla que nos permita buscar productos, que los muestre en la
pantalla y que podamos ver la informacin que se tenga de ellos.
A partir de este momento programaremos para lograr que los objetos (Formularios, Clases, Dll)
interacten entre s. Por ejemplo, lograremos que al momento de generar un ticket de venta la pantalla en
la que se haga el cobro ya sepa la cantidad que se cobrar al cliente en base al folio que tenga el ticket.
Todo esto lo haremos en base a constructores.
Agregaremos varios formularios a nuestro proyecto para que quede como se muestra:

Si no me equivoco, frmBuscaProducto, frmCobrar, frmVentas. Hoy nos enfocamos a frmBuscaProducto y


dejamos el resto para despus.
Disearemos frmBuscaProducto para que quede como se muestra:

Le deberemos de agregar una Label, un TextBox, un Button y un ListView, segn la siguiente tabla:

Nos vamos directamente al cdigo y tecleamos lo siguiente en la seccin de las directivas using
(nicamente si no est la lnea):
using System.Data.OleDb;

En la seccin de declaraciones ponemos:


//Declaraciones
public string varID_PRODUCTO = "";

Crearemos el siguiente procedimiento, el cual nos ayudar para poner columnas en el ListView:
private void Encabezados()
{
lvProductos.View = View.Details;
lvProductos.Columns.Add("Clave producto", 0,
HorizontalAlignment.Left);
lvProductos.Columns.Add("Descripcin", 250,
HorizontalAlignment.Left);
lvProductos.Columns.Add("Existencia", 90,
HorizontalAlignment.Right);
lvProductos.Columns.Add("Precio", 90,
HorizontalAlignment.Right);
}

Despus agregamos el siguiente:


private void Producto()
{
try
{
if (lvProductos.Items.Count != 0)
{
varID_PRODUCTO = lvProductos.SelectedItems[0].Text;
}
else
{
varID_PRODUCTO = "";
}
this.Close();
}
catch (Exception ex)
{
MessageBox.Show("Debe seleccionar un elemento de la lista."+
" \nDescripcin del error: \n" + ex.Message,
"Operacin no vlida", MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
}

Agregamos este otro procedimiento:


private void ReadData(string prmDESC_PRODUCTO){
//Este procedimiento lee los datos que se

//tranferirn y los mostrar en forma de


//lista en el ListView
try {
//Si la conexion esta abierta la cerramos;
//en caso contrario, la abrimos
OleDbConnection cnnReadData =
new OleDbConnection(Class.clsMain.CnnStr);
if (cnnReadData.State == ConnectionState.Open)
cnnReadData.Close();
else cnnReadData.Open();
int I = 0;
OleDbCommand cmdReadData =
new OleDbCommand("SELECT ID_PRODUCTO,"+
" DESC_PRODUCTO,"+
" CANTIDAD,P_U_VENTA " +
" FROM CAT_PRODUCTOS"+
" WHERE DESC_PRODUCTO like '%" +
prmDESC_PRODUCTO + "%'", cnnReadData);
OleDbDataReader drReadData;
drReadData = cmdReadData.ExecuteReader();
lvProductos.Items.Clear();
while (drReadData.Read()){
lvProductos.Items.
Add(drReadData["ID_PRODUCTO"].ToString());
lvProductos.Items[I].SubItems.
Add(drReadData["DESC_PRODUCTO"].ToString());
lvProductos.Items[I].SubItems.
Add(drReadData["CANTIDAD"].ToString());
lvProductos.Items[I].SubItems.
Add(String.Format("{0:C}",
drReadData["P_U_VENTA"]));
I += 1;
}
drReadData.Close();
cmdReadData.Dispose();
cnnReadData.Close();
}
catch (Exception ex){
MessageBox.Show(ex.Message);
}
}

Pondremos lo siguiente el Form_Load:


//Form_Load
this.lvProductos.DoubleClick +=
new System.EventHandler(this.lvProductos_DoubleClick);
this.lvProductos.KeyPress +=
new System.Windows.Forms.KeyPressEventHandler(this.lvProductos_KeyPress);
Encabezados();

Y justo despus del Form_Load ponemos lo siguiente:


void lvProductos_KeyPress(object sender,
System.Windows.Forms.KeyPressEventArgs e){
switch (e.KeyChar){
case (char)Keys.Enter:
Producto();
break;
case (char)Keys.Escape:
varID_PRODUCTO = "";
this.Close();
break;
}
}
void lvProductos_DoubleClick(object sender,
System.EventArgs e){
Producto();
}

Deber escribirse el cdigo tal y cual se muestra, ya que se tratan de procedimientos creados por
nosotros mismos.
Hacemos soble clic en el boton (btnBuscar) y le agregamos el siguiente cdigo:
ReadData(txtDESC_PRODUCTO.Text);

Si todo va bien y no nos hemos equivocado, hemos terminado satisfactoriamente el ejercicio.

Crear un punto de venta (7 de 10)


Inicio Anterior Siguiente Final
Pantalla para cobrar e imprimir el ticket de venta
Tenemos un formulario llamado frmCobrar, nos centraremos en l para lograr nuestro objetivo.
Deberemos disearlo como se muestra:

Agregamos tres Label, tres TextBox y un Button. Segn la siguiente tabla:

Para lograr que tome el tamao adecuado, disear al gusto


En donde las directivas using, poner una ms:
using System.Data.OleDb;

Localizamos el constructor, debe ser uno idntico al que se muestra:


public frmCobrar()
{
InitializeComponent();
}

Nosotros agregaremos uno ms:


public frmCobrar(int prmFolio){
InitializeComponent();
varFolio = prmFolio;
}

Justo debajo del constructor que acabamos de agregar, declaramos dos variables:
int varFolio=0;
double varTotal = 0;

Damos doble clic en el formulario y ponemos lo siguiente dentro del Form_Load:


//Form_Load
this.txtEfectivo.TextChanged +=
new EventHandler(txtEfectivo_TextChanged);
varTotal = fnCalculaPago(varFolio);
txtTotal.Text = String.Format("{0:C}", varTotal);

Inmediatamente despus del Form_Load, creamos el siguiente procedimiento (Fuera del Form_Load):
void txtEfectivo_TextChanged(object sender, EventArgs e){
try{
txtCambio.Text = String.Format("{0:C}",
(Convert.ToDouble(txtEfectivo.Text) - varTotal));
}
catch (Exception ex){
txtCambio.Text = ex.Message;
}
}

La lnea que est marcada con negritas indica que se crear un procedimiento para cuando una tecla sea
presionada si el TextBox tiene el foco.
Tambin agregamos este otro procedimiento:
private double fnCalculaPago(int prmFolio) {
try {
OleDbConnection _cnnCalculaPago =
new OleDbConnection(Class.clsMain.CnnStr);
_cnnCalculaPago.Open();
OleDbCommand _cmdCalculaPago =
new OleDbCommand("SELECT SUM(CANTIDAD*P_UNITARIO) "+
"FROM DETALLE_VENTAS "+
"WHERE FOLIO="+ prmFolio +"", _cnnCalculaPago);
double _return =
Convert.ToDouble(_cmdCalculaPago.ExecuteScalar());
_cnnCalculaPago.Close();
_cnnCalculaPago.Dispose();
_cmdCalculaPago.Dispose();
return (_return);
}
catch (Exception ex) {
MessageBox.Show(ex.Message,"fnCalculaPago");
return (0);
}
}

Hacemos soble clic sobre el botn (btnOk) y ponemos el siguiente cdigo:


if (txtEfectivo.Text != ""){
DialogResult _Resp = new DialogResult();
_Resp = MessageBox.Show("Desea imprimir el ticket?",
"Ticket", MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (_Resp == DialogResult.Yes){
//Imprmmir el ticket
GenerarTicket(varFolio);
this.Close();
}
else{
this.Close();
}
}
else {
MessageBox.Show("Debe introducir una cantidad",
"Faltan datos");
}

Ahora cramos el procedimiento que nos mostrar el ticket de venta:


Ojo, para que este funcione deberemos haber hecho bin el ejercicio de la Dll.
private void GenerarTicket(int prmFOLIO) {
try{
string Ticket = "Nombre de la tienda: UAMCAV\n" +
"RFC:XXXXXX\n" +
"------------------------------\n" +
"ARTICULO
CANT
PRECIO
TOTAL\n" +
"------------------------------\n";
string varSQL =
"SELECT LEFT(DESC_PRODUCTO,10) as DESC_PRODUCTO," +
" CANTIDAD,P_UNITARIO,TOTAL" +
" FROM vVENTAS WHERE FOLIO=" + prmFOLIO + "";
string DetalleTicket = "";
double varGranTotal = 0;
OleDbConnection cnnTicket =
new OleDbConnection(Class.clsMain.CnnStr);
cnnTicket.Open();

OleDbCommand cmdTicket =
new OleDbCommand(varSQL, cnnTicket);
OleDbDataReader drTicket;
drTicket = cmdTicket.ExecuteReader();
while (drTicket.Read()){
DetalleTicket +=
drTicket["DESC_PRODUCTO"].ToString() + "
drTicket["CANTIDAD"].ToString() + "
" +
String.Format("{0:C}",
drTicket["P_UNITARIO"]) + "
" +
String.Format("{0:C}",
drTicket["TOTAL"]) + "\n";
varGranTotal += (double)drTicket["TOTAL"];
}
DetalleTicket +=
"------------------------------\n" +
"TOTAL: " + String.Format("{0:C}",
varGranTotal);
Ticket += DetalleTicket;
mPrintDocument _mPrintDocument =
new mPrintDocument(Ticket);
_mPrintDocument.PrintPreview();

" +

}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}

Listo,... por el momento solo debemos compilarlo para asegurarnos de que no tenga errores

Crear un punto de venta (8 de 10)


Inicio Anterior Siguiente Final
Pantalla de Ventas
Hemos llegado a la parte ms difcil de esta serie de 10 ejercicios, las ventas. Todo tiene que estar bien
en los ejercicios anteriores ya que nos serviremos de ellos para tener xito en lo subsiguiente.
Para no tener problemas, recomiendo que lean los textos que voy a exponer, ya que antes de empezar a
escribir algn cdigo explicar e intentar dejar claro que es lo que se va a hacer, por que se va a hacer
as y, de ser posible, har aclaraciones de el por que es la mejor manera de hacerlo as.
Antes de comenzar, demos un vistazo sobre el funcionamiento de la aplicacin:
Iniciando sesin:

Aqu se pone el nombre de usuario y la contrasea. No tiene gran dificultad.


Si por algn motivo nuestra aplicacin est en RED, podemos ubicar el archivo de base de datos por
medio del link que est subrayado de azul:

Solo bastar buscar la ruta de la base de datos entre las ubicaciones de red disponibles y listo.
Cuando entramos, lo primero que vemos es lo siguiente:

Tiene varios mens los cuales nos llevan a diferentes opciones del sistema. Nos centraremos en el de
Ventas:

Si presionamos el botn buscar producto:

Al seleccionar uno, y hacindole doble clic:

En este momento podemos ponerle otra cantidad para que, al presionar Enter:

Luego, presionamos el Botn Realizar venta:

Podemos presionar Enter y ocurre lo siguiente:

Si elegimos Yes

Es una visin general de lo que lograremos una vez terminado este ejercicio.
Iniciemos de una vez
Vamos a intentar lograr lo imposible, intentaremos entender la mentalidad de un desarrollador profesional,
nos enredaremos la cabeza con cdigo avanzado que probablemente no entenderemos por ms que nos
expliquen. Solo vamos a centrar nuestra atencin en hacer las cosas al pi de la letra y os aseguro que
tendremos xito.
Disearemos frmVentas como se muestra a continuacin:

Agregaremos un Listview, 5 Label, 4 TextBox y 4 Button, como se muestra en la tabla:

El cuarto botn solo es para dar una mejor vista, se pone debajo de los otros tres, para efectos prcticos
puede ser omitido.
Agregaremos un constructor, justo debajo del constructor que ofrece predeterminadamente:
public frmVentas(string prmUSER_LOGIN,int prmID_CAJA){
InitializeComponent();
varID_CAJA = prmID_CAJA;
varUSER_LOGIN = prmUSER_LOGIN;
}

Luego declaramos unas variables:


//Declaraciones
string varUSER_LOGIN = frmLogin._USER_NAME;
int varID_CAJA=1;

La primera variable nos servir para saber el nombre con el que inici sesin el usuario, la segunda es
por que nuestro sistema podra soportar un indefinido nmero de cajas, claro que para este caso solo
ser una.
Ahora pondremos lo siguiente en el Form_Load:
//Form_Load
Headers();
ReadData(varUSER_LOGIN, varID_CAJA);
this.txtCANTIDAD.KeyPress +=
new System.Windows.Forms.
KeyPressEventHandler(this.txtCANTIDAD_KeyPress);
this.txtCANTIDAD.KeyDown +=
new System.Windows.Forms.
KeyEventHandler(this.txtCANTIDAD_KeyDown);
this.txtID_PRODUCTO.KeyPress +=
new System.Windows.Forms.
KeyPressEventHandler(this.txtID_PRODUCTO_KeyPress);
this.txtID_PRODUCTO.KeyDown +=
new System.Windows.Forms.
KeyEventHandler(this.txtID_PRODUCTO_KeyDown);

El cdigo anterior nos sirve para mandar llamar varios procedimientos que son importantes al momento
de que sea llamado el formulario. Claro que es necesario lo siguiente para que lo anterior tenga sentido:

void Headers()
{
//Encabezados del litView
lvVenta.View = View.Details;
lvVenta.Columns.Add("Producto", 100,
HorizontalAlignment.Left);
lvVenta.Columns.Add("Descripcion", 250,
HorizontalAlignment.Left);
lvVenta.Columns.Add("Cant", 75,
HorizontalAlignment.Right);
lvVenta.Columns.Add("Prec", 75,
HorizontalAlignment.Right);
lvVenta.Columns.Add("Iva", 75,
HorizontalAlignment.Right);
lvVenta.Columns.Add("Total", 100,
HorizontalAlignment.Right);
}

void txtCANTIDAD_KeyPress(object sender,KeyPressEventArgs e){


try{
lblMensaje.Text = "";
if (!((txtID_PRODUCTO.Text == "") ||
(txtCANTIDAD.Text == ""))){
if (e.KeyChar == 13){
//Insertar cdigo aqui
SaveTemp_Ventas(txtID_PRODUCTO.Text,
Convert.ToDouble(txtCANTIDAD.Text));
txtID_PRODUCTO.Focus();
}
}
else{
lblMensaje.Text = "Debe introducir una "+
"clave de producto y/o una cantidad";
}
}
catch (Exception ex){
MessageBox.Show(ex.Message);
}
}
void txtCANTIDAD_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.F5) {
RealizaVenta();
}
}
void txtID_PRODUCTO_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.F5) {
RealizaVenta();
}
}
void txtID_PRODUCTO_KeyPress(object sender, KeyPressEventArgs e) {
lblMensaje.Text = "";
try {
if (!((txtID_PRODUCTO.Text == "") ||
(txtCANTIDAD.Text == ""))) {
if (e.KeyChar == 13){
//Inserttar cdigo aqui
SaveTemp_Ventas(txtID_PRODUCTO.Text,
Convert.ToDouble(txtCANTIDAD.Text));
txtID_PRODUCTO.Focus();
}
}
else {
lblMensaje.Text = "Debe introducir una "+
"clave de producto y/o una cantidad";
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}

El cdigo anterior acta dependiendo del objeto del que se trate. Por ejemplo los que dicen KeyPress,
controlan el momento en que es presionada una tebla sobre el objeto, lo mismo ocurre con KeyDown,
solo que en este caso se trata de teclas especiales como las teclas F1-F12.
void SaveTemp_Ventas(string prmID_PRODUCTO,double prmCANTIDAD) {
double[] varProductDetails = new double[1];
varProductDetails =
FindProductDetails(prmID_PRODUCTO);
double varPRECIO = varProductDetails[0];
try {
if (varPRECIO ==0.0) {
lblMensaje.Text =
"El producto no existe!!!";
}
else {
Temp_Ventas(varUSER_LOGIN , varID_CAJA ,
prmID_PRODUCTO , prmCANTIDAD, varPRECIO);
ReadData(varUSER_LOGIN , varID_CAJA );
}
}
catch (Exception ex) {
MessageBox.Show(ex.Message, "Error");
}
}

void ReadData(string prmUSER_NAME,int prmID_CAJA) {


lblMensaje.Text = "";
double varIVA = 0.0;
double varGRAND_TOTAL = 0.0;
try {
OleDbConnection cnnReadData =
new OleDbConnection(Class.clsMain.CnnStr);
string varSQL = "SELECT CAT_PRODUCTOS.ID_PRODUCTO, "+
" CAT_PRODUCTOS.DESC_PRODUCTO," +
" TEMP_VENTAS.CANTIDAD, "+
" TEMP_VENTAS.P_UNITARIO, "+
" TEMP_VENTAS.IVA,"+
" (TEMP_VENTAS.CANTIDAD*"+
" TEMP_VENTAS.P_UNITARIO) AS TOTAL" +
" FROM CAT_PRODUCTOS "+
" INNER JOIN TEMP_VENTAS" +
" ON CAT_PRODUCTOS.ID_PRODUCTO = "+
" TEMP_VENTAS.ID_PRODUCTO "+
" WHERE TEMP_VENTAS.USER_NAME ='" +
prmUSER_NAME + "'";
int I = 0;
OleDbCommand cmdReadData =
new OleDbCommand(varSQL, cnnReadData);
OleDbDataReader drReadData;
if(cnnReadData.State == ConnectionState.Open)
cnnReadData.Close();
cnnReadData.Open();
drReadData = cmdReadData.ExecuteReader();
lvVenta.Items.Clear();
while (drReadData.Read()) {
lvVenta.Items.
Add(drReadData["ID_PRODUCTO"].ToString());
lvVenta.Items[I].SubItems.
Add(drReadData["DESC_PRODUCTO"].ToString());
lvVenta.Items[I].SubItems.
Add(drReadData["CANTIDAD"].ToString());
lvVenta.Items[I].SubItems.
Add(drReadData["P_UNITARIO"].ToString());
lvVenta.Items[I].SubItems.
Add(drReadData["IVA"].ToString() + " %");
lvVenta.Items[I].SubItems.
Add(String.Format("{0:C}", drReadData["TOTAL"]));
//Obtenemos el Grand Total y el Iva
varGRAND_TOTAL += Convert.ToDouble(drReadData[5]);
varIVA += Convert.ToDouble(drReadData["IVA"]) *
((Convert.ToDouble(drReadData["TOTAL"]))/100);
I += 1;
}

drReadData.Close();
cmdReadData.Dispose();
cnnReadData.Close();
cnnReadData.Dispose();
txtGRAND_TOTAL.Text =
String.Format("{0:C}",
varGRAND_TOTAL);
txtIVA.Text =
String.Format("{0:C}", varIVA);
}
catch (Exception ex) {
MessageBox.Show (ex.Message);
}
}
void Temp_Ventas(string prmUSER_LOGIN,int prmID_CAJA,
string prmID_PRODUCTO,double prmCANTIDAD,
double prmPRECIO) {
//Para cargar la venta tenporal
string varSQL = "";
try {
OleDbConnection cnnTempVentas =
new OleDbConnection(Class.clsMain.CnnStr);
if (GetSale(prmUSER_LOGIN, prmID_CAJA,
prmID_PRODUCTO) == 0){
varSQL = "INSERT INTO TEMP_VENTAS(USER_NAME,"+
"ID_PRODUCTO,CANTIDAD,P_UNITARIO,IVA)" +
" VALUES('" + prmUSER_LOGIN + "','" +
prmID_PRODUCTO +
"'," + prmCANTIDAD + "," +
prmPRECIO + ",0)";
}
else {
varSQL = "UPDATE TEMP_VENTAS "+
"SET CANTIDAD = CANTIDAD + "+
prmCANTIDAD +"" +
" WHERE USER_NAME = '"+
prmUSER_LOGIN +"'" +
" AND ID_PRODUCTO = '"+
prmID_PRODUCTO +"'";
}
OleDbCommand cmdTempVentas =
new OleDbCommand(varSQL, cnnTempVentas);
if (cnnTempVentas.State == ConnectionState.Open)
cnnTempVentas.Close();
cnnTempVentas.Open();
cmdTempVentas.ExecuteNonQuery();
cnnTempVentas.Close();
cmdTempVentas.Dispose();
cnnTempVentas.Dispose();
txtID_PRODUCTO.Text = "";
txtCANTIDAD.Text = "1";
}
catch(Exception ex) {
MessageBox.Show(ex.Message,"TempVentas");
}
}
double[] FindProductDetails(string prmID_PRODUCTO){
double[] Retorno = new double[2];
try {
OleDbConnection cnnFindProductDetails =
new OleDbConnection(Class.clsMain.CnnStr);
string varSQL = "SELECT count(*) "+
"FROM CAT_PRODUCTOS "+
"WHERE ID_PRODUCTO = '" +
prmID_PRODUCTO + "'";
OleDbCommand cmdFindProductDetails =
new OleDbCommand();
cmdFindProductDetails.Connection =
cnnFindProductDetails;
cmdFindProductDetails.CommandText = varSQL;
if (cnnFindProductDetails.State == ConnectionState.Open)
cnnFindProductDetails.Close();

cnnFindProductDetails.Open();
if (!(Convert.ToInt32(cmdFindProductDetails.ExecuteScalar()) == 0)) {
varSQL = "SELECT P_U_VENTA "+
" FROM CAT_PRODUCTOS "+
"WHERE ID_PRODUCTO ='" +
prmID_PRODUCTO + "'";
cmdFindProductDetails.CommandText = varSQL;
Retorno[0] = Convert.
ToDouble(cmdFindProductDetails.ExecuteScalar());
varSQL = "SELECT IVA "+
"FROM CAT_PRODUCTOS "+
"WHERE ID_PRODUCTO ='" +
prmID_PRODUCTO + "'";
cmdFindProductDetails.CommandText = varSQL;
Retorno[1] = Convert.
ToDouble(cmdFindProductDetails.ExecuteScalar());
}
else {
Retorno[0] = 0.0;
Retorno[1] = 0.0;
}
cmdFindProductDetails.Dispose();
cnnFindProductDetails.Close();
cnnFindProductDetails.Dispose();
return (Retorno);
}
catch (Exception ex) {
MessageBox.Show(ex.Message,
"FindProductDetails");
return (Retorno);
}
}
double GetSale(string prmUSER_LOGIN,int prmID_CAJA,
string prmID_PRODUCTO){
//Para cargar la venta tenporal
double Retorno;
try {
OleDbConnection cnnGetSale =
new OleDbConnection(Class.clsMain.CnnStr);
string varSQL = "SELECT COUNT(*) FROM TEMP_VENTAS " +
" WHERE USER_NAME = '"+ prmUSER_LOGIN +"' " +
" AND ID_PRODUCTO = '"+ prmID_PRODUCTO +"'";
OleDbCommand cmdGetSale =
new OleDbCommand(varSQL, cnnGetSale);
if (cnnGetSale.State == ConnectionState.Open)
cnnGetSale.Close();
cnnGetSale.Open();
Retorno = Convert.
ToDouble(cmdGetSale.ExecuteScalar());
cmdGetSale.Dispose();
cnnGetSale.Close();
cnnGetSale.Dispose();
return (Retorno);
}
catch (Exception ex){
MessageBox.Show(ex.Message,"GetSale");
return (0);
}
}
private void RealizaVenta() {
if (lvVenta.Items.Count != 0)
{
int varFolio = RealizaVenta(varUSER_LOGIN, varID_CAJA);
if (varFolio != 0)
{
frmCobrar _frmCobrar = new frmCobrar(varFolio);
_frmCobrar.StartPosition = FormStartPosition.CenterScreen;
_frmCobrar.ShowDialog();
}
}
}

private int RealizaVenta(string prmUSER_LOGIN, int prmID_CAJA){


int varFolio = 0;
try{
OleDbConnection cnnInsert =
new OleDbConnection(Class.clsMain.CnnStr);
cnnInsert.Open();
OleDbCommand cmdInsert = new OleDbCommand();
cmdInsert.Connection = cnnInsert;
//insertamos el registro padre
cmdInsert.CommandText =
"INSERT INTO VENTAS (USER_NAME,ID_CAJA,FECHA) " +
"VALUES('" + prmUSER_LOGIN +
"'," + prmID_CAJA + ",NOW())";
cmdInsert.ExecuteNonQuery();
//obtenemos el autonumerico
cmdInsert.CommandText = "SELECT @@IDENTITY";
varFolio = Convert.ToInt32(cmdInsert.ExecuteScalar());
//GENERAMOS LA VENTA
cmdInsert.CommandText =
"INSERT INTO DETALLE_VENTAS "+
" (ID_PRODUCTO,FOLIO,CANTIDAD,P_UNITARIO,IVA)"+
" SELECT ID_PRODUCTO,"+ varFolio +","+
" CANTIDAD,P_UNITARIO,IVA "+
" FROM TEMP_VENTAS "+
" WHERE USER_NAME ='"+ prmUSER_LOGIN +"'";
cmdInsert.ExecuteNonQuery();
//ACTUALIZAMOS LAS EXISTENCIAS
cmdInsert.CommandText = "UPDATE CAT_PRODUCTOS "+
" INNER JOIN TEMP_VENTAS "+
" ON CAT_PRODUCTOS.ID_PRODUCTO = "+
" TEMP_VENTAS.ID_PRODUCTO "+
" SET CAT_PRODUCTOS.CANTIDAD = "+
" CAT_PRODUCTOS.CANTIDAD-[TEMP_VENTAS].[CANTIDAD]"+
" WHERE (([TEMP_VENTAS].[USER_NAME]= "+
" '"+ prmUSER_LOGIN +"'));";
cmdInsert.ExecuteNonQuery();
//borramos las ventas temporales
cmdInsert.CommandText = "DELETE FROM TEMP_VENTAS " +
" WHERE USER_NAME = '" + prmUSER_LOGIN + "'";
cmdInsert.ExecuteNonQuery();
//LIBERAMOS LOS RECUSROS
cnnInsert.Close();
cnnInsert.Dispose();
cmdInsert.Dispose();
//mostramos la info
ReadData(varUSER_LOGIN, varID_CAJA);
return (varFolio);
}
catch (Exception ex){
MessageBox.Show(ex.Message, "RealizaVenta");
return (0);
}
}
private void DeshacerVenta(string prmUSER_LOGIN,int prmID_CAJA) {
OleDbConnection conDeshacerVenta;
OleDbCommand cmdDeshacerVenta;
string strSQL_Delete = "DELETE FROM TEMP_VENTAS " +
" WHERE USER_NAME = '" + prmUSER_LOGIN + "' ";
try{
conDeshacerVenta =
new OleDbConnection(Class.clsMain.CnnStr);
conDeshacerVenta.Open();
cmdDeshacerVenta =
new OleDbCommand(strSQL_Delete, conDeshacerVenta);
cmdDeshacerVenta.ExecuteNonQuery();
cmdDeshacerVenta.Dispose();
conDeshacerVenta.Close();
ReadData(varUSER_LOGIN, varID_CAJA);
}
catch(Exception ex){
MessageBox.Show(ex.Message,"DeshacerVenta");
}
}

Hacemos doble clic sobre btnBuscarProducto:


try{
frmBuscaProducto myForm = new frmBuscaProducto();
myForm.StartPosition = FormStartPosition.CenterScreen;
myForm.ShowDialog();
if (!(myForm.varID_PRODUCTO == "")){
txtID_PRODUCTO.Text = myForm.varID_PRODUCTO;
txtID_PRODUCTO.Focus();
}
myForm.Dispose();
}
catch (Exception ex) {
MessageBox.Show(ex.Message, "btnBuscaProducto", MessageBoxButtons.OK,
MessageBoxIcon.Error);
txtID_PRODUCTO.Text = "";
}

Luego sobre btnRealizarVenta:


RealizaVenta();

Para btnCerrar:
this.Close();

Vamos a suponer que todo lo anterior lo hemos hecho bien; lo que resta es poner en mdiMain el cdigo
correspondiente para mandar llamar al formulario de las ventas. Para conseguirlo deberemos hacer lo
siguiente:
Hacemos doble clic sobre el men Punto de venta:

Le ponemos el siguiente cdigo:


frmVentas _frmVentas =
new frmVentas(frmLogin._USER_NAME,1);
_frmVentas.MdiParent = this;
_frmVentas.StartPosition =
FormStartPosition.Manual;
_frmVentas.Show();

Crear un punto de venta (9 de 10)


Inicio Anterior Siguiente Final
Instalar la aplicacin
Para instalar la aplicacin basta con copiar los archivos de resultados, generalmente contenidos en las
carpetas "Debug"o "Release".

Nota: Es importante que el equipo en donde vayas a copiar los archivos est instalado el .Net Framework
correspondiente.

You might also like