010 - Aplicación de Stock con Java. Hibernate – MySQL – JPA. Formulario transaccional VentaApp.

La primera imagen (img. 01), nos muestra el diseño que tendrán nuestro formulario de Ventas. Indicada en letras rojas, el nombre de variable que le asignamos a cada objeto, esto es importante para ajustarlas los más posible a los métodos que presentaremos más adelante. Se indica cómo cambiar nombre de variables de objetos en los primeros tutoriales.
Obs.: En los primeros tutoriales ya vimos cómo crear formularios y demás.
La segunda imagen (img. 02) nos muestra las importaciones necesarias, los métodos que se ejecutan al arrancar el formulario y las variables de clase necesarias para tener acceso a datos desde cualquier método del formulario.
En forma de código vemos los “Eventos” que utilizaremos y los objetos a los que están encadenados. Utilizamos el evento “ActionPerformed” para llamar los métodos desde los botones. Para los campos de texto utilizamos el evento “KeyPressed”, específicamente se ejecuta la acción al presionar la tecla “Enter” o “Intro”. Para utilizar un “Evento” hacemos clic derecho sobre el objeto y seleccionamos “Eventos” de la lista utilizamos la que podamos aplicar al objeto. En la lista de evento vemos los comentarios especificando a que objetos se aplican.
Código Java
    private void nuevoActionPerformed(java.awt.event.ActionEvent evt) {                                      
nuevo();// Evento ActionPerformed para botón nuevo.
}

private void cancelarActionPerformed(java.awt.event.ActionEvent evt) {
arranque();// Evento ActionPerformed para botón cancelar.
}

private void agregarActionPerformed(java.awt.event.ActionEvent evt) {
agregar();// Evento ActionPerformed para botón agregar.

}

private void idKeyPressed(java.awt.event.KeyEvent evt) {
//Uso del Evento KeyPressed dentro del campo de texto "id".
if(evt.getKeyCode()== KeyEvent.VK_ENTER){
buscarFuncionario();
}
}

private void idClieKeyPressed(java.awt.event.KeyEvent evt) {
//Uso del Evento KeyPressed dentro del campo de texto "idClie".
if(evt.getKeyCode() == KeyEvent.VK_ENTER){
buscarCliente();
}
}

private void idArtKeyPressed(java.awt.event.KeyEvent evt) {
//Uso del Evento KeyPressed dentro del campo de texto "idArt".
if(evt.getKeyCode() == KeyEvent.VK_ENTER){
buscarArticulo();
}
}

private void cantidadKeyPressed(java.awt.event.KeyEvent evt) {
//Uso del Evento KeyPressed dentro del campo de texto "cantidad".
if(evt.getKeyCode() == KeyEvent.VK_ENTER){
calcularParcial();
}
}

private void eliminarActionPerformed(java.awt.event.ActionEvent evt) {
eliminar();// Evento ActionPerformed para botón eliminar.
}

private void guardarActionPerformed(java.awt.event.ActionEvent evt) {
guardar();// Evento ActionPerformed para botón guardar.
}
Vemos más abajo la lista de métodos que le dan vida al formulario, el nombre de cada método nos da una idea del funcionamiento que cumplen. En los primeros tutoriales indicamos el funcionamiento en profundidad de algunos métodos comunes que se utilizan en un ABM como en transacciones.
Código Java
public void hibernateSession(){
st = HibernateUtil.getSessionFactory().openSession();
}
public void arranque(){
this.nuevo.setEnabled(true);
this.agregar.setEnabled(false);
this.eliminar.setEnabled(false);
this.guardar.setEnabled(false);
this.num.setText(null);
this.fecha.setText(null);
this.hora.setText(null);
this.id.setText(null);
this.id.setEnabled(false);
this.nombres.setText(null);
this.apellidos.setText(null);
this.idClie.setText(null);
this.idClie.setEnabled(false);
this.des.setText(null);
this.idArt.setText(null);
this.idArt.setEnabled(false);
this.desArt.setText(null);
this.pve.setText(null);
this.can.setText(null);
this.cantidad.setText(null);
this.cantidad.setEnabled(false);
this.total.setText(null);
this.totalGeneral.setText(null);
tableModel();
}
public void tableModel(){
this.jTable1.getColumnModel().getColumn(0).setPreferredWidth(15);
this.jTable1.getColumnModel().getColumn(1).setPreferredWidth(150);
this.jTable1.getColumnModel().getColumn(2).setPreferredWidth(80);
this.jTable1.getColumnModel().getColumn(3).setPreferredWidth(50);
this.jTable1.getColumnModel().getColumn(4).setPreferredWidth(80);
model = (DefaultTableModel)this.jTable1.getModel();
model.setNumRows(0);
}
public void nuevo(){
obtenetID();
this.id.setEnabled(true);
this.idClie.setEnabled(true);
this.idArt.setEnabled(true);
this.cantidad.setEnabled(true);
this.agregar.setEnabled(true);
this.eliminar.setEnabled(true);
this.guardar.setEnabled(true);
this.nuevo.setEnabled(false);
this.id.requestFocus();
Calendar cal = Calendar.getInstance();
String calString = retornarString(cal);
String calHora = retornarStringHora(cal);
this.fecha.setText(calString);
this.num.setText(String.valueOf(numVenta));
this.hora.setText(calHora);
}
public void obtenetID(){
numVenta = 0;
List<VentaCab> lista = (List<VentaCab>)st.createQuery("From VentaCab").list();
for (Iterator<VentaCab> it = lista.iterator(); it.hasNext();) {
VentaCab ventaCab = it.next();
numVenta = ventaCab.getNum() + 1;
}
if(numVenta==0){
numVenta=1;
}
}
public void buscarArticulo(){
int idArti = 0;
try {
try {
idArti = Integer.parseInt(this.idArt.getText());
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "ID debe ser numérico.");
}
Articulo art = (Articulo)st.load(Articulo.class, idArti);
this.desArt.setText(art.getDes());
this.pve.setText(String.valueOf(art.getPve()));
this.can.setText(String.valueOf(art.getCan()));
this.cantidad.requestFocus();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "No hay artículo con ID: " + idArti);
}
}
public void calcularParcial(){
int canVent = 0;
int pVenta = 0;
int stock = 0;
int totalParcial = 0 ;
try {
canVent = Integer.parseInt(this.cantidad.getText());
pVenta = Integer.parseInt(this.pve.getText());
stock = Integer.parseInt(this.can.getText());
if(stock < canVent){
JOptionPane.showMessageDialog(null, "Stock insuficiente.");
}
else{
totalParcial = canVent * pVenta;
this.total.setText(String.valueOf(totalParcial));
this.agregar.requestFocus();
}

} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Se requiere datos numérico.");
}
}
public void buscarFuncionario(){
int idFunc = 0;
try {
try {
idFunc = Integer.parseInt(this.id.getText());
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "ID debe ser numérico.");
}
Funcionario funcio = (Funcionario)st.load(Funcionario.class, idFunc);
this.nombres.setText(funcio.getNombres());
this.apellidos.setText(funcio.getApellidos());
this.idClie.requestFocus();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "No hay funcionario con ID: " + idFunc);
}
}
public void buscarCliente(){
int idCl = 0;
try {
try {
idCl = Integer.parseInt(this.idClie.getText());
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "ID debe ser numérico.");
}
Cliente clie = (Cliente)st.load(Cliente.class, idCl);
this.des.setText(clie.getDes());
this.ruc.setText(clie.getRuc());
this.idArt.requestFocus();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "No hay cliente con ID: " + idCl);
}
}
public void agregar(){
if(this.id.getText().isEmpty()){
JOptionPane.showMessageDialog(null, "Seleccione un funcionario.");
}
else{
if(this.idClie.getText().isEmpty()){
JOptionPane.showMessageDialog(null, "Seleccione un cliente.");
}
else{
if(this.idArt.getText().isEmpty()){
JOptionPane.showMessageDialog(null, "Seleccione un articulo.");
}
else{
if(this.cantidad.getText().isEmpty()){
JOptionPane.showMessageDialog(null, "Indique una cantidad.");
}
else{
verificar();
if(var>=1){
int showConfirmDialog = JOptionPane.showConfirmDialog(null, "Artículo ya Agregado. Desea sumar la cantidad.", "Mensaje del Sistema.", JOptionPane.YES_NO_OPTION);
if(showConfirmDialog==0){
sumarRepetido();
calcular();
confimAgregar();
limpiar();
}
else{
limpiar();
this.idArt.requestFocus();
}
}
else{
model.addRow(new Object[]{
this.idArt.getText(),this.desArt.getText(),this.pve.getText(),this.cantidad.getText(),this.total.getText()
});
calcular();
confimAgregar();
limpiar();
}

}
}
}
}
}
public void confimAgregar(){
int showConfirmDialog = JOptionPane.showConfirmDialog(null, "Agregar más Articulos.", "Mensaje del Sistema.", JOptionPane.YES_NO_OPTION);
if(showConfirmDialog == 0){
this.idArt.requestFocus();
}
else{
this.guardar.requestFocus();
}

}
public void limpiar(){
this.idArt.setText(null);
this.desArt.setText(null);
this.pve.setText(null);
this.can.setText(null);
this.cantidad.setText(null);
this.total.setText(null);
this.id.setEnabled(false);
this.idClie.setEnabled(false);
}
public void calcular(){
int totalG = 0;
for (int i = 0; i < this.jTable1.getRowCount(); i++) {
Object valueAt = model.getValueAt(i, 4);
totalG += Integer.parseInt(valueAt.toString());
}
this.totalGeneral.setText(String.valueOf(totalG));
}
public void verificar(){
var = 0;
int idAr = Integer.parseInt(this.idArt.getText());
if(this.jTable1.getRowCount()>=1){
for (int i = 0; i < this.jTable1.getRowCount(); i++) {
Object valueAt = model.getValueAt(i, 0);
int parseInt = Integer.parseInt(valueAt.toString());
if(idAr == parseInt){
var = 1;
idArtt = i;
}
}
}
}
public void sumarRepetido(){
int artCant = Integer.parseInt(this.cantidad.getText());
int artTotal = Integer.parseInt(this.total.getText());
Object valueAt = model.getValueAt(idArtt, 3);
Object valueAt1 = model.getValueAt(idArtt, 4);
int cantArt = Integer.parseInt(valueAt.toString());
int totalArt = Integer.parseInt(valueAt1.toString());
int x = artCant + cantArt;
int y = artTotal + totalArt;
int t = Integer.parseInt(this.can.getText());
if(t>=x){
model.setValueAt(x, idArtt, 3);
model.setValueAt(y, idArtt, 4);
}
else{
JOptionPane.showMessageDialog(null, "Stock de artículos insuficiente.");
}

}

