Consulta – Control de asistencia Turnos 24hs

publicado por: Anonymous

Perdón, este es mi primer post y ya estoy pidiendo ayuda jajaja… Les voy a comentar a ver si me pueden dar una mano y seguro a varios mas les puede servir.

Tengo un sistema de asistencia realizado en PHP y MySQL, el cual funciona de manera correcta.
Ej: Empleado X ingresa a las 8 AM, se genera un registro indicando el horario de entrada, el empleado X sale a las 17hs y se actualiza dicho registro en el campo correspondiente con el horario de las 17hs, en la lógica el código lo que busca es que si un empleado tiene en la misma FECHA 2 o mas registros toma la hora mínima :jumpie: (Ingreso) y luego va buscando la máxima(egreso) para dejar esta como salida.

Mi problema es que hay Empleados que ingresan a trabajar a trabajar a las 18hs del día 1 y salen a las 00hs del dia2, por ende tengo fechas diferentes y se me generan inconsistencias dado q me toma ambos como ingresos… Se entiende? Me pueden dar una mano?

EDIT

Agrego la info que me piden…
Consta de 2 Tablas, Registros y Control Horario.

  • Registros: se cargan en crudo las marcas de los empleados (Empleado, Fecha y Hora, Estado). El campo estado lo trabajo como un bool para no reprosesar todos los registros que hay en la tabla.

  • Control Horario: Se cruza la información de la tabla registros para armar un solo registro con "Empleado, Fecha Entrada, Hora Entrada, Fecha Salida, Hora salida"

Les agrego el codigo de CONTROL HORARIO que es donde se hace todo el tema…

$vistaTemporal = "CREATE VIEW fingers_temp AS Select empleado, fecha, MIN(time(hora)) as ingreso_real, MAX(time(hora)) as egreso_real FROM eg_registro_fingerprint WHERE estado = 0 AND empleado NOT BETWEEN 99950 AND 99999 GROUP BY empleado,fecha";
$conn->execute($vistaTemporal);
//Consulta tabla temporal
$getAllSQL = "SELECT empleado, fecha, ingreso_real, egreso_real FROM fingers_temp";
$statementOfAll = $conn->execute($getAllSQL);

//Lectura de select
foreach ($statementOfAll as $registro) {
    $id = $registro['id'];
    $empleado = $registro['empleado'];
    $fecha = $registro['fecha'];
    $egreso_real = $registro['egreso_real'];
    $ingreso_real = $registro['ingreso_real'];
    $horas_trabajadas = 0;

    // Verifico sin un empleado tiene mas de 1 o mas registros el mismo dia
    $controlHorario = "SELECT count(fecha_entrada) as contador, fecha_entrada,empleado FROM eg_control_horario where fecha_entrada = '$fecha' AND empleado = '$empleado'";
    $statementOfHorarios = $conn->execute($controlHorario);

    $contador = 0;

    foreach ($statementOfHorarios as $horario) {
      $contador = $horario['contador'];
    }
  
  echo $contador;
  
  
    if ( $contador < 1){
      $newControlAsis = "INSERT INTO eg_control_horario (empleado, fecha_entrada, fecha_salida, ingreso_real, egreso_real, horas_trabajadas) VALUES ('$empleado', '$fecha','$fecha' , '$ingreso_real', '$egreso_real','$horas_trabajadas')";
      $conn->execute($newControlAsis);
      $updateRegistroEstado = "UPDATE eg_registro_fingerprint SET estado = 1";
      $conn->execute($updateRegistroEstado);
    }else{
      $updateControlAsis = "UPDATE eg_control_horario SET egreso_real = '$egreso_real' where fecha_entrada = '$fecha' AND empleado = '$empleado'";
      $conn->execute($updateControlAsis);
      $updateRegistroEstado = "UPDATE eg_registro_fingerprint SET estado = 1";
      $conn->execute($updateRegistroEstado);
    }

}
$drop = "DROP VIEW fingers_temp";
$conn->execute($drop);

Registros Crudos

Registros crudos

Control Horario
Control Horario

Ignoren los horarios teóricos y horas trabajadas

La primer imagen es referente a donde se suben todos los fichajes, en la segunda imagen es donde se unen los fichajes de cada empleado siempre y cuando cumplan en el mismo día. Como hago (sin romper la lógica actual) para cuando un empleado entra durante la noche y pasada las 00hs, es decir la fecha de entrada es diferente a la de salida.

solución

Si tienes MySQL 8+ puedes usar WITH para actualizar tus registros de salida con algo como:

WITH pivote AS (SELECT ingreso_real, fecha_entrada FROM `ControlHorario` WHERE empleado = 1710 ORDER BY fecha_entrada DESC, ingreso_real DESC LIMIT 1)
UPDATE `ControlHorario` SET `egreso_real` = now(), fecha_salida = now() WHERE (empleado = 1710 AND `ingreso_real` = pivote.ingreso_real AND `fecha_entrada` = pivote.fecha_entrada) LIMIT 1

Si MySQL no soporta WITH entonces solamente buscas el último registro en un query, obtienes los resultados con PHP y en otro query haces el UPDATE:

UPDATE `ControlHorario` SET `egreso_real` = now(), fecha_salida = now() WHERE (empleado = 1710 AND `ingreso_real` = '12:30' AND `fecha_entrada` = '2018-01-01') LIMIT 1

Después de esto la consulta sería un simple SELECT a ControlHorario.

Yo recomiendo usar campos tipo datetime en lugar de fechas y horas separadas para guardar puntos en el tiempo porque es más sencillo buscar, actualizar, calcular distancias y después extraer/separar las partes de estos campos que necesites en un QUERY, considera el siguiente ejemplo:

SELECT DATE(now()) AS fecha, TIME(now()) AS hora, now() AS datetime;
Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *