Crear un punto de venta (1 de 10

)
Inicio Anterior Siguiente Final Pantalla de inicio de Sesión Creamos un proyecto de Windows con el nombre proTienda_MATRICULA. Después 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 imágenes y/o Iconos para darle una mejor presentación al proyecto. No es obligatorio utilizarlos, pero en caso de estar interesado en conseguirlos, puedes intentar descargarlos desde la página de “La Web del Programador”. Antes de realizar cualquier cosa, asegurémonos 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: Diseño de la base de datos Diseño de las pantallas Programación Diseño de la base de datos:

Tenemos 10 tablas. Para la realización de este ejercicio solo utilizaremos la tabla USERS. Como esta es una clase de Lenguaje de programación, omitiremos al máximo las explicaciones relativas a Desarrollo de Base de datos. Solo se hace la aclaración que para los motivos educativos del presente curso, la base de datos aquí mostrada tiene el diseño óptimo.

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

Diseño 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. Según 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

Programación: Antes quiero hacer la aclaración de que al formulario mdiMain no se le hará ningún diseño por el momento. Comenzaremos por escribir el código para frmLogin.

Estructura del código:
//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 Computación 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 sección de las directivas using, agregaremos la siguiente instrucción:

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

En la sección 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 continuación, en la sección Funciones y Procedimientos agregamos el siguiente código:

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, "Información del Sistema"); return (Retorno); } }

Hacemos doble click en el botón btnOK y agregamos el siguiente código:

_Logged = fnLogin(txtUSER_NAME.Text, txtPASSWORD.Text); if (Intentos >= 3) { _Logged = false; MessageBox.Show("Demasiados intentos", "Información del sistema"); this.Close(); } if (_Logged) this.Close();

Al botón btnCANCEL, le agregamos lo siguiente:

this.Close();

Ahora agregamos el código 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!", "Información del sistema", MessageBoxButtons.OK, MessageBoxIcon.Error); } return (Retorno); } catch (Exception ex) { MessageBox.Show(ex.Message,"Información del Sistema", MessageBoxButtons.OK, MessageBoxIcon.Error); return (Retorno); }

} } } }

Explicaciones sobre el código:

Generalizando.- Cuando un usuario intente ingresar a nuestra aplicación le aparecerá una pantalla de Login para que intruduzca un nombre de usuario y una contraseña. Solo tendrá 3 oportunidades para ingresar antes de que se cierre la aplicación. Si el usuario ingresa un nombre de usuario y contraseña correctos, entonces entrará al sistema y verá la pantalla principal de la aplicación. Detalladamente.- Lo que hace la aplicación es verificar que el usuario exista en la tabla USERS, si existe significa que puede iniciar sesión 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 aplicación se cerrará. Podemos observar que utilizamos las intrucciones try-catch-finally, estas nos ayudarán para que en el caso de que ocurra un error en nuestra aplicación mientras es ejecutada, no tengamos mayores problemas. Utilizamos la propiedad State de la conexión, esta nos ayuda a saber si la conexión está abierta o cerrara. La utilizamos para evitar el error de intentar abrir una conexión abierta o cerrar una conexión cerrada lo cual es ilógico. La función fnLogin recibe dos parametros (Usuario y Contraseña) y retorna un valor booleano (Falso-Verdadero). La utilizamos para organizar nuestro código de tal manera que al ejecutarse la función podamos saber: True: Puede iniciar sesión y se cargan los datos del usuario a las variables False: No puede iniciar sesión por error/desconocer al escribir su nombre de usuario y contraseña y se le cuenta un intento de acceso. Las variables public static, son variables globales y pueden ser leidas desde cualquier parte de la aplicación con escribir el nombre del objeto, un punto y el nombre de la variable. Por ejemplo, si queremos saber apellido paterno el usuario haríamos lo siguiente: string varPATERNO = Forms.frmLogin._PATERNO; Comentarios o dudas, en la sección de comentarios o al mail musikin@gmail.com Suerte…

Utilidad para configurar la conexión a la base de datos Continuamos con el proyecto proTienda_MATRICULA. Contenido: • Diseño de las pantallas • Programación Diseño de las pantallas: La aplicación 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 realizarán posteriormente. El nuevo formulario (frmAppConfig), debe quedar como se muestra:

Le agregamos cinco Label, cinco TextBox y tres Button. Según la siguiente tabla:

Programación: Antes quiero hacer la aclaración de que al formulario mdiMain no se le hará ningún diseño por el momento. Comenzaremos por escribir el código para frmAppConfig. Estructura del código: //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 Computación 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 sección Declaraciones, agregamos lo siguiente:

Hacemos doble clic al formulario y ponemos el siguiente código 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 botón btnOK y agregamos el siguiente código: if (File.Exists(txtFileName.Text)) { System.Configuration.Configuration config = ConfigurationManager. OpenExeConfiguration(ConfigurationUserLevel.None); //Borramos la configuración 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 configuración 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!", "Información del sistema", MessageBoxButtons.OK, MessageBoxIcon.Error); }

Al botón btnCancel, le agregamos lo siguiente: this.Close();

Al botón btnSearch, le ponemos el siguiente código: 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; }

Después 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 código: 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 código de clsMain, que debe quedar como se muestra (he marcado con negrita la porción de código 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!", "Información del sistema", MessageBoxButtons.OK, MessageBoxIcon.Error); } return (Retorno); } catch (Exception ex) { MessageBox.Show(ex.Message, "Información del Sistema", MessageBoxButtons.OK, MessageBoxIcon.Error); return (Retorno); }

} } } }

Explicaciones sobre el código: Generalizando. Nuestra aplicación podrá leer la ruta de la base de datos en tiempo de ejecición. Esto nos da la gran posibilidad de poner nuestra aplicación 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 aplicación de Microsoft Office. Utilizamos un Archivo XML el cual es perfectamente legible a nuestros ojos, editable con cualquier editor de texto y ligero en tamaño. Modificamos la variable CnnStr y la convertimos en Propiedad, eso nos da una posiblidad mayor en cuanto a lo que podemos realizar. La utilización de Propiedades (Properties) en lugar de Campos (Fields) o variables nos permite una mejor administración de código además de que nos acerca mas a la programación 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 características de la programación orientada a objetos.

También creamos la clase clsMain

Lo mejor es que antes de programar podamos hacer nuestros diagramas de clase para tener una visión mas clara de lo que tenemos que realizar. Para este proyecto ya me he adelantado en el análisis 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: • Diseño de las pantallas • Programación Recordemos que en el primer ejercicio creamos un formulario para que los usuarios inicien sesión en la aplicación. En esta ocasión crearemos un formulario que nos permita administrar a los usuarios que tengan derecho a los recursos del sistema. Diseño de las Pantallas: Agregaremos un formulario al cual nombraremos frmUsers. A continuación agregaremos un ToolStrip al formulario recién creado, Etiquetas, Cajas de Texto y casillas de verificación como se muestra a continuación. El formulario frmUsers, deberá quedar como se muestra:

Según la información 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 continuación:

Según la información de la siguiente tabla:

Los menús del MenuStrip deberán ser como se muestra en la siguiente tabla:

Al menú mnuArchivo se le agregarán tres submenús, como se muestra en la siguiente imagen:

Según la información de la siguiente tabla:

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

Según la información de la siguiente tabla:

Programación: Empezamos con mdiMain. Hacemos sobre clic sobre el formulario y escribimos el siguiente código en el Form_Load: //Form_Load this.Text = "Módulo 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 código anterior se encarga de habilitar o deshabilitar los menús, siempre dependiendo de los permisos que tenga el usuario que inició sesión en el sistema. Hacemos doble clic sobre el submenú “Usuarios del sistema” (mnuUsuarios), accedemos a su código 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 código: this.Close();

Lo más interesante que hemos logrado hasta aquí es la parte de los permisos. Si recordamos lo que hicimos en frmLogin, en la función 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 fácil de lograr que los objetos compartan sus valores y lograr que interactuen entre ellos. Posteriormente podremos ver mejores muestras de interacción 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 código aquí expuesto. Mis disculpas a todos aquellos en quienes no he logrado hacer llegar la idea del código 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 código 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 realización de un simple punto de venta. Ahora seguiremos con frmUsers. El código aquí mostrado es simple aunque algo extenso. En la sección de las directivas: using System.Data.OleDb; using System.Data;

En la sección 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 código, 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 próxima...

Creación de una Librería de Clases (Dll) El objetivo de este ejercicio es mostrar al alumno la manera de crear sus propias Librerías de Clases. Nos ubicamos en la parte en donde dice Solution „proTienda_MATRICULA‟ y con el botón derecho seleccionamos “Add>New Project...”

Creamos una librería 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 botón 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 desarrollarán posteriormente. Agregamos las siguientes directivas using (únicamente si no están), 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 código } } En la parte que dice “Aquí irá todo el código” poner lo siguiente: //Aqui irá todo el código /// <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 tamaño de la fuente /// </summary> /// <value>Representa el tamaño 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 página /// </summary>

public int LeftMargin{ set{ leftmargin = value; } get{ return (leftmargin); } } /// <summary> /// Representa la distancia entre el contenido /// y el borde derecho de la página /// </summary> public int RightMargin{ set{ rightmargin = value; } get{ return (rightmargin); } } /// <summary> /// Representa la distancia entre el contenido /// y el borde superior de la página /// </summary> public int TopMargin{ set{ topmargin = value; } get{ return (topmargin); } } /// <summary> /// Representa la distancia entre el contenido y /// el borde inferior de la página /// </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 botón derecho del mouse, seleccionamos “Add Reference…” como se muestra a continuación:

Nos vamos a la pestaña “Projects” y seleccionamos “Ticket”

Le damos OK. Nuestro proyecto, finalmente quedará así:

El objetivo principal de la Librería Ticket es poder mandar a la pantalla el ticket correspondiente a la venta, pero en realidad se podrá imprimir prácticamente cualquier texto. En el ejercicio 5 podremos comprobarlo. Suerte ...

Consulta de ventas Lo que haremos en esta ocasión 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 tranferirán 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 más 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 código en el FormLoad: Encabezados(); ReadData();

Listo!!!!

Búsqueda 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 información que se tenga de ellos. A partir de este momento programaremos para lograr que los objetos (Formularios, Clases, Dll) interactúen 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 después. Diseñaremos frmBuscaProducto para que quede como se muestra:

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

Nos vamos directamente al código y tecleamos lo siguiente en la sección de las directivas using (únicamente si no está la línea): using System.Data.OleDb;

En la sección 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("Descripción", 250, HorizontalAlignment.Left); lvProductos.Columns.Add("Existencia", 90, HorizontalAlignment.Right); lvProductos.Columns.Add("Precio", 90, HorizontalAlignment.Right); }

Después 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."+ " \nDescripción del error: \n" + ex.Message, "Operación no válida", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } }

Agregamos este otro procedimiento: private void ReadData(string prmDESC_PRODUCTO){ //Este procedimiento lee los datos que se //tranferirán 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 después 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 código 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 código: ReadData(txtDESC_PRODUCTO.Text);

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

1. Hacer respaldos del sistema según se vaya avanzando en el desarrollo. 2. Guardar los cambios periódicamente 3. Tener mucho cuidado en donde colocamos nuestro código. Una instrucción mal colocada puede echar a perder todo nuestro trabajo. 4. Para estos ejercicios, si lo pongo con mayúscula, es mayúscula y viceversa. No le hagamos al héroe, aun no tenemos la experiencia como para saber como funcionará mejor nuestro programa. 5. Nadie es perfecto. Puedo equivocarme, siempre pruebo el código 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 diseñarlo como se muestra:

Agregamos tres Label, tres TextBox y un Button. Según la siguiente tabla:

Para lograr que tome el tamaño adecuado, diseñar al gusto En donde las directivas using, poner una más: using System.Data.OleDb;

Localizamos el constructor, debe ser uno idéntico al que se muestra: public frmCobrar() { InitializeComponent(); }

Nosotros agregaremos uno más: 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 después 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 línea que está marcada con negritas indica que se creará un procedimiento para cuando una tecla sea presionada si el TextBox tiene el foco. También 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 botón (btnOk) y ponemos el siguiente código: 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 bién 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 más difícil 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 algún código 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 aplicación: Iniciando sesión:

Aquí se pone el nombre de usuario y la contraseña. No tiene gran dificultad. Si por algún motivo nuestra aplicación 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 menús los cuales nos llevan a diferentes opciones del sistema. Nos centraremos en el de Ventas:

Si presionamos el botón buscar producto:

Al seleccionar uno, y haciéndole doble clic:

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

Luego, presionamos el Botón Realizar venta:

Podemos presionar Enter y ocurre lo siguiente:

Si elegimos “Yes”

Es una visión 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 código avanzado que probablemente no entenderemos por más que nos expliquen. Solo vamos a centrar nuestra atención en hacer las cosas al pié de la letra y os aseguro que tendremos éxito. Diseñaremos frmVentas como se muestra a continuación:

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

El cuarto botón solo es para dar una mejor vista, se pone debajo de los otros tres, para efectos prácticos 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ó sesión el usuario, la segunda es por que nuestro sistema podría soportar un indefinido número 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 código 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 código 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 código 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 código anterior actúa 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 código 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 código: 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 aplicación Para instalar la aplicación 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.

Creación de un programa de instalación Hola amigos, para crear un programa de instalación el .Net es realmente fácil. Solo debemos agregar un nuevo proyecto a la solución, y seleccionar "Asistente para programas de instalación". Seguir los pasos y listo.