public String retornarString(Calendar fecha){
String retorno=null;
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
if (fecha != null) {
retorno = sdf.format(fecha.getTime());
}
return retorno;
}
public String retornarStringHora(Calendar fecha){
String retorno=null;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
if (fecha != null) {
retorno = sdf.format(fecha.getTime());
}
return retorno;
}
public Calendar retornarCalendar(String fecha){
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Calendar cal = Calendar.getInstance();
try {
cal.setTime(sdf.parse(fecha));
} catch (ParseException ex) {
JOptionPane.showMessageDialog(null, "Error; compruebe formato de fecha: " + ex);
}
return cal;
}
public void eliminar(){
if(this.jTable1.getSelectedRow()==-1){
JOptionPane.showMessageDialog(null, "No ha seleccionado ninguna fila de la tabla.");
}
else{
int showConfirmDialog = JOptionPane.showConfirmDialog(null, "Eliminar fila seleccionada.", "Mensaje del Sistema.", JOptionPane.YES_NO_OPTION);
if(showConfirmDialog == 0){
int sel = this.jTable1.getSelectedRow();
model.removeRow(sel);
this.idArt.requestFocus();
}
else{
this.idArt.requestFocus();
}
}
}
public void guardar(){
if(this.id.getText().isEmpty() ||this.idClie.getText().isEmpty() ){
JOptionPane.showMessageDialog(null, "Faltan datos para guardar. Verifique.");
}
else{
if(this.jTable1.getRowCount()==0){
JOptionPane.showMessageDialog(null, "No hay datos para guardar.");
}
else{
int showConfirmDialog = JOptionPane.showConfirmDialog(null, "Desea guardar esta venta.", "Mensaje del Sistema.", JOptionPane.YES_NO_OPTION);
if(showConfirmDialog == 0){
try {
st.beginTransaction();
VentaCab venta = new VentaCab();
int idFun = Integer.parseInt(this.id.getText());
int idCli = Integer.parseInt(this.idClie.getText());
long totalVenta = Long.parseLong(this.totalGeneral.getText());
Funcionario funcionario = (Funcionario)st.load(Funcionario.class, idFun);
Cliente cliente = (Cliente)st.load(Cliente.class, idCli);
Calendar fechaVenta = retornarCalendar(this.fecha.getText());
String horaVenta = this.hora.getText();
venta.setCliente(cliente);
venta.setFuncionario(funcionario);
venta.setFecha(fechaVenta);
venta.setHora(horaVenta);
venta.setTotal(totalVenta);
funcionario.getVentaCabs().add(venta);
cliente.getVentaCabs().add(venta);
int rowCount = this.jTable1.getRowCount();
int[] idArti = new int[rowCount];
int[] cantVenta = new int[rowCount];
for (int i = 0; i < this.jTable1.getRowCount(); i++) {
VentaDet detalleVenta = new VentaDet();
int idArticulo = Integer.parseInt(String.valueOf(model.getValueAt(i, 0)));
idArti[i] = idArticulo;
Articulo ventaArticulo = (Articulo)st.load(Articulo.class, idArticulo);
int cantidadVenta = Integer.parseInt(String.valueOf(model.getValueAt(i, 3)));
cantVenta[i]= cantidadVenta;
int importeVenta = Integer.parseInt(String.valueOf(model.getValueAt(i, 4)));
detalleVenta.setArticulo(ventaArticulo);
detalleVenta.setCant(cantidadVenta);
detalleVenta.setImporte(importeVenta);
detalleVenta.setVentaCab(venta);
venta.getVentaDets().add(detalleVenta);
}
st.save(venta);
st.getTransaction().commit();
for (int i = 0; i < idArti.length; i++) {
actualizarStrock(cantVenta[i], idArti[i]);
}
arranque();
JOptionPane.showMessageDialog(null, "Venta guardada correctamente.");
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Error guardando venta. Verifique.");
}

}
else{
this.idArt.requestFocus();
}

}
}
}
public void actualizarStrock(int cantidadVendida, int idArticulo){
st.beginTransaction();
Articulo actualizar = (Articulo)st.load(Articulo.class, idArticulo);
int temp = actualizar.getCan() - cantidadVendida;
actualizar.setCan(temp);
st.update(actualizar);
st.getTransaction().commit();
}
En la última imagen vemos el formulario en ejecución. (img. 03)

