arielgritti
Mega Sage

Objetivo/Necesidad

  • Se nos planteó la necesidad de implementar un proceso por el cual un usuario gestor del inventario pudiera actualizar, a partir de un Excel (que convierte en un fichero .CSV) la tabla de asset (alm_asset) de forma autónoma y lo más dinámica posible.

Requisitos

  • Que el usuario final, a través del Service Portal, pueda elegir que campos de la tabla alm_asset quiere actualizar
  • Adjuntar un fichero .CSV que contiene la información en columnas que se corresponden con los campos de alm_asset

Restricciones

  • Lo único que indicamos como obligatorio por parte del usuario en la generación del fichero .CSV es que la primer columna sea el asset_tag (el campo por el cual podemos saber que asset vamos a actualizar) y que las columnas estén en el mismo orden que los campos que elige en el item de actualización masiva
  • El fichero .CSV no lleva encabezado

Implementación

  • Creamos un item de catálogo donde le pedimos que campos, mediante variables del tipo Reference a la tabla sys_dictionary, quiere actualizar. Con esto nos aseguramos varias cosas:
    • Que el nombre del campo será el correcto (evitamos tener que poner un encabezado en el .CSV)
    • Que solo los campos que nosotros "publicamos" se puedan actualizar
    • Obtener información de metadatos de los campos para saber si son a su vez Reference a otras tablas para su tratamiento posterior
  • Un workflow con una tarea del tipo "run script" que se encarga de procesar el excel y actualizar la tabla alm_asset

 

Detalle de la implementación

  • Las variables reference a los campos de la tabla alm_asset tienen esta carecterística:
    • La tabla es alm_asset
    • Los campos no contienen "sys"
    • Y así se puede ir filtrando que campos queremos que aparezcan (el filtro es más grande en mi caso)

find_real_file.png

 

El ítem, para elegir los campos, queda así (puse 4 campos, pero podemos poner 2, 6, 10, los que querramos)

find_real_file.png

find_real_file.png

 

  • La tarea del tipo "Run Script" del workflow, tiene el siguiente código, y las siguientes consideraciones (o retos 😉
    • Como la selección del campo es dinámica, se presentaban dos retos: Saber el nombre del campo para luego actualizarlo, y los campos del tipo Reference (a otras tablas) debía identificarlos, saber de que tabla se trataba, con el dato del fichero .CSV ir a buscar el registro y obtener el SYS_ID para la actualización.
//Variables globales
var vSysId1 = '';
var vSysId2 = '';
var vSysId3 = '';
var vSysId4 = '';
var vValor1 = '';
var vValor2 = '';
var vValor3 = '';
var vValor4 = '';
var debug = true;
var attachment = '';
var attachmentData = '';
var splited = '';
var splited2 = '';
var vAssetTag = '';

//Recupero attach
var attGr = new GlideRecord('sys_attachment');
attGr.addQuery('table_name', 'sc_req_item');
attGr.addQuery('table_sys_id', current.sys_id);
attGr.query();

//Si tengo attach
if(attGr.next()) {
	
	//Proceso attach
	var gsu = (typeof GlideStringUtil != 'undefined') ? (GlideStringUtil) : (Packages.com.glide.util.StringUtil);
	var gsa = (typeof GlideSysAttachment != 'undefined') ? (new GlideSysAttachment()) : (new Packages.com.glide.ui.SysAttachment());
	var attachmentData = gsa.getBytes(attGr);
	var attachment = String(Packages.java.lang.String(attachmentData));
	
	//Splito
	splited = attachment.split('\n');
	
	//Itero cada fila del attach
	for (var i=0; i<splited.length; i++) {
		//Splito again
		split2 = splited[i].split(';');
		
		vAssetTag = split2[0].trim();
		
		//Valores de campo directos
		vValor1 = split2[1].trim();
		vValor2 = split2[2].trim();
		vValor3 = split2[3].trim();
		vValor4 = split2[4].trim();
		
		//Si los valores de campos son reference
		//asset_field1
		if (current.variables.asset_field1.internal_type == 'reference') {
			//es reference, va el sys_id
			vSysId1=devuelveSYSID(current.variables.asset_field1.reference,vValor1);
			vValor1 = vSysId1;
		}
		
		//asset_field2
		if (current.variables.asset_field2.internal_type == 'reference') {
			//es reference, va el sys_id
			vSysId2=devuelveSYSID(current.variables.asset_field2.reference,vValor2);
			vValor2 = vSysId2;
		}
		
		//asset_field3
		if (current.variables.asset_field3.internal_type == 'reference') {
			//es reference, va el sys_id
			vSysId3=devuelveSYSID(current.variables.asset_field3.reference,vValor3);
			vValor3 = vSysId3;
		}
		
		//asset_field4
		if (current.variables.asset_field4.internal_type == 'reference') {
			//es reference, va el sys_id
			vSysId4=devuelveSYSID(current.variables.asset_field4.reference,vValor4);
			vValor4 = vSysId4;
		}
		
		//Recupero asset a actualizar
		var grAssetUpd = new GlideRecord("alm_asset");
		grAssetUpd.addQuery("asset_tag", vAssetTag);
		grAssetUpd.query();
		
		if (grAssetUpd.next()) {
			
			grAssetUpd.setValue(current.variables.asset_field1.element,vValor1);
			grAssetUpd.setValue(current.variables.asset_field2.element,vValor2);
			grAssetUpd.setValue(current.variables.asset_field3.element,vValor3);
			grAssetUpd.setValue(current.variables.asset_field4.element,vValor4);
			
			//Actualizo
			grAssetUpd.update();
		}
		else {gs.log('NOOOOOO encontre asset ' + vAssetTag);}
		}
	}
	
	//Funcion que devuelve el sys_id segun el reference y el valor
	function devuelveSYSID (vReference,vValor) {
		var vQuery = '';
		
		//Segun que tabla sea debo filtrar por diferentes campos
		if (vReference == 'u_acreditaciones') {
			vQuery = "u_acreditacion";
		}
		if (vReference == 'core_company') {
			vQuery = "u_codigo";
		}
		if (vReference == 'cmn_department') {
			vQuery = "name";
		}
		if (vReference == 'cmdb_model_category') {
			vQuery = "name";
		}
		if (vReference == 'cmdb_model') {
			vQuery = "name";
		}
		if (vReference == 'cmn_location') {
			vQuery = "name";
		}
		if (vReference == 'u_secciones') {
			vQuery = "u_name";
		}
		if (vReference == 'sys_user') {
			vQuery = "user_name";
		}
		
		//Busco la tabla segun vReference
		var gr = new GlideRecord(vReference);
		gr.addQuery(vQuery,vValor);
		gr.query();
		
		//Encuentro
		if (gr.next()) {
			var retorno = gr.getUniqueValue();
			return retorno;
		}
	}

 

Conclusiones

  • Como todo, el proceso es mejorable y hay muchas cosas por hacer, pero es un método bastante sencillo y fiable para darle al usuario una funcionalidad de actualización masiva de asset (podría ser realmente cualquier otra tabla), que no tiene que entrar en la interface UI y que le facilita su operación porque están muy acostumbrados al uso del Excel/CSV

 

Espero que os sea de utilidad, y como digo siempre, no he inventado nada, solo he reaprovechado lo que la propia comunidad comparte, modificado un poco allí, retocado aquí e implementado en nuestras instancias para obtener un resultado. Por eso, gracias por compartir y os animo a hacerlo!

PD: Si el artículo te ha sido de utilidad, te agradeceré lo marques como tal y lo compartas.

 

Version history
Last update:
‎02-28-2018 06:23 AM
Updated by: