{ ------------------------------------------------------------------------------- PROGRAMA : NOPRRP045 OBJETIVO : Informe para el Ministerio de Trabajo. Genera (en el server, via motor de reportes) el cuadro de: - Monto en RD$ (SUELDO del mes) por NIVEL EDUCATIVO, por mes y por sexo. - Cantidad de empleados por mes y por sexo. Se muestra en el visor de reportes; desde ahi el usuario lo exporta a EXCEL o PDF. FUENTES DE DATOS : Nivel educativo -> adtb00003.nivel_emp -> adtb00005 Sexo -> adtb00021.sexo ('M'/'F', titular con cod_par IS NULL) Sueldo -> notb00008.valor WHERE cod_mov = 1 (solo sueldo, sin horas extras) DISENO : noprrp045.4rp (datos: noprrp045.rdd, rutina r_min) PROGRAMADOR : Ing. Juan F. Soto FECHA REALIZACION : Julio 30, 2026 ------------------------------------------------------------------------------- } GLOBALS "noprgb000.4gl" DEFINE p_anio INTEGER -- ano a reportar MAIN DEFER INTERRUPT CALL ARG_VAL(1) RETURNING usuarios CALL ARG_VAL(2) RETURNING clave CALL startlog("noprrp045.log") CONNECT TO "smarmotech" USER usuarios USING clave SELECT a.* INTO p_companias.* FROM companias a CALL noprrp045() END MAIN FUNCTION noprrp045() DEFINE monto ARRAY[12,25] OF DECIMAL(16,2) -- [fila 6..12, col 2..25] DEFINE conteo ARRAY[25] OF INTEGER -- [col 2..25] DEFINE f, c, m SMALLINT DEFINE r_nom CHAR(30) DEFINE r_mes SMALLINT DEFINE r_sexo CHAR(1) DEFINE r_monto DECIMAL(16,2) DEFINE r_cant INTEGER DEFINE fila_e SMALLINT DEFINE sin_edu DECIMAL(16,2) DEFINE sin_sex DECIMAL(16,2) DEFINE th, tm DECIMAL(18,2) -- totales de monto por mes (H, M) DEFINE hay_datos SMALLINT DEFINE niveles ARRAY[7] OF CHAR(35) DEFINE vals DYNAMIC ARRAY OF VARCHAR(24) LET niveles[1] = "NINGUNO" LET niveles[2] = "PRIMARIA" LET niveles[3] = "SECUNDARIA" LET niveles[4] = "TECNICO SUPERIOR" LET niveles[5] = "ESTUDIANTE UNIVERSITARIO" LET niveles[6] = "GRADO UNIVERSITARIO (LICENCIATURA)" LET niveles[7] = "POSGRADO" OPTIONS FORM LINE 8, ERROR LINE 23, COMMENT LINE 21 CLEAR SCREEN OPEN FORM nofmrp045 FROM "nofmrp045" DISPLAY FORM nofmrp045 DISPLAY "noprrp045" AT 4,3 ATTRIBUTE(RED) DISPLAY "Informe Ministerio de Trabajo" AT 6,25 ATTRIBUTE(BLACK) LET p_anio = YEAR(TODAY) INPUT BY NAME p_anio WITHOUT DEFAULTS AFTER FIELD p_anio IF p_anio IS NULL OR p_anio < 1990 OR p_anio > 2100 THEN CALL fgl_winmessage("Aviso", "Digite un ano valido.", "stop") NEXT FIELD p_anio END IF ON ACTION cancel RETURN AFTER INPUT IF int_flag THEN LET int_flag = FALSE RETURN END IF END INPUT ------------------------------------------------------------------ -- Inicializa acumuladores ------------------------------------------------------------------ FOR f = 1 TO 12 FOR c = 1 TO 25 LET monto[f,c] = 0 END FOR END FOR FOR c = 1 TO 25 LET conteo[c] = 0 END FOR LET sin_edu = 0 LET sin_sex = 0 LET hay_datos = FALSE DISPLAY "Buscando informacion... Espere por favor" AT 19,14 ATTRIBUTE(REVERSE, BOLD) ------------------------------------------------------------------ -- (1) Monto RD$ = SUELDO (cod_mov=1) por nivel educativo / mes / sexo ------------------------------------------------------------------ LET selec = "SELECT RTRIM(ISNULL(ed.nom_educa,'')) AS nom_educa, ", " MONTH(n.fecha) AS mes, ", " ISNULL(dep.sexo,'') AS sexo, ", " SUM(n.valor) AS monto ", "FROM notb00008 n ", " JOIN adtb00003 e ON e.num_emp = n.num_emp ", " LEFT JOIN adtb00005 ed ON ed.cod_educa = e.nivel_emp ", " LEFT JOIN (SELECT num_emp, MAX(sexo) AS sexo ", " FROM adtb00021 WHERE cod_par IS NULL ", " GROUP BY num_emp) dep ON dep.num_emp = e.num_emp ", "WHERE YEAR(n.fecha) = ", p_anio, " ", " AND n.cod_mov = 1 ", -- SOLO SUELDO (sin horas extras ni otros ingresos) "GROUP BY RTRIM(ISNULL(ed.nom_educa,'')), MONTH(n.fecha), ISNULL(dep.sexo,'') " PREPARE q_monto FROM selec DECLARE cur_monto CURSOR FOR q_monto FOREACH cur_monto INTO r_nom, r_mes, r_sexo, r_monto LET hay_datos = TRUE LET c = col_grid(r_mes, r_sexo) IF c = 0 THEN LET sin_sex = sin_sex + r_monto CONTINUE FOREACH END IF LET fila_e = fila_educa(r_nom) IF fila_e = 0 THEN LET sin_edu = sin_edu + r_monto CONTINUE FOREACH END IF LET monto[fila_e,c] = monto[fila_e,c] + r_monto END FOREACH ------------------------------------------------------------------ -- (2) Cantidad de empleados por mes / sexo (solo con SUELDO, cod_mov=1) ------------------------------------------------------------------ LET selec = "SELECT MONTH(n.fecha) AS mes, ", " ISNULL(dep.sexo,'') AS sexo, ", " COUNT(DISTINCT n.num_emp) AS cant ", "FROM notb00008 n ", " JOIN adtb00003 e ON e.num_emp = n.num_emp ", " LEFT JOIN (SELECT num_emp, MAX(sexo) AS sexo ", " FROM adtb00021 WHERE cod_par IS NULL ", " GROUP BY num_emp) dep ON dep.num_emp = e.num_emp ", "WHERE YEAR(n.fecha) = ", p_anio, " ", " AND n.cod_mov = 1 ", -- solo empleados con SUELDO en el mes "GROUP BY MONTH(n.fecha), ISNULL(dep.sexo,'') " PREPARE q_cant FROM selec DECLARE cur_cant CURSOR FOR q_cant FOREACH cur_cant INTO r_mes, r_sexo, r_cant LET c = col_grid(r_mes, r_sexo) IF c = 0 THEN CONTINUE FOREACH END IF LET conteo[c] = conteo[c] + r_cant END FOREACH IF NOT hay_datos THEN CALL fgl_winmessage("Informe Ministerio", "No existe nomina procesada para el ano "||p_anio USING "&&&&"||".", "stop") RETURN END IF ------------------------------------------------------------------ -- Motor de reportes: carga el diseno y arranca el visor (preview). -- Desde el visor el usuario exporta a EXCEL o PDF. ------------------------------------------------------------------ LET r_filename = "noprrp045.4rp" IF NOT fgl_report_loadCurrentSettings(r_filename) THEN CALL fgl_winmessage("Error", "No se encontro el diseno del reporte (noprrp045.4rp).", "stop") RETURN END IF -- El usuario elige el formato de salida (EXCEL / PDF / SVG) con la -- funcion compartida seleccionarSalida() (otrodir/seleccionarsalida.4gl). LET preview = 1 CALL seleccionarSalida() RETURNING r_output CALL fgl_report_selectDevice(r_output) CALL fgl_report_selectPreview(preview) LET handler = fgl_report_commitCurrentSettings() START REPORT r_min TO XML HANDLER handler -- fila de titulo con empresa y ano FOR c = 1 TO 36 LET vals[c] = " " END FOR CALL emite_fila("T", p_companias.nombre CLIPPED||" - ANO "||(p_anio USING "&&&&"), vals) -- 7 filas de monto (grid 6..12 -> niveles 1..7). -- Por cada mes se emiten 3 columnas: Hombre, Mujer, Total (H+M). FOR f = 6 TO 12 FOR m = 1 TO 12 LET vals[3*m-2] = monto[f,2*m] USING "-###,###,##&.&&" LET vals[3*m-1] = monto[f,2*m+1] USING "-###,###,##&.&&" LET vals[3*m] = (monto[f,2*m]+monto[f,2*m+1]) USING "-###,###,##&.&&" END FOR CALL emite_fila("A", niveles[f-5], vals) END FOR -- fila TOTAL MONTO EMPLEADO: suma de todos los niveles por mes. -- (Hombre = suma de todos los H; Mujer = suma de todas las M; Total = H+M) -- Sirve para cuadrar con el total de la nomina pagada. FOR m = 1 TO 12 LET th = 0 LET tm = 0 FOR f = 6 TO 12 LET th = th + monto[f,2*m] LET tm = tm + monto[f,2*m+1] END FOR LET vals[3*m-2] = th USING "-###,###,##&.&&" LET vals[3*m-1] = tm USING "-###,###,##&.&&" LET vals[3*m] = (th+tm) USING "-###,###,##&.&&" END FOR CALL emite_fila("M", "TOTAL MONTO EMPLEADO", vals) -- fila de conteo total de empleados (Hombre, Mujer, Total por mes) FOR m = 1 TO 12 LET vals[3*m-2] = conteo[2*m] USING "-###,###,##&" LET vals[3*m-1] = conteo[2*m+1] USING "-###,###,##&" LET vals[3*m] = (conteo[2*m]+conteo[2*m+1]) USING "-###,###,##&" END FOR CALL emite_fila("C", "TOTAL EMPLEADOS", vals) -- Secciones 4-8: foto demografica de empleados activos (status_t IS NULL) a hoy CALL emite_demografia() FINISH REPORT r_min CLEAR SCREEN ------------------------------------------------------------------ -- Aviso de datos que no se pudieron clasificar (no se pierden en -- silencio: se informa para corregir el maestro) ------------------------------------------------------------------ IF sin_edu > 0 OR sin_sex > 0 THEN CALL fgl_winmessage("Datos sin clasificar", "Monto sin nivel educativo mapeado: "||(sin_edu USING "-#,###,###,##&.&&")|| "\nMonto de empleados sin sexo en adtb00021: "||(sin_sex USING "-#,###,###,##&.&&")|| "\n\nRevise el nivel educativo (nivel_emp/adtb00005) y el sexo de "|| "esos empleados en la maestra.", "exclamation") END IF END FUNCTION ------------------------------------------------------------------------ -- Emite una fila al reporte. tipo: 'A'=monto RD$, 'C'=conteo ------------------------------------------------------------------------ FUNCTION emite_fila(p_tipo, p_nivel, p_vals) DEFINE p_tipo CHAR(1) DEFINE p_nivel CHAR(60) DEFINE p_vals DYNAMIC ARRAY OF VARCHAR(24) DEFINE reg RECORD tipo CHAR(1), nivel CHAR(60), v01 VARCHAR(24), v02 VARCHAR(24), v03 VARCHAR(24), v04 VARCHAR(24), v05 VARCHAR(24), v06 VARCHAR(24), v07 VARCHAR(24), v08 VARCHAR(24), v09 VARCHAR(24), v10 VARCHAR(24), v11 VARCHAR(24), v12 VARCHAR(24), v13 VARCHAR(24), v14 VARCHAR(24), v15 VARCHAR(24), v16 VARCHAR(24), v17 VARCHAR(24), v18 VARCHAR(24), v19 VARCHAR(24), v20 VARCHAR(24), v21 VARCHAR(24), v22 VARCHAR(24), v23 VARCHAR(24), v24 VARCHAR(24), v25 VARCHAR(24), v26 VARCHAR(24), v27 VARCHAR(24), v28 VARCHAR(24), v29 VARCHAR(24), v30 VARCHAR(24), v31 VARCHAR(24), v32 VARCHAR(24), v33 VARCHAR(24), v34 VARCHAR(24), v35 VARCHAR(24), v36 VARCHAR(24) END RECORD LET reg.tipo = p_tipo LET reg.nivel = p_nivel LET reg.v01 = p_vals[1] LET reg.v02 = p_vals[2] LET reg.v03 = p_vals[3] LET reg.v04 = p_vals[4] LET reg.v05 = p_vals[5] LET reg.v06 = p_vals[6] LET reg.v07 = p_vals[7] LET reg.v08 = p_vals[8] LET reg.v09 = p_vals[9] LET reg.v10 = p_vals[10] LET reg.v11 = p_vals[11] LET reg.v12 = p_vals[12] LET reg.v13 = p_vals[13] LET reg.v14 = p_vals[14] LET reg.v15 = p_vals[15] LET reg.v16 = p_vals[16] LET reg.v17 = p_vals[17] LET reg.v18 = p_vals[18] LET reg.v19 = p_vals[19] LET reg.v20 = p_vals[20] LET reg.v21 = p_vals[21] LET reg.v22 = p_vals[22] LET reg.v23 = p_vals[23] LET reg.v24 = p_vals[24] LET reg.v25 = p_vals[25] LET reg.v26 = p_vals[26] LET reg.v27 = p_vals[27] LET reg.v28 = p_vals[28] LET reg.v29 = p_vals[29] LET reg.v30 = p_vals[30] LET reg.v31 = p_vals[31] LET reg.v32 = p_vals[32] LET reg.v33 = p_vals[33] LET reg.v34 = p_vals[34] LET reg.v35 = p_vals[35] LET reg.v36 = p_vals[36] OUTPUT TO REPORT r_min(reg.*) END FUNCTION ------------------------------------------------------------------------ -- Rutina de reporte. Un registro por fila del cuadro. ------------------------------------------------------------------------ REPORT r_min(x) DEFINE x RECORD tipo CHAR(1), nivel CHAR(60), v01 VARCHAR(24), v02 VARCHAR(24), v03 VARCHAR(24), v04 VARCHAR(24), v05 VARCHAR(24), v06 VARCHAR(24), v07 VARCHAR(24), v08 VARCHAR(24), v09 VARCHAR(24), v10 VARCHAR(24), v11 VARCHAR(24), v12 VARCHAR(24), v13 VARCHAR(24), v14 VARCHAR(24), v15 VARCHAR(24), v16 VARCHAR(24), v17 VARCHAR(24), v18 VARCHAR(24), v19 VARCHAR(24), v20 VARCHAR(24), v21 VARCHAR(24), v22 VARCHAR(24), v23 VARCHAR(24), v24 VARCHAR(24), v25 VARCHAR(24), v26 VARCHAR(24), v27 VARCHAR(24), v28 VARCHAR(24), v29 VARCHAR(24), v30 VARCHAR(24), v31 VARCHAR(24), v32 VARCHAR(24), v33 VARCHAR(24), v34 VARCHAR(24), v35 VARCHAR(24), v36 VARCHAR(24) END RECORD DEFINE fecha_actual DATE FORMAT FIRST PAGE HEADER LET fecha_actual = TODAY PRINTX p_companias.nombre, p_anio, fecha_actual ON EVERY ROW PRINTX x.tipo, x.nivel, x.v01, x.v02, x.v03, x.v04, x.v05, x.v06, x.v07, x.v08, x.v09, x.v10, x.v11, x.v12, x.v13, x.v14, x.v15, x.v16, x.v17, x.v18, x.v19, x.v20, x.v21, x.v22, x.v23, x.v24, x.v25, x.v26, x.v27, x.v28, x.v29, x.v30, x.v31, x.v32, x.v33, x.v34, x.v35, x.v36 END REPORT ------------------------------------------------------------------------ -- Devuelve la fila del formato (6..12) segun el nombre del nivel -- educativo (catalogo adtb00005). 0 = no mapeado. -- BASICA->7 SECUNDARIA/BACHILLER->8 TECNICO->9 -- ESTUDIANTE UNIVERSITARIO->10 PROFESIONAL->11 -- DIPLOMADO/POSTGRADO/MAESTRIA/ESPECIALIDAD/DOCTORADO->12 -- El orden importa: POSTGRADO antes que GRADO; ESTUDIANTE antes que -- UNIVERSITARIO. ------------------------------------------------------------------------ FUNCTION fila_educa(p_nom) DEFINE p_nom STRING DEFINE s CHAR(40) LET s = UPSHIFT(p_nom CLIPPED) IF s CLIPPED = "" THEN RETURN 0 END IF IF s MATCHES "*NINGUN*" THEN RETURN 6 END IF IF s MATCHES "*PRIMARIA*" OR s MATCHES "*BASICA*" THEN RETURN 7 END IF IF s MATCHES "*SECUNDAR*" OR s MATCHES "*BACHILLER*" THEN RETURN 8 END IF IF s MATCHES "*TECNIC*" THEN RETURN 9 END IF IF s MATCHES "*ESTUDIANTE*" THEN RETURN 10 END IF IF s MATCHES "*POSGRAD*" OR s MATCHES "*POSTGRAD*" OR s MATCHES "*MAESTR*" OR s MATCHES "*DOCTORAD*" OR s MATCHES "*ESPECIALIDAD*" OR s MATCHES "*DIPLOM*" THEN RETURN 12 END IF IF s MATCHES "*LICENCIAT*" OR s MATCHES "*GRADO*" OR s MATCHES "*UNIVERSITARI*" OR s MATCHES "*PROFESIONAL*" THEN RETURN 11 END IF RETURN 0 END FUNCTION ------------------------------------------------------------------------ -- Columna del grid (2..25) segun mes (1..12) y sexo. -- Hombre ('M') -> 2*mes Mujer ('F') -> 2*mes+1 0 = invalido ------------------------------------------------------------------------ FUNCTION col_grid(p_mes, p_sexo) DEFINE p_mes SMALLINT DEFINE p_sexo CHAR(1) IF p_mes < 1 OR p_mes > 12 THEN RETURN 0 END IF CASE UPSHIFT(p_sexo) WHEN "M" RETURN 2 * p_mes WHEN "F" RETURN 2 * p_mes + 1 OTHERWISE RETURN 0 END CASE END FUNCTION ------------------------------------------------------------------------ -- Secciones 4-8: foto demografica de los empleados ACTIVOS (status_t IS -- NULL) al dia de hoy. Cuenta empleados (sec 8 = promedio de sueldo_ac). -- Edad -> adtb00003.fech_nac a hoy -- Antiguedad -> adtb00003.fech_efec a hoy -- Sexo -> adtb00021 (titular, cod_par IS NULL) -- Nivel -> adtb00005 via nivel_emp -- E.civil -> adtb00003.estado_civil ------------------------------------------------------------------------ FUNCTION emite_demografia() DEFINE e_sexo CHAR(1) DEFINE e_ecivil CHAR(1) DEFINE e_fnac DATE DEFINE e_fefec DATE DEFINE e_sueldo DECIMAL(12,2) DEFINE e_nom CHAR(30) DEFINE si, nf, ageg, teng, mi SMALLINT DEFINE edad, tanios INTEGER DEFINE i, g SMALLINT DEFINE tot, th_, tm_ INTEGER DEFINE prom DECIMAL(16,2) DEFINE gsum DECIMAL(18,2) DEFINE gcnt INTEGER DEFINE vals DYNAMIC ARRAY OF VARCHAR(24) DEFINE c4 ARRAY[7,2] OF INTEGER -- nivel x (H,M) DEFINE c5 ARRAY[7,5] OF INTEGER -- nivel x grupo edad DEFINE c6 ARRAY[6,7] OF INTEGER -- e.civil x (H,M,edad1..5) DEFINE c7 ARRAY[5,7] OF INTEGER -- antiguedad x (H,M,edad1..5) DEFINE s8sum ARRAY[6,5] OF DECIMAL(18,2) -- suma sueldo por (estado civil, grupo edad) DEFINE s8cnt ARRAY[6,5] OF INTEGER DEFINE csum DECIMAL(18,2) DEFINE ccnt INTEGER DEFINE niv ARRAY[7] OF CHAR(35) DEFINE agl ARRAY[5] OF CHAR(8) DEFINE mar ARRAY[6] OF CHAR(20) DEFINE ten ARRAY[5] OF CHAR(14) LET niv[1]="NINGUNO" LET niv[2]="PRIMARIA" LET niv[3]="SECUNDARIA" LET niv[4]="TECNICO SUPERIOR" LET niv[5]="ESTUDIANTE UNIVERSITARIO" LET niv[6]="GRADO UNIVERSIT. (LIC.)" LET niv[7]="POSGRADO" LET agl[1]="18-25" LET agl[2]="26-30" LET agl[3]="31-40" LET agl[4]="41-50" LET agl[5]="51+" LET mar[1]="SOLTERO(A)" LET mar[2]="CASADO(A)" LET mar[3]="UNION LIBRE" LET mar[4]="DIVORCIADO(A)" LET mar[5]="VIUDO(A)" LET mar[6]="NO INDICADO" LET ten[1]="MENOS DE 1" LET ten[2]="1 A 5" LET ten[3]="6 A 10" LET ten[4]="11 A 20" LET ten[5]="MAS DE 20" FOR i=1 TO 7 LET c4[i,1]=0 LET c4[i,2]=0 END FOR FOR i=1 TO 7 FOR g=1 TO 5 LET c5[i,g]=0 END FOR END FOR FOR i=1 TO 6 FOR g=1 TO 7 LET c6[i,g]=0 END FOR END FOR FOR i=1 TO 5 FOR g=1 TO 7 LET c7[i,g]=0 END FOR END FOR FOR i=1 TO 6 FOR g=1 TO 5 LET s8sum[i,g]=0 LET s8cnt[i,g]=0 END FOR END FOR LET selec = "SELECT ISNULL(dep.sexo,''), ISNULL(e.estado_civil,''), e.fech_nac, ", " e.fech_efec, ISNULL(e.sueldo_ac,0), RTRIM(ISNULL(ed.nom_educa,'')) ", "FROM adtb00003 e ", " LEFT JOIN adtb00005 ed ON ed.cod_educa = e.nivel_emp ", " LEFT JOIN (SELECT num_emp, MAX(sexo) AS sexo FROM adtb00021 ", " WHERE cod_par IS NULL GROUP BY num_emp) dep ON dep.num_emp = e.num_emp ", "WHERE e.status_t IS NULL " PREPARE q_demo FROM selec DECLARE cur_demo CURSOR FOR q_demo FOREACH cur_demo INTO e_sexo, e_ecivil, e_fnac, e_fefec, e_sueldo, e_nom LET si = 0 IF UPSHIFT(e_sexo) = "M" THEN LET si = 1 END IF IF UPSHIFT(e_sexo) = "F" THEN LET si = 2 END IF LET nf = fila_educa(e_nom) IF nf > 0 THEN LET nf = nf - 5 END IF -- 1..7 (0 si no mapea) LET edad = anios_hasta_hoy(e_fnac) LET ageg = 0 IF edad >= 0 THEN LET ageg = grupo_edad(edad) END IF LET tanios = anios_hasta_hoy(e_fefec) LET teng = 0 IF tanios >= 0 THEN LET teng = rango_antig(tanios) END IF LET mi = grupo_marital(e_ecivil) IF nf > 0 AND si > 0 THEN LET c4[nf,si] = c4[nf,si] + 1 END IF IF nf > 0 AND ageg > 0 THEN LET c5[nf,ageg] = c5[nf,ageg] + 1 END IF IF si > 0 THEN LET c6[mi,si] = c6[mi,si] + 1 END IF IF ageg > 0 THEN LET c6[mi,2+ageg] = c6[mi,2+ageg] + 1 END IF IF teng > 0 THEN IF si > 0 THEN LET c7[teng,si] = c7[teng,si] + 1 END IF IF ageg > 0 THEN LET c7[teng,2+ageg] = c7[teng,2+ageg] + 1 END IF END IF IF ageg > 0 THEN LET s8sum[mi,ageg] = s8sum[mi,ageg] + e_sueldo LET s8cnt[mi,ageg] = s8cnt[mi,ageg] + 1 END IF END FOREACH ---------------- 4- Nivel academico por genero ---------------- CALL limpia_vals(vals) CALL emite_fila("S", "", vals) CALL emite_fila("S", "4- NIVEL ACADEMICO POR GENERO", vals) CALL limpia_vals(vals) LET vals[1]="HOMBRE" LET vals[2]="MUJER" LET vals[3]="TOTAL" CALL emite_fila("H", "NIVEL ACADEMICO", vals) LET th_=0 LET tm_=0 FOR i=1 TO 7 CALL limpia_vals(vals) LET vals[1] = c4[i,1] USING "-###,###,##&" LET vals[2] = c4[i,2] USING "-###,###,##&" LET vals[3] = (c4[i,1]+c4[i,2]) USING "-###,###,##&" CALL emite_fila("D", niv[i], vals) LET th_=th_+c4[i,1] LET tm_=tm_+c4[i,2] END FOR CALL limpia_vals(vals) LET vals[1]=th_ USING "-###,###,##&" LET vals[2]=tm_ USING "-###,###,##&" LET vals[3]=(th_+tm_) USING "-###,###,##&" CALL emite_fila("D", "TOTAL", vals) ---------------- 5- Nivel academico por grupo de edad ---------------- CALL limpia_vals(vals) CALL emite_fila("S", "", vals) CALL emite_fila("S", "5- NIVEL ACADEMICO POR GRUPO EDAD", vals) CALL limpia_vals(vals) FOR g=1 TO 5 LET vals[g]=agl[g] END FOR LET vals[6]="TOTAL" CALL emite_fila("H", "NIVEL ACADEMICO", vals) FOR i=1 TO 7 CALL limpia_vals(vals) LET tot=0 FOR g=1 TO 5 LET vals[g]=c5[i,g] USING "-###,###,##&" LET tot=tot+c5[i,g] END FOR LET vals[6]=tot USING "-###,###,##&" CALL emite_fila("D", niv[i], vals) END FOR CALL limpia_vals(vals) LET tot=0 FOR g=1 TO 5 LET th_=0 FOR i=1 TO 7 LET th_=th_+c5[i,g] END FOR LET vals[g]=th_ USING "-###,###,##&" LET tot=tot+th_ END FOR LET vals[6]=tot USING "-###,###,##&" CALL emite_fila("D", "TOTAL", vals) ---------------- 6- Estatus marital por genero y grupo de edad ---------------- CALL limpia_vals(vals) CALL emite_fila("S", "", vals) CALL emite_fila("S", "6- ESTADO CIVIL POR GENERO Y EDAD", vals) CALL limpia_vals(vals) LET vals[1]="HOMBRE" LET vals[2]="MUJER" FOR g=1 TO 5 LET vals[2+g]=agl[g] END FOR LET vals[8]="TOTAL" CALL emite_fila("H", "ESTADO CIVIL", vals) FOR i=1 TO 6 CALL limpia_vals(vals) FOR g=1 TO 7 LET vals[g]=c6[i,g] USING "-###,###,##&" END FOR LET vals[8]=(c6[i,1]+c6[i,2]) USING "-###,###,##&" CALL emite_fila("D", mar[i], vals) END FOR ---------------- 7- Tiempo en la empresa por genero y grupo de edad ---------------- CALL limpia_vals(vals) CALL emite_fila("S", "", vals) CALL emite_fila("S", "7- ANTIGUEDAD POR GENERO Y EDAD (anos)", vals) CALL limpia_vals(vals) LET vals[1]="HOMBRE" LET vals[2]="MUJER" FOR g=1 TO 5 LET vals[2+g]=agl[g] END FOR LET vals[8]="TOTAL" CALL emite_fila("H", "ANTIGUEDAD", vals) FOR i=1 TO 5 CALL limpia_vals(vals) FOR g=1 TO 7 LET vals[g]=c7[i,g] USING "-###,###,##&" END FOR LET vals[8]=(c7[i,1]+c7[i,2]) USING "-###,###,##&" CALL emite_fila("D", ten[i], vals) END FOR ---------------- 8- Sueldo promedio por estado civil y grupo de edad ---------------- CALL limpia_vals(vals) CALL emite_fila("S", "", vals) CALL emite_fila("S", "8- SUELDO PROMEDIO POR ESTADO CIVIL Y GRUPO EDAD", vals) CALL limpia_vals(vals) FOR g=1 TO 5 LET vals[g]=agl[g] END FOR LET vals[6]="GENERAL" CALL emite_fila("H", "ESTADO CIVIL", vals) -- una fila por estado civil: promedio de sueldo por grupo de edad FOR i=1 TO 6 CALL limpia_vals(vals) LET gsum=0 LET gcnt=0 FOR g=1 TO 5 IF s8cnt[i,g] > 0 THEN LET prom = s8sum[i,g] / s8cnt[i,g] ELSE LET prom = 0 END IF LET vals[g] = prom USING "-###,###,##&.&&" LET gsum = gsum + s8sum[i,g] LET gcnt = gcnt + s8cnt[i,g] END FOR IF gcnt > 0 THEN LET prom = gsum / gcnt ELSE LET prom = 0 END IF LET vals[6] = prom USING "-###,###,##&.&&" CALL emite_fila("D", mar[i], vals) END FOR -- fila GENERAL: promedio por grupo de edad (todos los estados civiles) CALL limpia_vals(vals) LET gsum=0 LET gcnt=0 FOR g=1 TO 5 LET csum=0 LET ccnt=0 FOR i=1 TO 6 LET csum = csum + s8sum[i,g] LET ccnt = ccnt + s8cnt[i,g] END FOR IF ccnt > 0 THEN LET prom = csum / ccnt ELSE LET prom = 0 END IF LET vals[g] = prom USING "-###,###,##&.&&" LET gsum = gsum + csum LET gcnt = gcnt + ccnt END FOR IF gcnt > 0 THEN LET prom = gsum / gcnt ELSE LET prom = 0 END IF LET vals[6] = prom USING "-###,###,##&.&&" CALL emite_fila("D", "GENERAL", vals) END FUNCTION -- Limpia las 36 columnas de valores (las deja en blanco) FUNCTION limpia_vals(v) DEFINE v DYNAMIC ARRAY OF VARCHAR(24) DEFINE i SMALLINT FOR i = 1 TO 36 LET v[i] = " " END FOR END FUNCTION -- Anos completos desde p_desde hasta hoy (-1 si es nulo) FUNCTION anios_hasta_hoy(p_desde) DEFINE p_desde DATE DEFINE a INTEGER IF p_desde IS NULL THEN RETURN -1 END IF LET a = YEAR(TODAY) - YEAR(p_desde) IF MONTH(TODAY) < MONTH(p_desde) OR (MONTH(TODAY) = MONTH(p_desde) AND DAY(TODAY) < DAY(p_desde)) THEN LET a = a - 1 END IF RETURN a END FUNCTION -- Grupo de edad: 1=18-25 2=26-30 3=31-40 4=41-50 5=51+ FUNCTION grupo_edad(p_edad) DEFINE p_edad INTEGER IF p_edad <= 25 THEN RETURN 1 END IF IF p_edad <= 30 THEN RETURN 2 END IF IF p_edad <= 40 THEN RETURN 3 END IF IF p_edad <= 50 THEN RETURN 4 END IF RETURN 5 END FUNCTION -- Rango antiguedad: 1=<1 2=1-5 3=6-10 4=11-20 5=20+ FUNCTION rango_antig(p_anos) DEFINE p_anos INTEGER IF p_anos < 1 THEN RETURN 1 END IF IF p_anos <= 5 THEN RETURN 2 END IF IF p_anos <= 10 THEN RETURN 3 END IF IF p_anos <= 20 THEN RETURN 4 END IF RETURN 5 END FUNCTION -- Grupo estado civil: 1=S 2=C 3=U 4=D 5=V 6=otro/blanco FUNCTION grupo_marital(p_ec) DEFINE p_ec CHAR(1) CASE UPSHIFT(p_ec) WHEN "S" RETURN 1 WHEN "C" RETURN 2 WHEN "U" RETURN 3 WHEN "D" RETURN 4 WHEN "V" RETURN 5 OTHERWISE RETURN 6 END CASE END FUNCTION