13 comentarios :

  1. hola Carlos! espero estés bien .. capo, te queria preguntar si es que esto sigue, con el tema de los reportes y etc etc .. gracias una vez más por los tutos capo, fueron de gran ayuda para aprenderme el tema de hibernate ...

    ResponderEliminar
  2. Buenas Andrés, aún tengo que agregar un formulario para compras y los reportes correspondientes. Estoy ocupado con otros proyectos, pero la idea es completar en un 100%. Estoy seguro que pronto. Gracias por comentar.

    ResponderEliminar
  3. buenas, te podrias poner en contacto conmigo para un tema de programacion?: ferrefurroy@gmail.com

    gracias

    ResponderEliminar
  4. Buenas amigo una pequeña consulta en la hora de mostar el reporte de ventas el total debería de estar no solo en números sino en letras como podria lograrse eso.desde ya gracias y saludos ..

    ResponderEliminar
    Respuestas
    1. Que tal, en el tutorial "Java básico 026" dentro de la págia hay una clase que te puede servir, "Conversión de números a letras", puedes adaptarla para integrarla a la aplicación. Saludos y suerte.

      Eliminar
  5. Entiendo amigo yo tengo esa misma clase .. lo que no comprendo es como llamar a la clase en un ireport y que convierta en total a letras ..desde ya gracias y saludos ..

    ResponderEliminar
    Respuestas
    1. No tengo ningún ejemplo para darte, normalmente para el ireport se pasan los datos externos como parámetros. Lo ideal seria pasar el dato final, osea el total convertido en letras como parámetro, la cual se obtiene utilizando las clase de que te he mencionado. Saludos.

      Eliminar
  6. Carlos, excelente tutorial, tengo una consulta, como puedo hacer que me busque por nombre al cliente y no por el id en el Jtextfield

    ResponderEliminar
    Respuestas
    1. Que tal. Es cuestión de elegir ese campo para la búsqueda. Ejemplo de un proyecto que tengo, en este caso se utiliza HQL, tendrás que utilizar esta importación ( import org.hibernate.Query;). Si no es un registro único no funcionará. Si repites un cliente con el mismo nombre te dará error en la búsqueda. Lo mejor para búsqueda es que sea única para cada registro. Saludos.
      PlanCuenta planCuenta = null;
      Query query = st.createQuery("From PlanCuenta cuenta Where cuenta. nombre=? and cuenta. clIDFisica=?");
      query.setParameter(0, toString);
      query.setParameter(1, clId);
      planCuenta=(PlanCuenta)query.uniqueResult();

      Eliminar
    2. Este comentario ha sido eliminado por el autor.

      Eliminar
    3. Muchas gracias Carlos por responder, voy a replantear mi pregunta porque lo formule mal, ¿es posible desplegar una lista de clientes en el jtextfiel y seleccionarlo?

      Eliminar
    4. La forma más fácil sería utilizando combo en vez de campo de texto y colocar allí tu lista de clientes o lo que necesites. También puedes utilizar un botón para desplegarte un panel con tu lista de clientes. Eje. https://codigo--java.blogspot.com/2014/02/java-swing-020-modo-diseno-en-netbeans.html

      Eliminar