none
Como finalizar mi registro cuando ya tenga la hr de salida, para poder iniciar un nuevo registro de e/s? RRS feed

  • Pregunta

  • Hola buen dia es la primera pregunta que realizo espero y puedan ayudarme porfavor.

    Soy nuevo en programacion y la verdad aun me cuesta programar. Tengo un proyecto donde realizo registros de entrada y salida por medio de un scanner utilizando el codigo de barras. Mi problema es que cuando yo ya cuento con mi hr de salida, quiero finalizar ese registro y me cree uno nuevo. Lo que me hace es estar modificando mi hr de salida cada vez que lee ese codigo de barras y nunca termina. No se en que parte de mi codigo este mal o que es lo que me aga falta.

    Mi metodo para registrar lo realizo de la siguiente  manera.

    public void registro(String codB)//Metodo Registro E/S
    {

           
    DateTime fh = DateTime.Now;
           
    string fech = fh.ToString("yyyy-MM-dd");
           
    string hr = fh.ToString("hh :mm :ss");
           
    string hrs = "00:00:00";
         
    // string fechS = "";

            con
    = new System.Data.SqlClient.SqlConnection();
            con
    .ConnectionString = "Data Source=10.140.2.131;Initial Catalog=SistemaControl;User ID=sa; Password=sebn.TLX.mx.08";
           
    try
           
    {
                con
    .Open();
               
    SqlCommand cmd = new SqlCommand("SELECT id_codBarras FROM Equipo WHERE id_codBarras  = @idC OR rfid = @idC", con);
              
    // SqlCommand cmd1 = new SqlCommand("SELECT rfid FROM Equipo WHERE  rfid = @idC", con);
                cmd
    .Parameters.AddWithValue("idC", codB);
               
    SqlDataAdapter sda = new SqlDataAdapter(cmd);
               
    DataTable dt = new DataTable();
                sda
    .Fill(dt); // devuelve el numero de filas.  
               
    if (dt.Rows.Count == 1)
               
    {
                   
    //  this.Hide();//Cerrar la ventana Log
                   
    MessageBox.Show("Se realizo la consulta:");

                   
    SqlCommand cm = new SqlCommand("SELECT id_codBarras FROM Registro_Eq WHERE id_codBarras  = @id", con);
                     cm
    .Parameters.AddWithValue("id", codB);
                    
    SqlDataAdapter sd = new SqlDataAdapter(cm);
                    
    DataTable dts = new DataTable();
                     sd
    .Fill(dts);
                    
    if(dts.Rows.Count == 1) 
                      
    {
                     
    MessageBox.Show("Existe el registro de entrada");
                      modificReg
    ();
                      mostrarReg
    ();

                      
    }else{
                          
    SqlCommand com = new SqlCommand("INSERT INTO Registro_Eq(hrE,fechaE,hrS, id_codBarras ) VALUES('" + hr + "','" + fech + "', '" + hrs + "', @cod)", con);
                           com
    .Parameters.AddWithValue("@cod", codB);
                          
    int i = com.ExecuteNonQuery();
                     
    if(i>0){
                          
    MessageBox.Show("Registro agregado correctamente");
                           mostrarReg
    ();
                     
    }
                     
    else{
                          
    MessageBox.Show("Error al agregar");
                     
    }
                      
    }

               
    }
               
    else
               
    {
                   
    MessageBox.Show("No se encuentra en en la BD");
               
    }
           
    }
           
    catch (Exception e)
           
    {
               
    MessageBox.Show(e.Message);
           
    }
           
    finally
           
    {
                con
    .Close();           
           
    }

    }

    Mi metodo Modificar es el siguiente.

    public void modificReg()
    {

           
    DateTime fh = DateTime.Now;
           
    string fech = fh.ToString("yyyy-MM-dd");
           
    string hr = fh.ToString("hh :mm :ss");


            con
    = new System.Data.SqlClient.SqlConnection();
            con
    .ConnectionString = "Data Source=10.140.2.131;Initial Catalog=SistemaControl;User ID=sa; Password=sebn.TLX.mx.08";

           
    try
           
    {
                con
    .Open();
               
    string cadena = "UPDATE Registro_Eq set  hrS='" + hr + "',fechaS='" + fech + "'  WHERE id_codBarras  = '" + txt1Codigo.Text + "'";
               
    SqlCommand comando = new SqlCommand(cadena, con);
               
    int cant;
                cant
    = comando.ExecuteNonQuery();
               
    if (cant == 1)
               
    {
                   
    MessageBox.Show("Se modifico la hr de salida");
                    con
    .Close();
               
    }
               
    else
               
    {
                   
    MessageBox.Show("Error de consulta");
               
    }
               
    // }

           
    }
           
    catch (Exception ex)
           
    {
               
    MessageBox.Show("Error" + ex.ToString());
           
    }
    }

    Para mostrar utilizo este método.

    public void mostrarReg()
    {

           
    try
           
    {

               
    SqlCommand cmd = new SqlCommand("SELECT id_Reg as 'ID',hrE as 'Hr de Entrada' ,fechaE as 'Fecha de Entrada'  ,hrS as 'Hr de Salida',fechaS as 'Fecha de Salida', deptoNum as 'Depto y No. Equipo', id_numControl as 'No. Control'  FROM Registro_Eq INNER JOIN Equipo ON Registro_Eq.id_codBarras = Equipo.id_codBarras ", con);

               
    SqlDataAdapter adaptador = new SqlDataAdapter(cmd);
               
    DataTable dt = new DataTable();
                adaptador
    .Fill(dt);

               
    TabReg.DataSource = dt;
           
    }
           
    catch (Exception e)
           
    {
               
    MessageBox.Show("No se pudo cargar los datos en la Tabla" + e.ToString());
           
    }

    }

    martes, 15 de mayo de 2018 14:24

Todas las respuestas

  • Buenas, por lo que veo en ningún momento validas si el registro existente ya cuenta con una hora de salida por lo que siempre que encuentras un registro te limitas a actualizarlo.

    if(dts.Rows.Count == 1)  
    {
        MessageBox.Show("Existe el registro de entrada");
        modificReg();
        mostrarReg();
    }

    En ese lugar habria que añadir una validación adicional para comprobar que ese registro que fue encontrado no contiene una hora de salida, desconozco la estructura de tu bd pero podria ser algo así:

    // escrito en navegador no estoy seguro si es así como se consulta un datatable no suelo ocuparlos mucho tomalo como punto de partida.
    if(dts.Rows.Count == 1 && dts.Rows[0]["fechaS"] != null)  
    {
        MessageBox.Show("Existe el registro de entrada");
        modificReg();
        mostrarReg();
    }


    Si me permites darte un consejo y aprovechando que estas empezando, evita utilizar abreviaciones en tu código esto dificulta la lectura del mismo por otras personas, intenta que los nombres sean descriptivos a lo que contienen por ejemplo en: 

    DataTable dts = new DataTable();
    // De esta manera podriamos saber que ese datatable contiene las entradas y salidas.
    DataTable entradasYSalidas = new DataTable();
    Esto te ayuda tanto a ti como a los demas a enteder tu código mas rapido. Adicionalmente si me permites el atrevimiento de recomiendo la lectura del libro "Clean Code" de Robert C. Martín estoy seguro que te ayudara mucho a mejorar tu codigo.

    martes, 15 de mayo de 2018 15:34
  • Claro muchas gracias Yamiel tomare tu consejo. Y si claro acepto las criticas para poder desarrollarme mejor.

    martes, 15 de mayo de 2018 17:00
  • Mi base de datos tiene una de estas tabla. la Tabla Registro_Eq tiene los campos id_Reg (pk), hrE, fechaE, hrS, fechaS y id_codBarras (fk)   se relaciona con la tabla    Equipo que tiene los campos id_codBarras (fk), rfid, marca, deptoNum y id_numControl. Agregaria la imagen pero no me permite, espero y me entiendas.
    martes, 15 de mayo de 2018 17:10
  • Se complica mucho la existencia.  Lo que necesita es un procedimiento almacenado que lo haga todo.

    Este es un script de prueba.  Puede correrse tal cual en cualquier SQL Server pues usa la base de datos tempdb.

    Use tempdb;
    Go
    
    Create Table dbo.tblUsuarios
    (
    	Id bigint Not Null Identity(1, 1) Primary Key Clustered
    	, Nombre nvarchar(100) Not Null
    );
    
    Create Table dbo.tblEyS
    (
    	Id bigint Not Null Identity(1, 1) Primary Key Clustered
    	, UsuarioId bigint Not Null Constraint FK_dbo_tblEyS_UsuarioDebeExistir Foreign Key References dbo.tblUsuarios(Id)
    	, HoraEntrada datetime2 Not Null
    	, HoraSalida datetime2 Null
    );
    Go
    
    Create Procedure dbo.uspRegistrarHora
    	@usuarioId bigint
    As
    Begin
    	Set NoCount On;
    
    	Declare @ahora datetime2 = GetDate(); --Aunque yo siempre gusto de usar UTC en mis bases de datos.
    
    	Merge dbo.tblEyS As t
    	Using (Select @usuarioId As [UsuarioId], @ahora As [Hora]) As s
    	On t.UsuarioId = s.UsuarioId And t.HoraSalida Is Null
    	When Matched Then
    	Update Set t.HoraSalida = s.Hora
    	When Not Matched By Target Then
    	Insert (UsuarioId, HoraEntrada) Values(s.UsuarioId, s.Hora)
    	;
    End
    Go
    
    Declare @usuarioId bigint;
    Insert Into dbo.tblUsuarios Values (N'Jose');
    Set @usuarioId = SCOPE_IDENTITY();
    
    Exec dbo.uspRegistrarHora @usuarioId;
    Select * From dbo.tblEyS;
    WaitFor Delay '00:01';
    Exec dbo.uspRegistrarHora @usuarioId;
    Select * From dbo.tblEyS;
    WaitFor Delay '00:01';
    Exec dbo.uspRegistrarHora @usuarioId;
    Select * From dbo.tblEyS;
    
    Go
    
    Drop Procedure dbo.uspRegistrarHora;
    Drop Table dbo.tblEyS;
    Drop Table dbo.tblUsuarios;
    Go

    Yo no tengo códigos de barra, así que en el ejemplo identifico al usuario por ID.  El procedimiento almacendado provee la hora, lo cual es bueno para cuestiones de auditoría pues normalmente un servidor es menos accesible que una PC cliente, así es más confiable que SQL Server sea quien tome el dato de hora en vez de recibirlo remotamente.

    La consulta tiene un par de DELAY para demostrar el procedimiento almacenado, así que tenga un poco de paciencia cuando lo pruebe, pues tardará 2 minutos en terminar.

    El script tiene 3 SELECT de la tabla de tiempos, uno inmediatamente después de cada ejecución del procedimiento almacenado.  Así usted podrá ver la progresión de los resultados.


    Jose R. MCP
    Code Samples

    martes, 15 de mayo de 2018 20:17
    Moderador
  • Buen día estimado, entonces lo que debes hacer es comprobar si el registro existente tiene una fecha de salida válida (cosa que la solución propuesta por Jose R. MCP hace), por otro lado me quede pensando en tu problema.

    Por lo que entiendo lo que buscas es: 

    • Obtener el "Equipo" por código de barras.
    • Buscar si el equipo tiene un registro
    • Si existe un registro de entrada registrar su salida.
    • En caso contrario crear un nuevo registro que registre su entrada.

    En caso de ser esto correcto lo que debes hacer entonces es comprobar si el registro que has encontrado tiene una hora de salida valida en tu código veo que cuando creas un registro nuevo estableces la hora de salida a "00:00:00" si lo que entiendo es correcto lo que tienes que hacer es luego de verificar que el registro existe verificar que su valor sea diferente a "00:00:00" si su valor es "00:00:00" solo actualizas el registro de lo contrario creas uno nuevo.

    El metodo con el que lo hagas queda a tu discreción dependiendo de tu nivel de conocimiento o lo que estes dispuesto a querer aprender en este punto. Yo en lo personal no me gusta meter logica de negocio en la db salvo para temas de optimización. (Que en el caso del ejemplo propuesto por Jose veo bastante aceptable).

    Saludos.


    • Editado Yamiel Dash miércoles, 16 de mayo de 2018 13:55 Cambio de opinion
    miércoles, 16 de mayo de 2018 13:51
  • Hola buen dia Jose!! gracias me a servido de mucho.

    Disculpa tengo una duda, lo que pasa que si te das cuenta tengo un campo de nombre rfid en la tabla Equipo ya que tambien utilizo una lectora rfid con  Tarjetas rfid. Quisiera saber cómo poder realizar  el registro por medio del rfid, es decir que si yo no  realizó el registro por el código de barras entonces que sea a travésde rfid. En mi primera consulta lo que ago es verificar si el código de barras o rfid se encuentran en mi base de datos.

    Esta es la consulta que verifica si existe el codigo de barras o rfid que se obtiene del textBox.

    SqlCommand cmd = new SqlCommand("SELECT id_codBarras FROM Equipo WHERE id_codBarras  = @idC OR rfid = @idC", con);

    Se que si yo ago mi consulta por rfid tengo que obtener el id de esa tarjeta para hacer mi registro debido a que id_codBarras es llave primaria.

    La consulta sería de esta manera.

    SqlCommand obtenerId_CodBarras = new SqlCommand("select id_codBarras from Equipo where rfid = @idC", con);

    Pero no se como seria mi condicion cuando sea por rfid.

    Alguien tendra alguna idea de como hacerlo, porfavor.

    miércoles, 16 de mayo de 2018 16:12
  • Buen día Yamiel! Gracias  los dos me han ayudado mucho. Soy nuevo en esto y la verdad me cuesta

    programar. Espero y puedas ayudarme en la pregunta que le hice a Jose, no se te ocurre un ejemplo de como seria. porfavor.

    miércoles, 16 de mayo de 2018 16:18
  • También es sencillo, no hay que complicarse.  Tiene entonces 2 formas de ubicar y registrar la entrada o salida de un equipo:  Códogo de barras o RFID.  No importa, puede tener 1000 que la lógica del SP no cambia.

    Simplemente debe estandarizar:  Yo tendría en mi tabla de equipos un ID único autonumérico como el de mi tabla ejemplo.  Entonces lo único que tengo que hacer es identificar ese ID a partir del código de barras o el RFID, y ya puedo usar el SP por ID.

    Puede crear el SP con 3 parámetros, todos opcionales (pero cualquiera de ellos requerido como mínimo).  Luego la base de datos ubica ID por el parámetro que sea que se haya provisto.

    Parámetros del SP:  @id, @rfid, @bcode, todos opcionales.  El SP primero verifica que haya al menos 1.

    Create Procedure ...
    
        Set NoCount On;
    
        If (@Id Is Null And @rfid Is Null And @bcode Is Null)
        Begin
            Raiserror(N'Debe especificarse uno de los tres posibles identificadores.', 16, 1);
            Return 1;
        End
    
        ...

    Luego cambiamos el MERGE.  Ahora hay que proveer una tabla fuente (source) más compleja.

    	With fuente As
    	(
    		Select
    			ID
    			, @ahora As [Hora]
    		From
    			dbo.tblEquipos
    		Where
    		(@id Is Not Null And ID = @id)
    		Or
    		(@rfid Is Not Null And RFID = @rfid)
    		Or
    		(@bcode Is Not Null And BCode = @bcode)
    	)
    	Merge dbo.tblEyS As t
    	Using fuente As s
    	...

    Tal vez esos serían las modificaciones.  Unas notas:

    1. Cuando escribí el ejemplo pensé en entradas y salidas de usuarios, por eso el nombre de parámetro @idUsuario.  Si es registro de entradas y salida de equipo, pues no invalida el ejemplo, pero sí comprenda las correcciones.  Donde dice ID ahora, sería el @idUsuario de antes.
    2. Después de que escribí las correcciones, no imaginé el uso de otras tablas para almacenar los RFID's o códigos de barra.  Imagino que están en la misma tabla de equipos.

    Creo que eso sería todo.


    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    miércoles, 16 de mayo de 2018 20:32
    Moderador
  • Que tal Jose buen dia!!

     oye agregue un id en la tabla Equipo como mencionas, creo que es lo correcto. Es necesario utilizar los 3 parametros (@Id, @rfid, @bcode), porque ya solo seria recuperar el id de mi tabla equipo ya sea por codigo de barras o rfid.

    Porfa ayudame.

    martes, 22 de mayo de 2018 13:31
  • Según lo expliqué en la respuesta anterior, el procedimiento almacenado tiene los 3 parámetros, pero solamente uno es necesario.

    Jose R. MCP
    My GIT Repositories | Mis Repositorios GIT

    miércoles, 23 de mayo de 2018 1:12
    Moderador