{ PROGRAMA : prprmt022.4gl OBJETIVO : Visualizar las ordenes, con la finalidad de mostrar diferentes estados DESARROLLADO POR : Ing. Elvis Garcia FECHA : JULIO 12, 2025 } IMPORT util IMPORT FGL fgldialog SCHEMA smarmotech DEFINE usuarios, clave STRING DEFINE pcompanias RECORD LIKE companias.* DEFINE fechas RECORD fech_inicial DATE, fech_final DATE END RECORD DEFINE data DYNAMIC ARRAY OF RECORD orden INT, estado STRING, cotizacion STRING, fecha_orden DATE, cliente STRING, email STRING, vendedor STRING, emailVendedor STRING, celular_vendedor STRING, telefono_casa STRING, celular1 STRING, tel_contacto STRING, parentId STRING, childId STRING END RECORD DEFINE cell_colors DYNAMIC ARRAY OF STRING, criterio STRING, contador INT DEFINE handler om.SaxDocumentHandler, -- return value from fgl_report_commitCurrentSettings() r_filename STRING, -- filename of Report Design Document including .4rp extension r_output VARCHAR(10), -- output format option preview INTEGER MAIN CALL ARG_VAL(1) RETURNING usuarios CALL ARG_VAL(2) RETURNING clave CONNECT TO "smarmotech" USER usuarios USING clave SELECT * INTO pcompanias.* FROM companias CALL estado_ordenes() END MAIN FUNCTION estado_ordenes() OPEN WINDOW w1 WITH FORM "prfmmt022" CALL ui.Interface.LoadStyles("mbsStyle") CALL initConditions() CALL consulta() DIALOG ATTRIBUTE(UNBUFFERED) DISPLAY ARRAY data TO s_tree.* BEFORE DISPLAY DISPLAY BY NAME contador ON ACTION consultar ATTRIBUTES(TEXT = "OK") CALL initConditions() CALL consulta() ON ACTION visualiza_log ATTRIBUTES(TEXT = "Abrir Log") CALL abrir_log(arr_curr()) ON ACTION b_reporte ATTRIBUTE(TEXT="Informe",IMAGE="printer") CALL generar_reporte_tiempos(fechas.fech_inicial, fechas.fech_final) ON ACTION salir ATTRIBUTES(TEXT = "Salir", IMAGE = "fa-power-off") EXIT PROGRAM END DISPLAY END DIALOG CLOSE WINDOW w1 END FUNCTION FUNCTION abrir_log(indice INT) END FUNCTION FUNCTION initConditions() INITIALIZE fechas.* TO NULL CLEAR FORM DIALOG ATTRIBUTES(UNBUFFERED) INPUT BY NAME fechas.* ATTRIBUTES(WITHOUT DEFAULTS) AFTER INPUT IF fechas.fech_final IS NOT NULL AND fechas.fech_inicial IS NOT NULL THEN IF fechas.fech_inicial > fechas.fech_final THEN CALL msg(86) NEXT FIELD fech_inicial END IF END IF END INPUT CONSTRUCT criterio ON view_ordenes.estado, view_ordenes.orden, view_ordenes.rnc, view_ordenes.cliente, view_ordenes.clase, view_ordenes.grupo, view_ordenes.tipo, view_ordenes.medida, view_ordenes.cotizacion FROM estado1, orden1, rnc, nombre_cliente, cod_n, cod_grupo, cod_tipo, cod_sec, cotizacion1 END CONSTRUCT ON ACTION ACCEPT ATTRIBUTES(TEXT = "Consultar", IMAGE = "mag") ACCEPT DIALOG ON ACTION salir ATTRIBUTES(TEXT = "Salir", IMAGE = "fa-power-off") EXIT PROGRAM END DIALOG END FUNCTION FUNCTION consulta() ------------------------------------------------------------------ -- 1) VARIABLES ------------------------------------------------------------------ DEFINE i, grp_no, prod_idx, mov_idx INT DEFINE last_key, curr_key, last_prod STRING DEFINE prod_id, param_fechas STRING DEFINE flag BOOLEAN -- Buffers de FECHAS / ESTADOS del producto activo DEFINE bf_fOrd DATE, bf_fCot DATE, bf_fIns DATE, bf_fTdm DATE, bf_fCal DATE, bf_fDes DATE, bf_fComp DATE, bf_estProd STRING, bf_estProc STRING, bf_observ STRING -- Variables del cursor DEFINE v_orden INT, v_estado STRING, v_cot INT, v_cliente STRING, v_email STRING, v_vendedor STRING, v_emailVend STRING, v_celVend STRING, v_telCasa STRING, v_cel1 STRING, v_telContacto STRING, v_desc_prod STRING, v_docAlm INT, v_desc_mov STRING, v_sumcant DECIMAL(12, 5), v_fInst DATE, v_fTDM DATE, v_fCal DATE, v_fOrd DATE, v_fCot DATE, v_fDoc DATE, v_fDes DATE, v_fcomp DATE, v_estProd STRING, v_estProc STRING, v_observ STRING ------------------------------------------------------------------ -- 2) SENTENCIA SQL ------------------------------------------------------------------ DEFINE sql STRING INITIALIZE cell_colors TO NULL LET sql = " SELECT orden, view_ordenes.ESTADO, cotizacion,Cliente, view_ordenes.email, RTRIM(NOMBRE_VENDEDOR)+' '+RTRIM(APELLIDO_VENDEDOR) AS vendedor, ISNULL(telefono, 'NO TIENE'), ISNULL(vetb00050.telefono_r,'NO TIENE'),ISNULL(vetb00050.celular,'NO TIENE'), ISNULL(vetb00050.celular1,'NO TIENE'),equipoVentas, CONCAT('(',clase,'-',grupo,'-',tipo,'-',medida,') - ',DESCRIPCION_PRODUCTO) AS PRODUCTO, documentoAlmacen, DescripcionMovimiento, SUM(CANTIDAD_ORDEN) AS suma_cantidad_orden, fechaSolicitudInstalacion, fechaSolicitudTDMCompletada, fechaInspeccionCalidad, fechaOrden, fechaCotizacion, FechaDocumento, FechaDespacho, fecha_compromiso, estado_producto, EstadoProcesos, observacion FROM view_ordenes inner join vetb00050 on view_ordenes.cotizacion = vetb00050.cotizacion_no WHERE " IF fechas.fech_inicial IS NULL AND fechas.fech_final IS NULL THEN LET param_fechas = "" END IF IF fechas.fech_inicial IS NOT NULL AND fechas.fech_final IS NULL THEN LET SQL = SQL || " fechaOrden >= ? AND " END IF IF fechas.fech_inicial IS NULL AND fechas.fech_final IS NOT NULL THEN LET SQL = SQL || " fechaOrden <= ? AND " END IF IF fechas.fech_final IS NOT NULL AND fechas.fech_final IS NOT NULL THEN LET SQL = SQL || " fechaOrden BETWEEN ? AND ? AND " END IF LET SQL = SQL || criterio CLIPPED || " GROUP BY orden, view_ordenes.ESTADO, cotizacion, Cliente, view_ordenes.email, NOMBRE_VENDEDOR, APELLIDO_VENDEDOR, telefono, equipoVentas, clase, grupo, tipo, medida, DESCRIPCION_PRODUCTO, documentoAlmacen, DescripcionMovimiento, fechaSolicitudInstalacion, fechaSolicitudTDMCompletada, fechaInspeccionCalidad, fechaOrden, fechaCotizacion, FechaDocumento, FechaDespacho, fecha_compromiso, estado_producto, EstadoProcesos, observacion, vetb00050.telefono_o, vetb00050.telefono_r,vetb00050.celular,vetb00050.celular1 ORDER BY orden, view_ordenes.ESTADO, cotizacion, Cliente, view_ordenes.email, vendedor, telefono, equipoVentas, clase, grupo, tipo, medida, DESCRIPCION_PRODUCTO, DescripcionMovimiento" PREPARE stmt FROM sql DECLARE cur CURSOR FOR stmt IF fechas.fech_inicial IS NULL AND fechas.fech_final IS NULL THEN OPEN cur END IF IF fechas.fech_inicial IS NOT NULL AND fechas.fech_final IS NULL THEN OPEN cur USING fechas.fech_inicial END IF IF fechas.fech_inicial IS NULL AND fechas.fech_final IS NOT NULL THEN OPEN cur USING fechas.fech_final END IF IF fechas.fech_final IS NOT NULL AND fechas.fech_final IS NOT NULL THEN OPEN cur USING fechas.fech_inicial, fechas.fech_final END IF OPEN cur ------------------------------------------------------------------ -- 3) CONSTRUCCIÓN DEL TREE ------------------------------------------------------------------ CALL data.clear() LET i = 1 LET contador = 0 LET grp_no = 0 LET last_key = "¤" LET last_prod = "¤" LET prod_id = "" FOREACH cur INTO v_orden, v_estado, v_cot, v_cliente, v_email, v_vendedor, v_emailVend, v_celVend, v_telCasa , v_cel1 , v_telContacto, v_desc_prod, v_docAlm, v_desc_mov, v_sumcant, v_fInst, v_fTDM, v_fCal, v_fOrd, v_fCot, v_fDoc, v_fDes, v_fcomp, v_estProd, v_estProc, v_observ LET curr_key = v_orden || '|' || v_estado || '|' || v_cot || '|' || v_cliente || '|' || v_email || '|' || v_vendedor || '|' || v_emailVend || '|' || v_celVend --===== NUEVA ORDEN ========================================== IF curr_key <> last_key THEN LET i = finaliza_producto( i, prod_id, last_prod, bf_fOrd, bf_fCot, bf_fIns, bf_fTdm, bf_fCal, bf_fDes, bf_fComp, bf_estProd, bf_estProc, bf_observ) LET grp_no = grp_no + 1 LET prod_idx = 0 LET last_prod = "¤" -- Raíz LET data[i].orden = v_orden LET flag = FALSE LET cell_colors[i] = NULL CALL Marcar_Amarillo(data[i].orden) RETURNING flag IF flag THEN LET cell_colors[i] = 'yellow reverse' END IF LET data[i].estado = v_estado LET data[i].cotizacion = v_cot LET data[i].fecha_orden = v_fOrd LET data[i].cliente = v_cliente LET data[i].email = v_email LET data[i].vendedor = v_vendedor LET data[i].emailVendedor = v_emailVend LET data[i].celular_vendedor = v_celVend LET data[i].telefono_casa = v_telCasa LET data[i].celular1 = v_cel1 LET data[i].tel_contacto = v_telcontacto LET data[i].parentId = NULL LET data[i].childId = grp_no LET contador = contador + 1 LET i = i + 1 -- título PRODUCTOS INITIALIZE data[i].* TO NULL LET data[i].estado = "PRODUCTOS" LET data[i].parentId = grp_no LET data[i].childId = grp_no || ".1" LET i = i + 1 END IF --===== NUEVO PRODUCTO ======================================= IF v_desc_prod <> last_prod THEN LET i = finaliza_producto( i, prod_id, last_prod, bf_fOrd, bf_fCot, bf_fIns, bf_fTdm, bf_fCal, bf_fDes, bf_fComp, bf_estProd, bf_estProc, bf_observ) LET prod_idx = prod_idx + 1 LET prod_id = grp_no || ".1." || prod_idx LET mov_idx = 0 LET last_prod = v_desc_prod -- buffer de FECHAS / ESTADOS LET bf_fOrd = v_fOrd; LET bf_fCot = v_fCot LET bf_fIns = v_fInst; LET bf_fTdm = v_fTDM LET bf_fCal = v_fCal; LET bf_fDes = v_fDes LET bf_fComp = v_fComp LET bf_estProd = v_estProd LET bf_estProc = v_estProc LET bf_observ = v_observ -- nodo PRODUCTO INITIALIZE data[i].* TO NULL LET data[i].cotizacion = v_desc_prod || " (" || v_sumcant || ")" LET data[i].parentId = grp_no || ".1" LET data[i].childId = prod_id LET i = i + 1 -- título MOVIMIENTOS INITIALIZE data[i].* TO NULL LET data[i].cotizacion = " MOVIMIENTOS" LET data[i].parentId = prod_id LET data[i].childId = prod_id || ".1" LET i = i + 1 ELSE -- mismo producto ? actualiza buffers IF v_fInst IS NOT NULL THEN LET bf_fIns = v_fInst END IF IF v_fTDM IS NOT NULL THEN LET bf_fTdm = v_fTDM END IF IF v_fCal IS NOT NULL THEN LET bf_fCal = v_fCal END IF IF v_fDes IS NOT NULL THEN LET bf_fDes = v_fDes END IF IF v_fComp IS NOT NULL THEN LET bf_fComp = v_fComp END IF END IF --===== DETALLE MOVIMIENTO =================================== IF v_docAlm IS NOT NULL THEN LET mov_idx = mov_idx + 1 INITIALIZE data[i].* TO NULL LET data[i].cotizacion = " " || v_docAlm || " - " || v_desc_mov CLIPPED || " - " || v_fDoc LET data[i].parentId = prod_id || ".1" LET data[i].childId = prod_id || ".1." || mov_idx LET i = i + 1 END IF LET last_key = curr_key END FOREACH -- cierra el último producto LET i = finaliza_producto( i, prod_id, last_prod, bf_fOrd, bf_fCot, bf_fIns, bf_fTdm, bf_fCal, bf_fDes, bf_fComp, bf_estProd, bf_estProc, bf_observ) END FUNCTION ------------------------------------------------------------------ -- FIN PRODUCTO (devuelve nuevo índice i) ------------------------------------------------------------------ FUNCTION finaliza_producto( start_i INT, p_prod_id STRING, p_last_prod STRING, fOrd DATE, fCot DATE, fIns DATE, fTdm DATE, fCal DATE, fDes DATE, fComp DATE, sProd STRING, sProc STRING, sObs STRING) DEFINE i INT LET i = start_i IF p_last_prod = "¤" THEN RETURN i -- nada pendiente END IF -- ----- FECHAS título + detalles ----- INITIALIZE data[i].* TO NULL LET data[i].cotizacion = " FECHAS" LET data[i].parentId = p_prod_id LET data[i].childId = p_prod_id || ".2" LET i = i + 1 LET i = add_fecha_block( i, p_prod_id || ".2", fOrd, fCot, fIns, fTdm, fCal, fDes, fComp) -- ----- ESTADOS título + detalles ----- INITIALIZE data[i].* TO NULL LET data[i].cotizacion = " ESTADOS" LET data[i].parentId = p_prod_id LET data[i].childId = p_prod_id || ".3" LET i = i + 1 LET sProd = ' Estado producto : ', sProd LET sProc = ' Estado procesos : ', sProc LET sObs = ' Observacion : ', sObs CALL add_simple_detail( i, p_prod_id || ".3", 1, sProd); LET i = i + 1 CALL add_simple_detail( i, p_prod_id || ".3", 2, sProc); LET i = i + 1 CALL add_simple_detail( i, p_prod_id || ".3", 3, sObs); LET i = i + 1 RETURN i END FUNCTION ------------------------------------------------------------------ -- helpers ------------------------------------------------------------------ FUNCTION add_simple_detail(pos INT, parent STRING, n INT, txt STRING) INITIALIZE data[pos].* TO NULL LET data[pos].cotizacion = txt LET data[pos].parentId = parent LET data[pos].childId = parent || "." || n END FUNCTION FUNCTION add_fecha_block( start_i INT, parent STRING, f_ord DATE, f_cot DATE, f_ins DATE, f_tdm DATE, f_cal DATE, f_dep DATE, f_comp DATE) DEFINE i, idx INT, descrip_fecha STRING LET i = start_i LET idx = 0 LET idx = idx + 1 LET descrip_fecha = "Fecha Orden : ", f_ord CALL add_simple_detail(i, parent, idx, descrip_fecha); LET i = i + 1 LET idx = idx + 1 LET descrip_fecha = "Fecha Cotizacion : ", f_cot CALL add_simple_detail(i, parent, idx, descrip_fecha); LET i = i + 1 LET idx = idx + 1 LET descrip_fecha = "Solic. Instalacion : ", f_ins CALL add_simple_detail(i, parent, idx, descrip_fecha); LET i = i + 1 LET idx = idx + 1 LET descrip_fecha = "TDM Completada : ", f_tdm CALL add_simple_detail(i, parent, idx, descrip_fecha); LET i = i + 1 LET idx = idx + 1 LET descrip_fecha = "Inspeccion Calidad : ", f_cal CALL add_simple_detail(i, parent, idx, descrip_fecha); LET i = i + 1 LET idx = idx + 1 LET descrip_fecha = "Fecha Despacho : ", f_dep CALL add_simple_detail(i, parent, idx, descrip_fecha); LET i = i + 1 LET idx = idx + 1 LET descrip_fecha = "Fecha Compromiso : ", f_comp CALL add_simple_detail(i, parent, idx, descrip_fecha); LET i = i + 1 RETURN i END FUNCTION FUNCTION marcar_amarillo(orden INT) DEFINE flag BOOLEAN, idx INT DEFINE CompromisoProduccion DYNAMIC ARRAY OF RECORD orden INT, producto STRING, fecha_compromiso DATE, es_produccion BOOLEAN END RECORD LET flag = FALSE DECLARE data_compromisoProduccion CURSOR FOR SELECT a.num_oc, CONCAT('(',a.cod_n,'-',a.cod_grupo,'-',a.cod_tipo,'-',a.cod_sec,')',b.descrip_esp) AS producto, a.fecha_compromiso, b.es_produccion FROM prtb00013 a INNER JOIN iptb00002 b ON a.cod_n = b.cod_n and a.cod_grupo = b.cod_grupo and a.cod_tipo = b.cod_tipo and a.cod_sec = b.cod_sec WHERE b.es_produccion = 1 and a.num_oc = orden LET idx = 1 FOREACH data_compromisoProduccion INTO CompromisoProduccion[idx].* IF compromisoProduccion[idx].fecha_compromiso IS NULL THEN LET flag = TRUE EXIT FOREACH END IF LET idx = idx + 1 END FOREACH RETURN flag END FUNCTION FUNCTION generar_reporte_tiempos(fi DATE, ff DATE) DEFINE r RECORD -- periodo DATETIME YEAR TO DAY , tiempo_colocacion INTEGER, tiempo_despacho INTEGER, tiempo_solicitud_instalacion INTEGER, tiempo_tdm INTEGER, tiempo_inspeccion_calidad INTEGER END RECORD DEFINE respuesta DYNAMIC ARRAY OF RECORD nombre_categoria STRING, cantidad_dias INTEGER END RECORD DEFINE fecha_final, fecha_inicial DATE DEFINE idx INT DEFINE query_report STRING LET fecha_final = ff USING "yyyy-mm-dd" LET fecha_inicial = fi USING "yyyy-mm-dd" LET r_filename ='tiempos_ordenes.4rp' LET preview = 1 IF fgl_report_loadCurrentSettings(r_filename) THEN -- load the .4rp file CALL fgl_report_selectDevice(r_output) -- changing default CALL fgl_report_selectPreview(preview) -- changing default LET handler = fgl_report_commitCurrentSettings() -- commit changes END IF --run the report IF handler IS NOT NULL THEN START REPORT tiempos_ordenes_report TO XML HANDLER HANDLER LET query_report = --"SELECT DATEADD(month, DATEDIFF(month, 0, fechaOrden), 0) as Fecha_general, "SELECT AVG(ISNULL(DATEDIFF(day, fechaCotizacion, fechaOrden),0)) as 'Cotizacion de la orden', AVG(ISNULL(DATEDIFF(day, fechaOrden, FechaDespacho),0)) as 'Dias para despachar', AVG(ISNULL(DATEDIFF(day, fechaSolicitudInstalacion, fechaOrden),0)) as 'Solicitud de instalacion', AVG(ISNULL(DATEDIFF(day, fechaSolicitudMedida, fechaSolicitudTDMCompletada),0)) as 'Tiempo toma de medida', AVG(ISNULL(DATEDIFF(day, fechaInspeccionCalidad, FechaDespacho),0)) as 'Fecha de inspeccion de calidad' FROM view_ordenes WHERE fechaOrden BETWEEN '",fi USING "mm/dd/yyyy" ,"' AND '",ff USING "mm/dd/yyyy" ,"' AND ",criterio {," GROUP BY DATEADD(month, DATEDIFF(month, 0, fechaOrden), 0) ORDER BY DATEADD(month, DATEDIFF(month, 0, fechaOrden), 0) " } DISPLAY query_report PREPARE buscar_graph FROM query_report EXECUTE buscar_graph INTO --r.periodo, r.tiempo_colocacion, r.tiempo_despacho, r.tiempo_solicitud_instalacion, r.tiempo_tdm, r.tiempo_inspeccion_calidad FOR idx = 1 TO 5 CASE idx WHEN 1 LET respuesta[idx].nombre_categoria = 'Colocacion' LET respuesta[idx].cantidad_dias = r.tiempo_colocacion EXIT CASE WHEN 2 LET respuesta[idx].nombre_categoria = 'Despacho' LET respuesta[idx].cantidad_dias = r.tiempo_despacho EXIT CASE WHEN 3 LET respuesta[idx].nombre_categoria = 'Solic. instalacion' LET respuesta[idx].cantidad_dias = r.tiempo_solicitud_instalacion EXIT CASE WHEN 4 LET respuesta[idx].nombre_categoria = 'TDM' LET respuesta[idx].cantidad_dias = r.tiempo_tdm EXIT CASE WHEN 5 LET respuesta[idx].nombre_categoria = 'Inspec. calidad' LET respuesta[idx].cantidad_dias = r.tiempo_inspeccion_calidad EXIT CASE END CASE IF respuesta[idx].cantidad_dias IS NULL THEN LET respuesta[idx].cantidad_dias = 0 END IF DISPLAY respuesta[idx].nombre_categoria DISPLAY respuesta[idx].cantidad_dias OUTPUT TO REPORT tiempos_ordenes_report(fecha_inicial,fecha_final, respuesta[idx].*) END FOR FINISH REPORT tiempos_ordenes_report END IF END FUNCTION REPORT tiempos_ordenes_report(fi,ff, respuesta) DEFINE respuesta RECORD nombre_categoria STRING, cantidad_dias INTEGER END RECORD DEFINE fi, ff DATE DEFINE rango STRING DEFINE hora CHAR(5) DEFINE fecha_reporte CHAR(16) FORMAT PAGE HEADER LET rango = 'Desde el ', fi, ' hasta ', ff LET hora = TIME LET fecha_reporte = TODAY,' ',hora ON EVERY ROW PRINTX respuesta.* END REPORT