{ PROGRAMA : NOPRMT030 OBJETIVO : GENERAR INFORMACION PARA LAS HORAS EXTRAS Y TRABAJADAS A PARTIR DE LOS DISPOSITIVOS BIOMETRICOS DESARROLLADO POR: ING. JUAN SOTO FECHA DESARROLLADO: JUNIO 30, 2021 DETALLE ADICIONAL: ESTE PROGRAMA USA UNAS TABLAS INTERMEDIAS PARA PODER RESOLVER EL TEMA DE QUE UN EMPLEADO PUNCHE DOS VECES EN LOS DISPOSITIVOS BIOMETRICOS, RESOLVIENDO QUE EL PROCESO SOLO TOME UNA DE LAS DOS REGISTROS PARA EL MISMO DIA AL MOMENTO DE LA ENTRADA O LA SALIDA } GLOBALS "noprgb000.4gl" DEFINE buf base.StringBuffer, chdepartamento STRING DEFINE fecha_inicial,fecha_final,fecha_corte DATE, criterio,selec,respuesta,criterioborrar STRING, data1 RECORD USERID int,CHECKTIME DATETIME YEAR TO minute,CHECKTYPE CHAR(1) END RECORD, xtipoemp CHAR(1), xdepartamento,xnivel,xpuesto,pbar,numnomi,numemp,xuserid,xdia,xmes,xwd,dnumnomi,horaAlmuerzo,idx INT, nombreempleado VARCHAR(100), xhtrabajadas ,xhextras35,xhextras100 DEC(12,2), fechaEntrada,fechaSalida,xhoraentrada,xhorasalida,xhhsalida DATETIME HOUR TO MINUTE, cantidadh35,cantidadh100,cantidadTrabajadas,valorExtra35,valorExtra100,salario_diario,salario, salario_hora DEC(12,2), chcantidad35,chcantidad100,chcantidadtrabaja CHAR(20), arr_departamentos DYNAMIC ARRAY OF RECORD chequeado SMALLINT, departamento INT, titulo VARCHAR(100), tipodepto VARCHAR(100) END RECORD, arr_data DYNAMIC ARRAY OF RECORD empleado, xtrabajadas,xextras35,xhextras100 STRING, num_emp INT END RECORD MAIN DEFER INTERRUPT CALL ARG_VAL(1) RETURNING usuarios CALL ARG_VAL(2) RETURNING clave CONNECT to "smarmotech" USER usuarios USING clave SELECT * INTO p_companias.* FROM companias CALL noprmt038() END MAIN FUNCTION noprmt038() OPEN WINDOW w1 WITH FORM "nofmmt038" DIALOG ATTRIBUTE(UNBUFFERED) INPUT BY NAME fecha_inicial,fecha_final BEFORE INPUT # CALL rangofechas() SELECT MIN(a.num_nomi) INTO numnomi FROM notb00010 a WHERE a.fecha_del > '04/30/2023' SELECT DISTINCT a.fecha_inicio_trabajadas,a.fecha_final_trabajadas INTO fecha_inicial,fecha_final FROM notb00010 a WHERE a.num_nomi = numnomi AND a.status_t IS NULL IF STATUS = NOTFOUND THEN DISPLAY BY NAME numnomi,fecha_inicial,fecha_final CALL fgl_winmessage("INFO","NOMINA NO EXISTE O ESTA CERRADA, NO PUEDES GENERAR H. EXTRAS","stop") RETURN END IF DISPLAY BY NAME numnomi,fecha_inicial,fecha_final CALL departamentos() AFTER INPUT END INPUT INPUT ARRAY arr_departamentos FROM sdepartamentos.* ATTRIBUTE(WITHOUT DEFAULTS) AFTER INPUT END INPUT ON ACTION procesar ATTRIBUTE(TEXT="Procesa") LET selec = "SELECT DATEDIFF(minute,?,?) " PREPARE comando FROM selec LET criterio = "b.departamento in (" FOR idx = 1 TO arr_departamentos.getLength() IF arr_departamentos[idx].chequeado =1 THEN LET chdepartamento = chdepartamento CLIPPED,arr_departamentos[idx].departamento USING "<<<<","," END IF END FOR IF chdepartamento IS NOT NULL THEN LET criterio = criterio CLIPPED,chdepartamento CLIPPED,")" LET criterioborrar = criterio CLIPPED,chdepartamento CLIPPED,")" LET buf = base.StringBuffer.create() CALL buf.append(criterio) CALL buf.replace(",)",")",1) LET criterio = buf.toString() CALL buf.replace("b.","",1) LET criterioborrar = buf.toString() DISPLAY "criterioborrar ",criterioborrar ELSE LET criterio = 'b.departamento=b.departamento ' END IF LET horaAlmuerzo = 1 # BORRA LA DATA EN EL RANGO DE FECHAS LET pbar = 10 CALL ui.Interface.refresh() DISPLAY pbar TO pbar DISPLAY "BORRANDO INFORMACION.... " TO mensajes LET selec = "DELETE FROM checkinout1 WHERE checktime BETWEEN ? AND ? " PREPARE borrar1 FROM selec EXECUTE borrar1 USING fecha_inicial,fecha_final LET selec = "DELETE FROM checkinout2 WHERE checktime BETWEEN ? AND ? " PREPARE borrar2 FROM selec EXECUTE borrar2 USING fecha_inicial,fecha_final LET pbar = 20 CALL ui.Interface.refresh() DISPLAY pbar TO pbar # BORRA REGISTROS DE LA TABLA DE NOVEDADES DEL SISTEMA DE NOMINAS # DECLARE novedad CURSOR FOR # SELECT DISTINCT a.num_nomi FROM checkinout a WHERE checktime BETWEEN fecha_inicial AND fecha_final # FOREACH novedad INTO dnumnomi # END FOREACH LET selec = "DELETE FROM CHECKINOUT_calculo WHERE checktime BETWEEN ? AND ? and ",criterioborrar CLIPPED PREPARE borra3 FROM selec EXECUTE borra3 USING fecha_inicial,fecha_final LET pbar = 30 CALL ui.Interface.refresh() DISPLAY pbar TO pbar LET selec = " SELECT a.USERID,MIN(a.CHECKTIME),a.CHECKTYPE from facial.dbo.CHECKINOUT_calculo a RIGHT OUTER JOIN marmotech.dbo.adtb00003 b ON a.userid = b.cuenta_out and b.status_T is null where a.CHECKTIME between ? and ? and ",criterio CLIPPED, " GROUP BY a.USERID,a.CHECKTYPE,CAST(checktime as date) " PREPARE comando1 FROM selec DECLARE busca1 CURSOR FOR comando1 OPEN busca1 USING fecha_inicial,fecha_final DISPLAY "INICIO PROCESO.... " TO mensajes FOREACH busca1 INTO data1.* IF EXTEND(data1.CHECKTIME,HOUR TO MINUTE) < '11:00' THEN LET data1.CHECKTYPE = 'I' END IF IF EXTEND(data1.CHECKTIME,HOUR TO MINUTE) > '11:01' THEN LET data1.CHECKTYPE = 'O' END IF INSERT INTO CHECKINOUT1(USERID,CHECKTIME,CHECKTYPE) VALUES (data1.*) END FOREACH LET pbar = 60 CALL ui.Interface.refresh() DISPLAY pbar TO pbar # PROCESO DE GENERACION HORAS EXTRAS, TRABAJADAS LET selec = " SELECT a.userid,a.checktime,a.checktype from CHECKINOUT1 a RIGHT OUTER JOIN adtb00003 b ON a.userid = b.cuenta_out and b.status_t is null where a.CHECKTIME between ? and ? and ",criterio CLIPPED PREPARE comando3 FROM selec DECLARE buscaemp SCROLL CURSOR FOR comando3 OPEN buscaemp USING fecha_inicial,fecha_final LET idx = 1 BEGIN WORK FOREACH buscaemp INTO data1.* SELECT UNIQUE a.num_emp,RTRIM(a.nom1_emp)||' '||a.apell1_emp, a.departamento,a.cod_puesto,a.nivel_emp,b.userid,a.nomina, a.sueldo_ac INTO numemp,nombreempleado,xdepartamento,xpuesto,xnivel,xuserid,xtipoemp, salario from adtb00003 a,CHECKINOUT1 b where a.cuenta_out = b.USERID AND b.userid = data1.USERID AND b.checktime = data1.CHECKTIME AND b.checktype = data1.CHECKTYPE # Adicionando al arreglo LET arr_data[idx].empleado = "(",numemp USING "<<<<",") ",nombreempleado CLIPPED, "(",xuserid USING "<<<<<<<",")" LET salario_diario =salario/23.83 IF data1.CHECKTYPE = 'O' THEN SELECT MIN(a.checktime) INTO fechaEntrada from CHECKINOUT1 a WHERE cast(a.checktime as date) = CAST(data1.CHECKTIME AS DATE) and a.userid =data1.USERID and a.CHECKTYPE='I' SELECT MAX(a.checktime) INTO fechaSalida from CHECKINOUT1 a WHERE cast(a.checktime as date) = CAST(data1.CHECKTIME AS DATE) and a.userid =data1.USERID and a.CHECKTYPE='O' LET xhhsalida = data1.CHECKTIME EXECUTE comando INTO xhtrabajadas USING fechaentrada,fechasalida LET xhtrabajadas = xhtrabajadas/60 LET xhtrabajadas = xhtrabajadas - horaAlmuerzo LET chcantidadtrabaja = xhtrabajadas LET arr_data[idx].xtrabajadas = chcantidadtrabaja LET xwd = WEEKDAY(data1.CHECKTIME) IF xwd > 0 THEN #--------- BUSCAR HORARIOS EMPLEDOS SELECT a.entrada,a.salida INTO xhoraentrada,xhorasalida FROM adtb00054 a,adtb00055 b WHERE a.id_hora = b.id_horario and b.num_emp=numemp AND b.fecha = CAST(data1.CHECKTIME AS DATE) DISPLAY "fecha ",data1.CHECKTIME," entrada ",xhoraentrada," salida ",xhorasalida LET xhhsalida = data1.CHECKTIME DISPLAY "HORAS: ",xhorasalida," ",xhhsalida," EMP ",numemp IF xhorasalida < xhhsalida THEN EXECUTE comando INTO xhextras35 USING xhorasalida,xhhsalida DISPLAY "HORA EXTRA: ",xhextras35," EMP ",numemp LET xhextras35 = xhextras35/60 # LET xhextras35 = xhhsalida - xhorasalida LET chcantidad35 = xhextras35 LET cantidadh35 = chcantidad35 LET arr_data[idx].xextras35 = cantidadh35 END IF ELSE # DIAS FERIADOS LET xhorasalida = EXTEND(fechaEntrada,HOUR TO MINUTE) LET xhhsalida = EXTEND(data1.CHECKTIME, HOUR TO MINUTE) EXECUTE comando INTO xhextras100 USING xhorasalida,xhhsalida LET xhextras100 = xhextras100/60 # LET xhextras100 = EXTEND(data1.CHECKTIME, HOUR TO MINUTE) - EXTEND(fechaEntrada,HOUR TO MINUTE) LET chcantidad100 = xhextras100 LET cantidadh100 = chcantidad100 LET arr_data[idx].xhextras100 = cantidadh100 END IF # dias feriados fuera del domingo LET xmes = MONTH(data1.CHECKTIME) LET xdia = DAY(data1.CHECKTIME) SELECT a.dias FROM notb00012 a WHERE a.cod_mes = xmes and a.dias = xdia IF STATUS <> NOTFOUND THEN LET xhorasalida = EXTEND(fechaEntrada,HOUR TO MINUTE) LET xhhsalida = EXTEND(data1.CHECKTIME, HOUR TO MINUTE) EXECUTE comando INTO xhextras100 USING xhorasalida,xhhsalida LET xhextras100 = xhextras100/60 LET arr_data[idx].xhextras100 = xhextras100 END IF END IF SELECT DISTINCT a.checktime FROM checkinout_calculo a WHERE a.checktime = data1.CHECKTIME AND a.userid = data1.USERID IF STATUS = NOTFOUND THEN INSERT INTO CHECKINOUT_calculo (userid,CHECKTIME,CHECKTYPE,num_emp,nombre_empleado, h_trabajadas,h_extras35,h_extras100,departamento) values (data1.*,numemp,nombreempleado,xhtrabajadas,xhextras35,xhextras100,xdepartamento) END IF IF cantidadh35 > 0 THEN #empleado a 3335 860.26 37.64 2.00 75.28 sueldo 20500.00 LET salario_hora = (salario_diario / 8)*1.35 LET valorExtra35 = salario_hora * cantidadh35 IF valorExtra35 IS NULL THEN LET valorExtra35 =0 END IF SELECT a.num_emp FROM notb00007 a WHERE a.num_nomi = numnomi AND a.num_emp = numemp AND a.cod_mov = 3 IF STATUS = NOTFOUND THEN INSERT INTO notb00007 (num_nomi,tipo_emp,cod_mov,num_emp,departamento,departamento_afecta,cod_puesto,nivel_emp,cantidad,valor,us_crea,fech_crea) VALUES (numnomi,xtipoemp,3,numemp,xdepartamento,xdepartamento, xpuesto,xnivel,cantidadh35,valorExtra35,'noprmt030',getdate()) ELSE UPDATE notb00007 SET cantidad = cantidad + cantidadh35,us_mod = 'noprmt030',fech_mod = getdate(), valor = valor + valorExtra35 WHERE num_emp = numemp AND num_nomi = numnomi AND cod_mov = 3 END IF END IF IF cantidadh100 IS NOT NULL THEN LET salario_hora = (salario_diario / 8)*2 LET valorExtra100 = salario_hora * cantidadh100 IF valorExtra100 IS NULL THEN LET valorExtra100 =0 END IF END IF LET xhextras35 =0 LET xhextras100 = 0 LET xhtrabajadas =0 LET cantidadTrabajadas =0 LET cantidadh35=0 LET cantidadh100 =0 LET valorExtra100 =0 LET valorExtra35 = 0 IF pbar < 90 THEN IF idx = 4 THEN LET idx = 1 END IF IF idx < 4 THEN LET pbar = pbar+1 CALL ui.Interface.refresh() DISPLAY pbar TO pbar END IF END IF LET idx = idx + 1 END FOREACH COMMIT WORK LET pbar = 100 CALL ui.Interface.refresh() DISPLAY pbar TO pbar CALL fgl_Winmessage("INFO","PROCESO TERMINADO","INFO") DISPLAY ARRAY arr_data TO sdata.* EXIT PROGRAM ON ACTION CANCEL LET int_flag = FALSE EXIT PROGRAM END DIALOG END FUNCTION FUNCTION departamentos() CALL arr_departamentos.clear() DECLARE busca_dep CURSOR FOR SELECT '0',a.departamento,a.nom_dpto,a.tipo_departamento FROM adtb00001 a,adtb00056 b WHERE a.departamento = b.departamento_visualiza AND b.usuario = usuarios and a.status_t IS NULL ORDER BY a.nom_dpto LET idx = 1 FOREACH busca_dep INTO arr_departamentos[idx].* LET idx = idx + 1 END FOREACH END FUNCTION FUNCTION calculo_extras() END FUNCTION