{ ----------------------------------------------------------------------------- MODULO : prtraza OBJETIVO : Trazabilidad del Bloque. Dado un codigo_bloque, arma el recorrido completo desde cttb00003 (inventario inicial, produccion, salidas y recepciones entre departamentos, hasta almacen) y lo presenta como una pagina HTML que se abre en el navegador del cliente. USADO POR: prprmt003 (boton "Trazabilidad") NOTA : Requiere el template 'prtraza.html' desplegado junto al programa (misma carpeta bin donde corre el .42m). ----------------------------------------------------------------------------- } IMPORT os SCHEMA smarmotech # guard one-time del PREPARE/DECLARE (evita -404 al re-trazar en la misma sesion) DEFINE m_traza_prep SMALLINT DEFINE m_rango_prep SMALLINT FUNCTION trazabilidad_bloque(p_bloque) DEFINE p_bloque STRING DEFINE eventos DYNAMIC ARRAY OF RECORD num_doc INTEGER, fecha CHAR(10), dep_no SMALLINT, dep_nom CHAR(30), cod_mov SMALLINT, mov_desc CHAR(30), estado_mov SMALLINT, cod_prod INTEGER, prod_desc CHAR(60), unidad CHAR(6), cantidad DECIMAL(18,5), medida DECIMAL(18,5), emp_no INTEGER, emp_nom CHAR(60), recep_no SMALLINT, recep_nom CHAR(30), ref_no INTEGER, estatus CHAR(1) END RECORD DEFINE i, j, found, ndeptos INT DEFINE q, cls, mvlabel, prodtxt, qtytxt, s_cant, s_med, line STRING DEFINE origen, medida_ini, desc_hero, estado_hero, aprovcls, descbloque STRING DEFINE sbflow, sbtl, sbbal, sbfull base.StringBuffer DEFINE cin base.Channel DEFINE nl CHAR(1) DEFINE med_abs, v_balance, v_aprov DECIMAL(18,5) DEFINE bal DYNAMIC ARRAY OF RECORD uni CHAR(6), entro DECIMAL(18,5), salio DECIMAL(18,5) END RECORD LET nl = ASCII 10 IF p_bloque IS NULL OR LENGTH(p_bloque CLIPPED) = 0 THEN RETURN END IF # ---------------- 1. Consultar el recorrido ---------------- LET q = "SELECT a.num_doc, CONVERT(VARCHAR(10),a.fecha,103), a.departamento, ISNULL(d.nom_dpto,''),", " ISNULL(a.cod_mov,0), ISNULL(m.descrip_mov,''), ISNULL(m.estado_mov,0),", " ISNULL(a.cod_prod,0), ISNULL(p.descripcion,''), ISNULL(p.unidad_med,''),", " ISNULL(a.cantidad,0), ISNULL(a.medida,0),", " ISNULL(a.emp_no,0), ISNULL(RTRIM(e.nom1_emp)+' '+RTRIM(e.apell1_emp),''),", " ISNULL(a.depto_receptor,0), ISNULL(dr.nom_dpto,''), ISNULL(a.ref,0),", " ISNULL(a.status_t,'')", " FROM cttb00003 a", " LEFT JOIN adtb00001 d ON d.departamento = a.departamento", " LEFT JOIN cttb00005 m ON m.cod_mov = a.cod_mov", " LEFT JOIN cttb00001 p ON p.cod_prod = a.cod_prod", " LEFT JOIN adtb00003 e ON e.num_emp = a.emp_no", " LEFT JOIN adtb00001 dr ON dr.departamento = a.depto_receptor", " WHERE a.codigo_bloque = ? AND a.status_t IS NULL", " ORDER BY a.fecha, a.num_doc, a.cod_mov" IF m_traza_prep = 0 THEN PREPARE s_traza FROM q DECLARE c_traza CURSOR FOR s_traza LET m_traza_prep = 1 END IF LET i = 1 FOREACH c_traza USING p_bloque INTO eventos[i].* LET i = i + 1 END FOREACH IF eventos.getLength() = 0 THEN CALL fgl_winmessage("Trazabilidad", "No se encontraron movimientos activos para el bloque: " || p_bloque CLIPPED, "information") RETURN END IF # ---------------- 2. Armar secciones HTML ---------------- LET sbflow = base.StringBuffer.create() LET sbtl = base.StringBuffer.create() LET ndeptos = 0 FOR i = 1 TO eventos.getLength() # -- Clasificar el movimiento (color + etiqueta) -- CASE WHEN eventos[i].cod_mov = 1 LET cls = "inicial" LET mvlabel = "Inventario inicial" WHEN eventos[i].cod_mov = 3 IF UPSHIFT(eventos[i].recep_nom) MATCHES "*ALMAC*" THEN LET cls = "almacen" ELSE LET cls = "salida" END IF LET mvlabel = "Salida" WHEN eventos[i].cod_mov = 2 AND eventos[i].ref_no > 0 LET cls = "entrada" LET mvlabel = "Recepcion" OTHERWISE LET cls = "produccion" LET mvlabel = "Produccion" END CASE # -- Texto del producto / destino -- CASE WHEN eventos[i].cod_mov = 3 LET prodtxt = "→ ", eventos[i].recep_nom CLIPPED WHEN eventos[i].cod_mov = 1 IF LENGTH(eventos[i].prod_desc CLIPPED) > 0 THEN LET prodtxt = eventos[i].prod_desc CLIPPED ELSE LET prodtxt = "Bloque recibido" END IF OTHERWISE IF LENGTH(eventos[i].prod_desc CLIPPED) > 0 THEN LET prodtxt = eventos[i].prod_desc CLIPPED ELSE LET prodtxt = "—" END IF END CASE # -- Cantidad / medida formateadas -- LET s_cant = eventos[i].cantidad USING "<<<<<<<<<&.#" LET s_med = eventos[i].medida USING "<<<<<<<<<&.##" LET qtytxt = s_cant CLIPPED, " ", eventos[i].unidad CLIPPED, " · ", s_med CLIPPED # -- Contar departamentos distintos (secuencia) -- # (OR de Genero NO hace short-circuit; se separa para no tocar eventos[0]) IF i = 1 THEN LET ndeptos = ndeptos + 1 ELSE IF eventos[i].dep_no <> eventos[i-1].dep_no THEN LET ndeptos = ndeptos + 1 END IF END IF # -- Paso del recorrido horizontal -- IF i > 1 THEN CALL sbflow.append('