Vous êtes sur la page 1sur 59

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: PROPEDAD VALOR Name Name lblUSER_NAME lblPASSWORD txtUSER_NAME txtPASSWORD btnOK btnCANCEL frmLogin

OBJETO Label Label

TextBox Name TextBox Name Button Button Form Name Name Name

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 (Falso-Verdadero). 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; Comentarios o dudas, en la seccin de comentarios o al mail musikin@gmail.com Suerte

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

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. Suerte y hasta la prxima...

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 using using using System.Drawing.Printing; System; System.Windows.Forms; 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. Suerte ...

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

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. Recomendaciones:

1. Hacer respaldos del sistema segn se vaya avanzando en el desarrollo. 2. Guardar los cambios peridicamente 3. Tener mucho cuidado en donde colocamos nuestro cdigo. Una instruccin mal colocada puede echar a perder todo nuestro trabajo. 4. Para estos ejercicios, si lo pongo con mayscula, es mayscula y viceversa. No le hagamos al hroe, aun no tenemos la experiencia como para saber como funcionar mejor nuestro programa. 5. Nadie es perfecto. Puedo equivocarme, siempre pruebo el cdigo que estoy exponiendo, pero al momento de transcribirlo aqu pueden ocurrir errores.

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

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

Si todo nos ha salido bien, Hemos terminado

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.

Creacin de un programa de instalacin Hola amigos, para crear un programa de instalacin el .Net es realmente fcil. Solo debemos agregar un nuevo proyecto a la solucin, y seleccionar "Asistente para programas de instalacin". Seguir los pasos y listo.

Vous aimerez peut-être aussi